Completed
Branch master (24c3eb)
by
unknown
34:49 queued 28:57
created
core/libraries/shortcodes/EE_Datetime_Shortcodes.lib.php 1 patch
Indentation   +59 added lines, -59 removed lines patch added patch discarded remove patch
@@ -15,77 +15,77 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Datetime_Shortcodes extends EE_Shortcodes
17 17
 {
18
-    /**
19
-     * @return void
20
-     */
21
-    protected function _init_props()
22
-    {
23
-        $this->label = esc_html__('Datetime Shortcodes', 'event_espresso');
24
-        $this->description = esc_html__('All shortcodes specific to datetime related data', 'event_espresso');
25
-        $this->_shortcodes = array(
26
-            '[DATETIME_START]' => esc_html__('The start date and time.', 'event_espresso'),
27
-            '[DATETIME_END]' => esc_html__('The end date and time.', 'event_espresso'),
28
-            '[DATETIME_TIMEZONE]' => esc_html__('The timezone for the date and time', 'event_espresso'),
29
-            '[DATE_START]' => esc_html__('The datetime start date.', 'event_espresso'),
30
-            '[DATE_END]' => esc_html__('The datetime end date.', 'event_espresso'),
31
-            '[TIME_START]' => esc_html__('The datetime start time.', 'event_espresso'),
32
-            '[TIME_END]' => esc_html__('The datetime end time.', 'event_espresso'),
33
-            '[ICAL_LINK_*]' => esc_html__(
34
-                'The datetime iCal link. The optional "link_text" attribute can be used to set custom text within the link (Default is "Add to iCal Calendar").',
35
-                'event_espresso'
36
-            ),
37
-        );
38
-    }
18
+	/**
19
+	 * @return void
20
+	 */
21
+	protected function _init_props()
22
+	{
23
+		$this->label = esc_html__('Datetime Shortcodes', 'event_espresso');
24
+		$this->description = esc_html__('All shortcodes specific to datetime related data', 'event_espresso');
25
+		$this->_shortcodes = array(
26
+			'[DATETIME_START]' => esc_html__('The start date and time.', 'event_espresso'),
27
+			'[DATETIME_END]' => esc_html__('The end date and time.', 'event_espresso'),
28
+			'[DATETIME_TIMEZONE]' => esc_html__('The timezone for the date and time', 'event_espresso'),
29
+			'[DATE_START]' => esc_html__('The datetime start date.', 'event_espresso'),
30
+			'[DATE_END]' => esc_html__('The datetime end date.', 'event_espresso'),
31
+			'[TIME_START]' => esc_html__('The datetime start time.', 'event_espresso'),
32
+			'[TIME_END]' => esc_html__('The datetime end time.', 'event_espresso'),
33
+			'[ICAL_LINK_*]' => esc_html__(
34
+				'The datetime iCal link. The optional "link_text" attribute can be used to set custom text within the link (Default is "Add to iCal Calendar").',
35
+				'event_espresso'
36
+			),
37
+		);
38
+	}
39 39
 
40 40
 
41
-    /**
42
-     * @param string $shortcode
43
-     * @return string
44
-     * @throws EE_Error
45
-     * @throws ReflectionException
46
-     */
47
-    protected function _parser($shortcode)
48
-    {
49
-        if (! $this->_data instanceof EE_Datetime) {
50
-            return ''; // get out cause we can only parse with the datetime object.
51
-        }
41
+	/**
42
+	 * @param string $shortcode
43
+	 * @return string
44
+	 * @throws EE_Error
45
+	 * @throws ReflectionException
46
+	 */
47
+	protected function _parser($shortcode)
48
+	{
49
+		if (! $this->_data instanceof EE_Datetime) {
50
+			return ''; // get out cause we can only parse with the datetime object.
51
+		}
52 52
 
53
-        switch ($shortcode) {
54
-            case '[DATETIME_START]':
55
-                return $this->_data->get_i18n_datetime('DTT_EVT_start');
53
+		switch ($shortcode) {
54
+			case '[DATETIME_START]':
55
+				return $this->_data->get_i18n_datetime('DTT_EVT_start');
56 56
 
57
-            case '[DATETIME_END]':
58
-                return $this->_data->get_i18n_datetime('DTT_EVT_end');
57
+			case '[DATETIME_END]':
58
+				return $this->_data->get_i18n_datetime('DTT_EVT_end');
59 59
 
60
-            case '[DATETIME_TIMEZONE]':
61
-                return $this->_data->get_timezone();
60
+			case '[DATETIME_TIMEZONE]':
61
+				return $this->_data->get_timezone();
62 62
 
63
-            case '[DATE_START]':
64
-                return $this->_data->get_i18n_datetime('DTT_EVT_start', get_option('date_format'));
63
+			case '[DATE_START]':
64
+				return $this->_data->get_i18n_datetime('DTT_EVT_start', get_option('date_format'));
65 65
 
66
-            case '[DATE_END]':
67
-                return $this->_data->get_i18n_datetime('DTT_EVT_end', get_option('date_format'));
66
+			case '[DATE_END]':
67
+				return $this->_data->get_i18n_datetime('DTT_EVT_end', get_option('date_format'));
68 68
 
69
-            case '[TIME_START]':
70
-                return $this->_data->get_i18n_datetime('DTT_EVT_start', get_option('time_format'));
69
+			case '[TIME_START]':
70
+				return $this->_data->get_i18n_datetime('DTT_EVT_start', get_option('time_format'));
71 71
 
72
-            case '[TIME_END]':
73
-                return $this->_data->get_i18n_datetime('DTT_EVT_end', get_option('time_format'));
74
-        }
72
+			case '[TIME_END]':
73
+				return $this->_data->get_i18n_datetime('DTT_EVT_end', get_option('time_format'));
74
+		}
75 75
 
76
-        if (strpos($shortcode, '[ICAL_LINK_*') !== false) {
77
-            $attrs = $this->_get_shortcode_attrs($shortcode);
76
+		if (strpos($shortcode, '[ICAL_LINK_*') !== false) {
77
+			$attrs = $this->_get_shortcode_attrs($shortcode);
78 78
 
79
-            $link_text = empty($attrs['link_text'])
80
-                ? esc_html__('Add to iCal Calendar', 'event_espresso')
81
-                : $attrs['link_text'];
79
+			$link_text = empty($attrs['link_text'])
80
+				? esc_html__('Add to iCal Calendar', 'event_espresso')
81
+				: $attrs['link_text'];
82 82
 
83
-            $URL = add_query_arg(['ee' => 'download_ics_file', 'ics_id' => $this->_data->ID()], site_url());
84
-            $URL = esc_url_raw(str_replace('http://', 'https://', $URL));
83
+			$URL = add_query_arg(['ee' => 'download_ics_file', 'ics_id' => $this->_data->ID()], site_url());
84
+			$URL = esc_url_raw(str_replace('http://', 'https://', $URL));
85 85
 
86
-            return '<a class="ee-ical" href="' . $URL . '">' . $link_text . '</a>';
87
-        }
86
+			return '<a class="ee-ical" href="' . $URL . '">' . $link_text . '</a>';
87
+		}
88 88
 
89
-        return '';
90
-    }
89
+		return '';
90
+	}
91 91
 }
Please login to merge, or discard this patch.
line_item_display/EE_Receipt_Line_Item_Display_Strategy.strategy.php 1 patch
Indentation   +57 added lines, -58 removed lines patch added patch discarded remove patch
@@ -10,90 +10,89 @@
 block discarded – undo
10 10
  * @copyright   (c) 2008-2014 Event Espresso  All Rights Reserved.
11 11
  * @license     https://eventespresso.com/support/terms-conditions/   * see Plugin Licensing *
12 12
  * @link        http://www.eventespresso.com
13
-
14 13
  */
15 14
  /**
16
- *
17
- * Class EE_Receipt_Line_Item_Display_Strategy
18
- *
19
- * Description
20
- *
21
- * @package         Event Espresso
22
- * @subpackage    core
23
- * @author              Brent Christensen
24
- *
25
- *
26
- */
15
+  *
16
+  * Class EE_Receipt_Line_Item_Display_Strategy
17
+  *
18
+  * Description
19
+  *
20
+  * @package         Event Espresso
21
+  * @subpackage    core
22
+  * @author              Brent Christensen
23
+  *
24
+  *
25
+  */
27 26
 
28 27
 class EE_Receipt_Line_Item_Display_Strategy implements EEI_Line_Item_Display
29 28
 {
30
-    /**
31
-     * @param EE_Line_Item $line_item
32
-     * @param array        $options
33
-     * @return mixed
34
-     */
35
-    public function display_line_item(EE_Line_Item $line_item, $options = array())
36
-    {
29
+	/**
30
+	 * @param EE_Line_Item $line_item
31
+	 * @param array        $options
32
+	 * @return mixed
33
+	 */
34
+	public function display_line_item(EE_Line_Item $line_item, $options = array())
35
+	{
37 36
 
38
-        $html = '';
39
-        // set some default options and merge with incoming
40
-        $default_options = array(
41
-            'show_desc' => true,
42
-            'odd' => false
43
-        );
44
-        $options = array_merge($default_options, (array) $options);
45
-        switch ($line_item->type()) {
46
-            case EEM_Line_Item::type_total:
47
-                // loop thru children
48
-                foreach ($line_item->children() as $child_line_item) {
49
-                    // recursively feed children back into this method
37
+		$html = '';
38
+		// set some default options and merge with incoming
39
+		$default_options = array(
40
+			'show_desc' => true,
41
+			'odd' => false
42
+		);
43
+		$options = array_merge($default_options, (array) $options);
44
+		switch ($line_item->type()) {
45
+			case EEM_Line_Item::type_total:
46
+				// loop thru children
47
+				foreach ($line_item->children() as $child_line_item) {
48
+					// recursively feed children back into this method
50 49
 //                  $html .= $this->display_line_item( $child_line_item, $options );
51
-                }
50
+				}
52 51
 //              $html .= $this->_separator_row( $options );
53 52
 //              $html .= $this->_total_row( $line_item, esc_html__('Total', 'event_espresso'), $options );
54
-                break;
53
+				break;
55 54
 
56 55
 
57
-            case EEM_Line_Item::type_sub_total:
58
-                // loop thru children
59
-                foreach ($line_item->children() as $child_line_item) {
60
-                    // recursively feed children back into this method
56
+			case EEM_Line_Item::type_sub_total:
57
+				// loop thru children
58
+				foreach ($line_item->children() as $child_line_item) {
59
+					// recursively feed children back into this method
61 60
 //                  $html .= $this->display_line_item( $child_line_item, $options );
62
-                }
61
+				}
63 62
 //              $html .= $this->_total_row( $line_item, esc_html__('Sub-Total', 'event_espresso'), $options );
64
-                break;
63
+				break;
65 64
 
66 65
 
67
-            case EEM_Line_Item::type_tax_sub_total:
68
-                // loop thru children
69
-                foreach ($line_item->children() as $child_line_item) {
70
-                    // recursively feed children back into this method
66
+			case EEM_Line_Item::type_tax_sub_total:
67
+				// loop thru children
68
+				foreach ($line_item->children() as $child_line_item) {
69
+					// recursively feed children back into this method
71 70
 //                  $html .= $this->display_line_item( $child_line_item, $options );
72
-                }
71
+				}
73 72
 //              $html .= $this->_total_row( $line_item, esc_html__('Tax Total', 'event_espresso'), $options );
74
-                break;
73
+				break;
75 74
 
76 75
 
77
-            case EEM_Line_Item::type_line_item:
78
-                // item row
76
+			case EEM_Line_Item::type_line_item:
77
+				// item row
79 78
 //              $html .= $this->_item_row( $line_item, $options );
80
-                // got any kids?
81
-                foreach ($line_item->children() as $child_line_item) {
79
+				// got any kids?
80
+				foreach ($line_item->children() as $child_line_item) {
82 81
 //                  $this->display_line_item( $child_line_item, $options );
83
-                }
84
-                break;
82
+				}
83
+				break;
85 84
 
86 85
 
87
-            case EEM_Line_Item::type_sub_line_item:
86
+			case EEM_Line_Item::type_sub_line_item:
88 87
 //              $html .= $this->_sub_item_row( $line_item, $options );
89
-                break;
88
+				break;
90 89
 
91 90
 
92
-            case EEM_Line_Item::type_tax:
91
+			case EEM_Line_Item::type_tax:
93 92
 //              $html .= $this->_tax_row( $line_item, $options );
94
-                break;
95
-        }
93
+				break;
94
+		}
96 95
 
97
-        return $html;
98
-    }
96
+		return $html;
97
+	}
99 98
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/RestIncomingQueryParamMetadata.php 1 patch
Indentation   +788 added lines, -788 removed lines patch added patch discarded remove patch
@@ -30,794 +30,794 @@
 block discarded – undo
30 30
  */
31 31
 class RestIncomingQueryParamMetadata
32 32
 {
33
-    private string $query_param_key;
34
-
35
-    private $query_param_value;
36
-
37
-    private RestIncomingQueryParamContext $context;
38
-
39
-    private ?EE_Model_Field_Base $field;
40
-
41
-    /**
42
-     * @var string same as $query_param_key but has the * and anything after it removed
43
-     */
44
-    private string $query_param_key_sans_stars;
45
-
46
-    /**
47
-     * @var string for timezone or timezone offset
48
-     */
49
-    private string $timezone;
50
-
51
-    /**
52
-     * @var bool if the field in $query_param_key is for a GMT field (eg `EVT_modified_gmt`)
53
-     */
54
-    private bool $is_gmt_field = false;
55
-
56
-
57
-    /**
58
-     * RestIncomingQueryParamMetadata constructor.
59
-     * You probably want to call
60
-     *
61
-     * @param string                        $query_param_key
62
-     * @param mixed                         $query_param_value
63
-     * @param RestIncomingQueryParamContext $context
64
-     * @throws EE_Error
65
-     * @throws ReflectionException
66
-     */
67
-    public function __construct(string $query_param_key, $query_param_value, RestIncomingQueryParamContext $context)
68
-    {
69
-        $this->query_param_key   = $query_param_key;
70
-        $this->query_param_value = $query_param_value;
71
-        $this->context           = $context;
72
-        $this->determineFieldAndTimezone();
73
-    }
74
-
75
-
76
-    /**
77
-     * Gets the query parameter key. This may have been modified (see setQueryParamValue())
78
-     *
79
-     * @return string
80
-     */
81
-    public function getQueryParamKey(): string
82
-    {
83
-        return $this->query_param_key;
84
-    }
85
-
86
-
87
-    /**
88
-     * Modifies the query parameter key passed in (Eg this is done when rewriting the simplified specified operator REST
89
-     * query parameters into the legacy structure)
90
-     *
91
-     * @param string|array|int|float $query_param_value
92
-     */
93
-    private function setQueryParamValue($query_param_value)
94
-    {
95
-        $this->query_param_value = $query_param_value;
96
-    }
97
-
98
-
99
-    /**
100
-     * Gets the original query parameter value passed in.
101
-     *
102
-     * @return mixed
103
-     */
104
-    public function getQueryParamValue()
105
-    {
106
-        return $this->query_param_value;
107
-    }
108
-
109
-
110
-    /**
111
-     * Gets the context object.
112
-     *
113
-     * @return RestIncomingQueryParamContext
114
-     */
115
-    public function getContext(): RestIncomingQueryParamContext
116
-    {
117
-        return $this->context;
118
-    }
119
-
120
-
121
-    /**
122
-     * Sets the query parameter key. This may be used to rewrite a key into its non-GMT alternative.
123
-     *
124
-     * @param string $query_param_key
125
-     */
126
-    private function setQueryParamKey(string $query_param_key)
127
-    {
128
-        $this->query_param_key = $query_param_key;
129
-    }
130
-
131
-
132
-    /**
133
-     * Gets the field the query parameter key indicated. This may be null (in cases where the query parameter key
134
-     * did not indicate a field, eg if it were `OR`).
135
-     *
136
-     * @return EE_Model_Field_Base|null
137
-     */
138
-    public function getField(): ?EE_Model_Field_Base
139
-    {
140
-        return $this->field;
141
-    }
142
-
143
-
144
-    /**
145
-     * Gets the query parameter key (with the star and everything afterwards removed).
146
-     *
147
-     * @return string
148
-     */
149
-    public function getQueryParamKeySansStars(): string
150
-    {
151
-        return $this->query_param_key_sans_stars;
152
-    }
153
-
154
-
155
-    /**
156
-     * Gets the timezone associated with this model (the site timezone, except for GMT datetime fields).
157
-     *
158
-     * @return string
159
-     */
160
-    public function getTimezone(): string
161
-    {
162
-        return $this->timezone;
163
-    }
164
-
165
-
166
-    /**
167
-     * Returns whether this is a GMT field
168
-     *
169
-     * @return bool
170
-     */
171
-    public function isGmtField(): bool
172
-    {
173
-        return $this->is_gmt_field;
174
-    }
175
-
176
-
177
-    /**
178
-     * Sets the field indicated by the query parameter key (might be null).
179
-     *
180
-     * @param EE_Model_Field_Base|null $field
181
-     */
182
-    private function setField(EE_Model_Field_Base $field = null)
183
-    {
184
-        $this->field = $field;
185
-    }
186
-
187
-
188
-    /**
189
-     * Sets the query parameter key-with-stars-removed.
190
-     *
191
-     * @param string $query_param_key_sans_stars
192
-     */
193
-    private function setQueryParamKeySansStars(string $query_param_key_sans_stars)
194
-    {
195
-        $this->query_param_key_sans_stars = $query_param_key_sans_stars;
196
-    }
197
-
198
-
199
-    /**
200
-     * Sets the timezone (this could be a timezone offset string).
201
-     *
202
-     * @param string $timezone
203
-     */
204
-    private function setTimezone(string $timezone)
205
-    {
206
-        $this->timezone = $timezone;
207
-    }
208
-
209
-
210
-    /**
211
-     * @param bool|int|string|null $is_gmt_field
212
-     */
213
-    private function setIsGmtField($is_gmt_field)
214
-    {
215
-        $this->is_gmt_field = filter_var($is_gmt_field, FILTER_VALIDATE_BOOLEAN);
216
-    }
217
-
218
-
219
-    /**
220
-     * Determines what field, query param name, and query param name without stars, and timezone to use.
221
-     *
222
-     * @return void {
223
-     * @throws EE_Error
224
-     * @throws InvalidDataTypeException
225
-     * @throws InvalidInterfaceException
226
-     * @throws InvalidArgumentException
227
-     * @throws ReflectionException
228
-     * @throws Exception
229
-     * @since 4.9.72.p
230
-     * @type EE_Model_Field_Base $field
231
-     */
232
-    private function determineFieldAndTimezone()
233
-    {
234
-        $this->setQueryParamKeySansStars(
235
-            ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
236
-                $this->getQueryParamKey()
237
-            )
238
-        );
239
-        $this->setField(
240
-            ModelDataTranslator::deduceFieldFromQueryParam(
241
-                $this->getQueryParamKeySansStars(),
242
-                $this->getContext()->getModel()
243
-            )
244
-        );
245
-        // double-check is it a *_gmt field?
246
-        if (
247
-            ! $this->getField() instanceof EE_Model_Field_Base
248
-            && ModelDataTranslator::isGmtDateFieldName($this->getQueryParamKeySansStars())
249
-        ) {
250
-            // yep, take off '_gmt', and find the field
251
-            $this->setQueryParamKey(ModelDataTranslator::removeGmtFromFieldName($this->getQueryParamKeySansStars()));
252
-            $this->setField(
253
-                ModelDataTranslator::deduceFieldFromQueryParam(
254
-                    $this->getQueryParamKey(),
255
-                    $this->context->getModel()
256
-                )
257
-            );
258
-            $this->setTimezone('UTC');
259
-            $this->setIsGmtField(true);
260
-        } elseif ($this->getField() instanceof EE_Datetime_Field) {
261
-            // so it's not a GMT field. Set the timezone on the model to the default
262
-            $this->setTimezone(EEH_DTT_Helper::get_valid_timezone_string());
263
-        } else {
264
-            // just keep using what's already set for the timezone
265
-            $this->setTimezone($this->context->getModel()->get_timezone());
266
-        }
267
-        $this->assertOnlyAdminCanReadPasswordFields();
268
-    }
269
-
270
-
271
-    /**
272
-     * Throws an exception if a non-admin is trying to query by password.
273
-     *
274
-     * @throws RestException
275
-     * @since 4.9.74.p
276
-     */
277
-    private function assertOnlyAdminCanReadPasswordFields()
278
-    {
279
-        if (
280
-            $this->getField() instanceof EE_Password_Field
281
-            && ! current_user_can(EE_Restriction_Generator_Base::get_default_restrictions_cap())
282
-        ) {
283
-            // only full admins can query by password. sorry bub!
284
-            throw new RestException(
285
-                'only_admins_can_query_by_password',
286
-                // @codingStandardsIgnoreStart
287
-                esc_html__(
288
-                    'You attempted to filter by a password field without the needed privileges. Only a full admin is allowed to do that.',
289
-                    'event_espresso'
290
-                ),
291
-                // @codingStandardsIgnoreEnd
292
-                [
293
-                    'status' => 403,
294
-                ]
295
-            );
296
-        }
297
-    }
298
-
299
-
300
-    /**
301
-     * Given a ton of input, determines the value to use for the models.
302
-     *
303
-     * @return mixed
304
-     * @throws DomainException
305
-     * @throws EE_Error
306
-     * @throws RestException
307
-     * @throws DomainException
308
-     * @since 4.9.72.p
309
-     */
310
-    public function determineConditionsQueryParameterValue()
311
-    {
312
-        if ($this->valueIsArrayDuringRead()) {
313
-            return $this->determineModelValueGivenRestInputArray();
314
-        }
315
-        return ModelDataTranslator::prepareFieldValueFromJson(
316
-            $this->getField(),
317
-            $this->getQueryParamValue(),
318
-            $this->getContext()->getRequestedVersion(),
319
-            $this->getTimezone()
320
-        );
321
-    }
322
-
323
-
324
-    /**
325
-     * Given that the array value provided was itself an array, handles finding the correct value to pass to the model.
326
-     *
327
-     * @return array|null
328
-     * @throws RestException
329
-     * @throws EE_Error
330
-     * @since 4.9.72.p
331
-     * @noinspection PhpStatementHasEmptyBodyInspection
332
-     */
333
-    private function determineModelValueGivenRestInputArray(): ?array
334
-    {
335
-        $this->transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax();
336
-        // did they specify an operator?
337
-        if ($this->valueIsLegacySpecifiedOperator()) {
338
-            $query_param_value = $this->getQueryParamValue();
339
-            $sub_array_key     = $query_param_value[0];
340
-            $translated_value  = [$sub_array_key];
341
-            if ($this->operatorIsNAry($sub_array_key)) {
342
-                $translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
343
-            } elseif ($this->operatorIsTernary($sub_array_key)) {
344
-                $translated_value[] = [
345
-                    $this->prepareValuesFromJson($query_param_value[1][0]),
346
-                    $this->prepareValuesFromJson($query_param_value[1][1]),
347
-                ];
348
-            } elseif ($this->operatorIsLike($sub_array_key)) {
349
-                // we want to leave this value mostly-as-is (eg don't force it to be a float
350
-                // or a boolean or an enum value. Leave it as-is with wildcards etc)
351
-                // but do verify it at least doesn't have any serialized data
352
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
353
-                $translated_value[] = $query_param_value[1];
354
-            } elseif ($this->operatorIsUnary($sub_array_key)) {
355
-                // no arguments should have been provided, so don't look for any
356
-            } elseif ($this->operatorIsBinary($sub_array_key)) {
357
-                // it's a valid operator, but none of the exceptions. Treat it normally.
358
-                $translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
359
-            } else {
360
-                // so they provided a valid operator, but wrong number of arguments
361
-                $this->throwWrongNumberOfArgsExceptionIfDebugging($sub_array_key);
362
-                $translated_value = null;
363
-            }
364
-        } else {
365
-            // so they didn't provide a valid operator
366
-            // if we aren't in debug mode, then just try our best to fulfill the user's request
367
-            $this->throwInvalidOperatorExceptionIfDebugging();
368
-            $translated_value = null;
369
-        }
370
-        return $translated_value;
371
-    }
372
-
373
-
374
-    /**
375
-     * Returns if this request is a "read" request and the value provided was an array.
376
-     * This will indicate is such things as `array('<', 123)` and `array('IN', array(1,2,3))` are acceptable or not.
377
-     *
378
-     * @return bool
379
-     * @since 4.9.72.p
380
-     */
381
-    private function valueIsArrayDuringRead(): bool
382
-    {
383
-        return ! $this->getContext()->isWriting() && is_array($this->getQueryParamValue());
384
-    }
385
-
386
-
387
-    /**
388
-     * Returns if the value provided was an associative array (we should have already verified it's an array of some
389
-     * sort). If the value is an associative array, it had better be in the simplified specified operator structure.
390
-     *
391
-     * @return bool
392
-     * @since 4.9.72.p
393
-     */
394
-    private function valueIsAssociativeArray(): bool
395
-    {
396
-        return ! EEH_Array::is_array_numerically_and_sequentially_indexed((array) $this->getQueryParamValue());
397
-    }
398
-
399
-
400
-    /**
401
-     * Checks if the array value is itself an array that fits into the simplified specified operator structure
402
-     * (eg ["!=" => 123]).
403
-     *
404
-     * @return bool
405
-     * @since 4.9.72.p
406
-     */
407
-    private function valueIsSimplifiedSpecifiedOperator(): bool
408
-    {
409
-        return count($this->getQueryParamValue()) === 1
410
-            && array_key_exists(
411
-                key($this->getQueryParamValue()),
412
-                $this->getContext()->getModel()->valid_operators()
413
-            );
414
-    }
415
-
416
-
417
-    /**
418
-     * Throws an exception if the sub-value is an array (eg ["!=" => []). It needs to just be a string,
419
-     * of either comma-separated-values, or a JSON array.
420
-     *
421
-     * @param $sub_array_key
422
-     * @param $sub_array_value
423
-     * @throws RestException
424
-     * @since 4.9.72.p
425
-     */
426
-    private function assertSubValueIsntArray($sub_array_key, $sub_array_value)
427
-    {
428
-        if (is_array($sub_array_value) && EED_Core_Rest_Api::debugMode()) {
429
-            throw new RestException(
430
-                'csv_or_json_string_only',
431
-                sprintf(
432
-                /* translators: 1: variable name*/
433
-                    esc_html__(
434
-                        'The value provided for the operator "%1$s" should be comma-separated value string or a JSON array.',
435
-                        'event_espresso'
436
-                    ),
437
-                    $sub_array_key
438
-                ),
439
-                [
440
-                    'status' => 400,
441
-                ]
442
-            );
443
-        }
444
-    }
445
-
446
-
447
-    /**
448
-     * Determines if the sub-array key is an operator taking 3 or more operators.
449
-     *
450
-     * @param $sub_array_key
451
-     * @return bool
452
-     * @since 4.9.72.p
453
-     */
454
-    private function subArrayKeyIsNonBinaryOperator($sub_array_key): bool
455
-    {
456
-        return array_key_exists(
457
-            $sub_array_key,
458
-            array_merge(
459
-                $this->getContext()->getModel()->valid_in_style_operators(),
460
-                $this->getContext()->getModel()->valid_between_style_operators()
461
-            )
462
-        );
463
-    }
464
-
465
-
466
-    /**
467
-     * Given that the $sub_array_key is a string, checks if it's an operator taking only 1 argument.
468
-     *
469
-     * @param string $sub_array_key
470
-     * @return bool
471
-     * @since 4.9.72.p
472
-     */
473
-    private function subArrayKeyIsUnaryOperator(string $sub_array_key): bool
474
-    {
475
-        return array_key_exists(
476
-            $sub_array_key,
477
-            $this->getContext()->getModel()->valid_null_style_operators()
478
-        );
479
-    }
480
-
481
-
482
-    /**
483
-     * Parses the $sub_array_value string into an array (given it could either be a comma-separated-list or a JSON
484
-     * array). eg `"1,2,3"` or `"[1,2,3]"` into `array(1,2,3)`.
485
-     *
486
-     * @param $sub_array_value
487
-     * @return array|mixed|object
488
-     * @since 4.9.72.p
489
-     */
490
-    private function extractQuickStyleSpecifiedOperatorValue($sub_array_value)
491
-    {
492
-        // the value should be JSON or CSV
493
-        $values = json_decode($sub_array_value);
494
-        if (! is_array($values)) {
495
-            $values = array_filter(
496
-                array_map(
497
-                    'trim',
498
-                    explode(
499
-                        ',',
500
-                        $sub_array_value
501
-                    )
502
-                )
503
-            );
504
-        }
505
-        return $values;
506
-    }
507
-
508
-
509
-    /**
510
-     * Throws an exception if the value isn't a simplified specified operator (only called when we expect that).
511
-     *
512
-     * @throws RestException
513
-     * @since 4.9.72.p
514
-     */
515
-    private function assertSimplifiedSpecifiedOperator()
516
-    {
517
-        if (! $this->valueIsSimplifiedSpecifiedOperator() && EED_Core_Rest_Api::debugMode()) {
518
-            throw new RestException(
519
-                'numerically_indexed_array_of_values_only',
520
-                sprintf(
521
-                /* translators: 1: variable name*/
522
-                    esc_html__(
523
-                        'The array provided for the parameter "%1$s" should be numerically indexed.',
524
-                        'event_espresso'
525
-                    ),
526
-                    $this->getQueryParamKey()
527
-                ),
528
-                [
529
-                    'status' => 400,
530
-                ]
531
-            );
532
-        }
533
-    }
534
-
535
-
536
-    /**
537
-     * If query_param_value were in the simplified specific operator structure, change it into the legacy structure.
538
-     *
539
-     * @throws RestException
540
-     * @since 4.9.72.p
541
-     */
542
-    private function transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax()
543
-    {
544
-        if ($this->valueIsAssociativeArray()) {
545
-            $this->assertSimplifiedSpecifiedOperator();
546
-            $query_param_value = $this->getQueryParamValue();
547
-            $sub_array_value   = reset($query_param_value);
548
-            $sub_array_key     = key($query_param_value);
549
-            $this->assertSubValueIsntArray($sub_array_key, $sub_array_value);
550
-            // they're doing something like "&where[EVT_ID][IN]=1,2,3" or "&where[EVT_ID][>]=5"
551
-            if ($this->subArrayKeyIsNonBinaryOperator($sub_array_key)) {
552
-                $this->setQueryParamValue(
553
-                    [
554
-                        $sub_array_key,
555
-                        $this->extractQuickStyleSpecifiedOperatorValue($sub_array_value),
556
-                    ]
557
-                );
558
-            } elseif ($this->subArrayKeyIsUnaryOperator($sub_array_key)) {
559
-                $this->setQueryParamValue([$sub_array_key]);
560
-            } else {
561
-                $this->setQueryParamValue([$sub_array_key, $sub_array_value]);
562
-            }
563
-        }
564
-    }
565
-
566
-
567
-    /**
568
-     * Returns true is the value is an array using the legacy structure to specify the operator. Eg `array('!=',123)`.
569
-     *
570
-     * @return bool
571
-     * @since 4.9.72.p
572
-     */
573
-    private function valueIsLegacySpecifiedOperator(): bool
574
-    {
575
-        $valid_operators   = $this->getContext()->getModel()->valid_operators();
576
-        $query_param_value = $this->getQueryParamValue();
577
-        return isset($query_param_value[0])
578
-            && isset($valid_operators[ $query_param_value[0] ]);
579
-    }
580
-
581
-
582
-    /**
583
-     * Returns true if the value specified operator accepts arbitrary number of arguments, like "IN".
584
-     *
585
-     * @param $operator
586
-     * @return bool
587
-     * @since 4.9.72.p
588
-     */
589
-    private function operatorIsNAry($operator): bool
590
-    {
591
-        $valueArray = $this->getQueryParamValue();
592
-        return array_key_exists(
593
-            $operator,
594
-            $this->getContext()->getModel()->valid_in_style_operators()
595
-        )
596
-            && isset($valueArray[1])
597
-            && is_array($valueArray[1])
598
-            && ! isset($valueArray[2]);
599
-    }
600
-
601
-
602
-    /**
603
-     * Returns true if the operator accepts 3 arguments (eg "BETWEEN").
604
-     * So we're looking for a value that looks like
605
-     * `array('BETWEEN', array('2015-01-01T00:00:00', '2016-01-01T00:00:00'))`.
606
-     *
607
-     * @param $operator
608
-     * @return bool
609
-     * @since 4.9.72.p
610
-     */
611
-    private function operatorIsTernary($operator): bool
612
-    {
613
-        $query_param_value = $this->getQueryParamValue();
614
-        return array_key_exists($operator, $this->getContext()->getModel()->valid_between_style_operators())
615
-            && isset($query_param_value[1])
616
-            && is_array($query_param_value[1])
617
-            && isset($query_param_value[1][0], $query_param_value[1][1])
618
-            && ! isset($query_param_value[1][2])
619
-            && ! isset($query_param_value[2]);
620
-    }
621
-
622
-
623
-    /**
624
-     * Returns true if the operator is a similar to LIKE, indicating the value may have wildcards we should leave alone.
625
-     *
626
-     * @param $operator
627
-     * @return bool
628
-     * @since 4.9.72.p
629
-     */
630
-    private function operatorIsLike($operator): bool
631
-    {
632
-        $query_param_value = $this->getQueryParamValue();
633
-        return array_key_exists($operator, $this->getContext()->getModel()->valid_like_style_operators())
634
-            && isset($query_param_value[1])
635
-            && ! isset($query_param_value[2]);
636
-    }
637
-
638
-
639
-    /**
640
-     * Returns true if the operator only takes one argument (eg it's like `IS NULL`).
641
-     *
642
-     * @param $operator
643
-     * @return bool
644
-     * @since 4.9.72.p
645
-     */
646
-    private function operatorIsUnary($operator): bool
647
-    {
648
-        $query_param_value = $this->getQueryParamValue();
649
-        return array_key_exists($operator, $this->getContext()->getModel()->valid_null_style_operators())
650
-            && ! isset($query_param_value[1]);
651
-    }
652
-
653
-
654
-    /**
655
-     * Returns true if the operator specified is a binary operator (eg `=`, `!=`)
656
-     *
657
-     * @param $operator
658
-     * @return bool
659
-     * @since 4.9.72.p
660
-     */
661
-    private function operatorIsBinary($operator): bool
662
-    {
663
-        $query_param_value = $this->getQueryParamValue();
664
-        $model             = $this->getContext()->getModel();
665
-        return isset($query_param_value[1])
666
-            && ! isset($query_param_value[2])
667
-            && ! array_key_exists(
668
-                $operator,
669
-                array_merge(
670
-                    $model->valid_in_style_operators(),
671
-                    $model->valid_null_style_operators(),
672
-                    $model->valid_like_style_operators(),
673
-                    $model->valid_between_style_operators()
674
-                )
675
-            );
676
-    }
677
-
678
-
679
-    /**
680
-     * If we're debugging, throws an exception saying that the wrong number of arguments was provided.
681
-     *
682
-     * @param $operator
683
-     * @throws RestException
684
-     * @since 4.9.72.p
685
-     */
686
-    private function throwWrongNumberOfArgsExceptionIfDebugging($operator)
687
-    {
688
-        if (EED_Core_Rest_Api::debugMode()) {
689
-            throw new RestException(
690
-                'wrong_number_of_arguments',
691
-                sprintf(
692
-                    esc_html__(
693
-                        'The operator you provided, "%1$s" had the wrong number of arguments',
694
-                        'event_espresso'
695
-                    ),
696
-                    $operator
697
-                ),
698
-                [
699
-                    'status' => 400,
700
-                ]
701
-            );
702
-        }
703
-    }
704
-
705
-
706
-    /**
707
-     * Wrapper for ModelDataTranslator::prepareFieldValuesFromJson(), just a tad more DRY.
708
-     *
709
-     * @param $value
710
-     * @return mixed
711
-     * @throws RestException
712
-     * @throws EE_Error
713
-     * @since 4.9.72.p
714
-     */
715
-    private function prepareValuesFromJson($value)
716
-    {
717
-        return ModelDataTranslator::prepareFieldValuesFromJson(
718
-            $this->getField(),
719
-            $value,
720
-            $this->getContext()->getRequestedVersion(),
721
-            $this->getTimezone()
722
-        );
723
-    }
724
-
725
-
726
-    /**
727
-     * Throws an exception if an invalid operator was specified and we're debugging.
728
-     *
729
-     * @throws RestException
730
-     * @since 4.9.72.p
731
-     */
732
-    private function throwInvalidOperatorExceptionIfDebugging()
733
-    {
734
-        // so they didn't provide a valid operator
735
-        if (EED_Core_Rest_Api::debugMode()) {
736
-            throw new RestException(
737
-                'invalid_operator',
738
-                sprintf(
739
-                    esc_html__(
740
-                        'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
741
-                        'event_espresso'
742
-                    ),
743
-                    $this->getQueryParamKey(),
744
-                    $this->getQueryParamValue()
745
-                ),
746
-                [
747
-                    'status' => 400,
748
-                ]
749
-            );
750
-        }
751
-    }
752
-
753
-
754
-    /**
755
-     * Returns true if the query_param_key was a logic query parameter, eg `OR`, `AND`, `NOT`, `OR*`, etc.
756
-     *
757
-     * @return bool
758
-     * @since 4.9.72.p
759
-     */
760
-    private function isLogicQueryParam(): bool
761
-    {
762
-        return in_array($this->getQueryParamKeySansStars(), $this->getContext()->getModel()->logic_query_param_keys());
763
-    }
764
-
765
-
766
-    /**
767
-     * If the query param isn't for a field, it must be a nested query parameter which requires different logic.
768
-     *
769
-     * @return array
770
-     * @throws DomainException
771
-     * @throws EE_Error
772
-     * @throws RestException
773
-     * @throws InvalidDataTypeException
774
-     * @throws InvalidInterfaceException
775
-     * @throws InvalidArgumentException
776
-     * @since 4.9.72.p
777
-     */
778
-    public function determineNestedConditionQueryParameters(): array
779
-    {
780
-        // so this param doesn't correspond to a field eh?
781
-        if ($this->getContext()->isWriting()) {
782
-            // always tell API clients about invalid parameters when they're creating data. Otherwise,
783
-            // they are probably going to create invalid data
784
-            throw new RestException(
785
-                'invalid_field',
786
-                sprintf(
787
-                /* translators: 1: variable name */
788
-                    esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
789
-                    $this->getQueryParamKey()
790
-                )
791
-            );
792
-        }
793
-        // so it's not for a field, is it a logic query param key?
794
-        if ($this->isLogicQueryParam()) {
795
-            return ModelDataTranslator::prepareConditionsQueryParamsForModels(
796
-                $this->getQueryParamValue(),
797
-                $this->getContext()->getModel(),
798
-                $this->getContext()->getRequestedVersion()
799
-            );
800
-        }
801
-        if (EED_Core_Rest_Api::debugMode()) {
802
-            // only tell API clients they got it wrong if we're in debug mode
803
-            // otherwise try our best ot fulfill their request by ignoring this invalid data
804
-            throw new RestException(
805
-                'invalid_parameter',
806
-                sprintf(
807
-                /* translators: 1: variable name */
808
-                    esc_html__(
809
-                        'You provided an invalid parameter, with key "%1$s"',
810
-                        'event_espresso'
811
-                    ),
812
-                    $this->getQueryParamKey()
813
-                ),
814
-                array(
815
-                    'status' => 400,
816
-                )
817
-            );
818
-        }
819
-        return [];
820
-    }
33
+	private string $query_param_key;
34
+
35
+	private $query_param_value;
36
+
37
+	private RestIncomingQueryParamContext $context;
38
+
39
+	private ?EE_Model_Field_Base $field;
40
+
41
+	/**
42
+	 * @var string same as $query_param_key but has the * and anything after it removed
43
+	 */
44
+	private string $query_param_key_sans_stars;
45
+
46
+	/**
47
+	 * @var string for timezone or timezone offset
48
+	 */
49
+	private string $timezone;
50
+
51
+	/**
52
+	 * @var bool if the field in $query_param_key is for a GMT field (eg `EVT_modified_gmt`)
53
+	 */
54
+	private bool $is_gmt_field = false;
55
+
56
+
57
+	/**
58
+	 * RestIncomingQueryParamMetadata constructor.
59
+	 * You probably want to call
60
+	 *
61
+	 * @param string                        $query_param_key
62
+	 * @param mixed                         $query_param_value
63
+	 * @param RestIncomingQueryParamContext $context
64
+	 * @throws EE_Error
65
+	 * @throws ReflectionException
66
+	 */
67
+	public function __construct(string $query_param_key, $query_param_value, RestIncomingQueryParamContext $context)
68
+	{
69
+		$this->query_param_key   = $query_param_key;
70
+		$this->query_param_value = $query_param_value;
71
+		$this->context           = $context;
72
+		$this->determineFieldAndTimezone();
73
+	}
74
+
75
+
76
+	/**
77
+	 * Gets the query parameter key. This may have been modified (see setQueryParamValue())
78
+	 *
79
+	 * @return string
80
+	 */
81
+	public function getQueryParamKey(): string
82
+	{
83
+		return $this->query_param_key;
84
+	}
85
+
86
+
87
+	/**
88
+	 * Modifies the query parameter key passed in (Eg this is done when rewriting the simplified specified operator REST
89
+	 * query parameters into the legacy structure)
90
+	 *
91
+	 * @param string|array|int|float $query_param_value
92
+	 */
93
+	private function setQueryParamValue($query_param_value)
94
+	{
95
+		$this->query_param_value = $query_param_value;
96
+	}
97
+
98
+
99
+	/**
100
+	 * Gets the original query parameter value passed in.
101
+	 *
102
+	 * @return mixed
103
+	 */
104
+	public function getQueryParamValue()
105
+	{
106
+		return $this->query_param_value;
107
+	}
108
+
109
+
110
+	/**
111
+	 * Gets the context object.
112
+	 *
113
+	 * @return RestIncomingQueryParamContext
114
+	 */
115
+	public function getContext(): RestIncomingQueryParamContext
116
+	{
117
+		return $this->context;
118
+	}
119
+
120
+
121
+	/**
122
+	 * Sets the query parameter key. This may be used to rewrite a key into its non-GMT alternative.
123
+	 *
124
+	 * @param string $query_param_key
125
+	 */
126
+	private function setQueryParamKey(string $query_param_key)
127
+	{
128
+		$this->query_param_key = $query_param_key;
129
+	}
130
+
131
+
132
+	/**
133
+	 * Gets the field the query parameter key indicated. This may be null (in cases where the query parameter key
134
+	 * did not indicate a field, eg if it were `OR`).
135
+	 *
136
+	 * @return EE_Model_Field_Base|null
137
+	 */
138
+	public function getField(): ?EE_Model_Field_Base
139
+	{
140
+		return $this->field;
141
+	}
142
+
143
+
144
+	/**
145
+	 * Gets the query parameter key (with the star and everything afterwards removed).
146
+	 *
147
+	 * @return string
148
+	 */
149
+	public function getQueryParamKeySansStars(): string
150
+	{
151
+		return $this->query_param_key_sans_stars;
152
+	}
153
+
154
+
155
+	/**
156
+	 * Gets the timezone associated with this model (the site timezone, except for GMT datetime fields).
157
+	 *
158
+	 * @return string
159
+	 */
160
+	public function getTimezone(): string
161
+	{
162
+		return $this->timezone;
163
+	}
164
+
165
+
166
+	/**
167
+	 * Returns whether this is a GMT field
168
+	 *
169
+	 * @return bool
170
+	 */
171
+	public function isGmtField(): bool
172
+	{
173
+		return $this->is_gmt_field;
174
+	}
175
+
176
+
177
+	/**
178
+	 * Sets the field indicated by the query parameter key (might be null).
179
+	 *
180
+	 * @param EE_Model_Field_Base|null $field
181
+	 */
182
+	private function setField(EE_Model_Field_Base $field = null)
183
+	{
184
+		$this->field = $field;
185
+	}
186
+
187
+
188
+	/**
189
+	 * Sets the query parameter key-with-stars-removed.
190
+	 *
191
+	 * @param string $query_param_key_sans_stars
192
+	 */
193
+	private function setQueryParamKeySansStars(string $query_param_key_sans_stars)
194
+	{
195
+		$this->query_param_key_sans_stars = $query_param_key_sans_stars;
196
+	}
197
+
198
+
199
+	/**
200
+	 * Sets the timezone (this could be a timezone offset string).
201
+	 *
202
+	 * @param string $timezone
203
+	 */
204
+	private function setTimezone(string $timezone)
205
+	{
206
+		$this->timezone = $timezone;
207
+	}
208
+
209
+
210
+	/**
211
+	 * @param bool|int|string|null $is_gmt_field
212
+	 */
213
+	private function setIsGmtField($is_gmt_field)
214
+	{
215
+		$this->is_gmt_field = filter_var($is_gmt_field, FILTER_VALIDATE_BOOLEAN);
216
+	}
217
+
218
+
219
+	/**
220
+	 * Determines what field, query param name, and query param name without stars, and timezone to use.
221
+	 *
222
+	 * @return void {
223
+	 * @throws EE_Error
224
+	 * @throws InvalidDataTypeException
225
+	 * @throws InvalidInterfaceException
226
+	 * @throws InvalidArgumentException
227
+	 * @throws ReflectionException
228
+	 * @throws Exception
229
+	 * @since 4.9.72.p
230
+	 * @type EE_Model_Field_Base $field
231
+	 */
232
+	private function determineFieldAndTimezone()
233
+	{
234
+		$this->setQueryParamKeySansStars(
235
+			ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
236
+				$this->getQueryParamKey()
237
+			)
238
+		);
239
+		$this->setField(
240
+			ModelDataTranslator::deduceFieldFromQueryParam(
241
+				$this->getQueryParamKeySansStars(),
242
+				$this->getContext()->getModel()
243
+			)
244
+		);
245
+		// double-check is it a *_gmt field?
246
+		if (
247
+			! $this->getField() instanceof EE_Model_Field_Base
248
+			&& ModelDataTranslator::isGmtDateFieldName($this->getQueryParamKeySansStars())
249
+		) {
250
+			// yep, take off '_gmt', and find the field
251
+			$this->setQueryParamKey(ModelDataTranslator::removeGmtFromFieldName($this->getQueryParamKeySansStars()));
252
+			$this->setField(
253
+				ModelDataTranslator::deduceFieldFromQueryParam(
254
+					$this->getQueryParamKey(),
255
+					$this->context->getModel()
256
+				)
257
+			);
258
+			$this->setTimezone('UTC');
259
+			$this->setIsGmtField(true);
260
+		} elseif ($this->getField() instanceof EE_Datetime_Field) {
261
+			// so it's not a GMT field. Set the timezone on the model to the default
262
+			$this->setTimezone(EEH_DTT_Helper::get_valid_timezone_string());
263
+		} else {
264
+			// just keep using what's already set for the timezone
265
+			$this->setTimezone($this->context->getModel()->get_timezone());
266
+		}
267
+		$this->assertOnlyAdminCanReadPasswordFields();
268
+	}
269
+
270
+
271
+	/**
272
+	 * Throws an exception if a non-admin is trying to query by password.
273
+	 *
274
+	 * @throws RestException
275
+	 * @since 4.9.74.p
276
+	 */
277
+	private function assertOnlyAdminCanReadPasswordFields()
278
+	{
279
+		if (
280
+			$this->getField() instanceof EE_Password_Field
281
+			&& ! current_user_can(EE_Restriction_Generator_Base::get_default_restrictions_cap())
282
+		) {
283
+			// only full admins can query by password. sorry bub!
284
+			throw new RestException(
285
+				'only_admins_can_query_by_password',
286
+				// @codingStandardsIgnoreStart
287
+				esc_html__(
288
+					'You attempted to filter by a password field without the needed privileges. Only a full admin is allowed to do that.',
289
+					'event_espresso'
290
+				),
291
+				// @codingStandardsIgnoreEnd
292
+				[
293
+					'status' => 403,
294
+				]
295
+			);
296
+		}
297
+	}
298
+
299
+
300
+	/**
301
+	 * Given a ton of input, determines the value to use for the models.
302
+	 *
303
+	 * @return mixed
304
+	 * @throws DomainException
305
+	 * @throws EE_Error
306
+	 * @throws RestException
307
+	 * @throws DomainException
308
+	 * @since 4.9.72.p
309
+	 */
310
+	public function determineConditionsQueryParameterValue()
311
+	{
312
+		if ($this->valueIsArrayDuringRead()) {
313
+			return $this->determineModelValueGivenRestInputArray();
314
+		}
315
+		return ModelDataTranslator::prepareFieldValueFromJson(
316
+			$this->getField(),
317
+			$this->getQueryParamValue(),
318
+			$this->getContext()->getRequestedVersion(),
319
+			$this->getTimezone()
320
+		);
321
+	}
322
+
323
+
324
+	/**
325
+	 * Given that the array value provided was itself an array, handles finding the correct value to pass to the model.
326
+	 *
327
+	 * @return array|null
328
+	 * @throws RestException
329
+	 * @throws EE_Error
330
+	 * @since 4.9.72.p
331
+	 * @noinspection PhpStatementHasEmptyBodyInspection
332
+	 */
333
+	private function determineModelValueGivenRestInputArray(): ?array
334
+	{
335
+		$this->transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax();
336
+		// did they specify an operator?
337
+		if ($this->valueIsLegacySpecifiedOperator()) {
338
+			$query_param_value = $this->getQueryParamValue();
339
+			$sub_array_key     = $query_param_value[0];
340
+			$translated_value  = [$sub_array_key];
341
+			if ($this->operatorIsNAry($sub_array_key)) {
342
+				$translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
343
+			} elseif ($this->operatorIsTernary($sub_array_key)) {
344
+				$translated_value[] = [
345
+					$this->prepareValuesFromJson($query_param_value[1][0]),
346
+					$this->prepareValuesFromJson($query_param_value[1][1]),
347
+				];
348
+			} elseif ($this->operatorIsLike($sub_array_key)) {
349
+				// we want to leave this value mostly-as-is (eg don't force it to be a float
350
+				// or a boolean or an enum value. Leave it as-is with wildcards etc)
351
+				// but do verify it at least doesn't have any serialized data
352
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($query_param_value[1]);
353
+				$translated_value[] = $query_param_value[1];
354
+			} elseif ($this->operatorIsUnary($sub_array_key)) {
355
+				// no arguments should have been provided, so don't look for any
356
+			} elseif ($this->operatorIsBinary($sub_array_key)) {
357
+				// it's a valid operator, but none of the exceptions. Treat it normally.
358
+				$translated_value[] = $this->prepareValuesFromJson($query_param_value[1]);
359
+			} else {
360
+				// so they provided a valid operator, but wrong number of arguments
361
+				$this->throwWrongNumberOfArgsExceptionIfDebugging($sub_array_key);
362
+				$translated_value = null;
363
+			}
364
+		} else {
365
+			// so they didn't provide a valid operator
366
+			// if we aren't in debug mode, then just try our best to fulfill the user's request
367
+			$this->throwInvalidOperatorExceptionIfDebugging();
368
+			$translated_value = null;
369
+		}
370
+		return $translated_value;
371
+	}
372
+
373
+
374
+	/**
375
+	 * Returns if this request is a "read" request and the value provided was an array.
376
+	 * This will indicate is such things as `array('<', 123)` and `array('IN', array(1,2,3))` are acceptable or not.
377
+	 *
378
+	 * @return bool
379
+	 * @since 4.9.72.p
380
+	 */
381
+	private function valueIsArrayDuringRead(): bool
382
+	{
383
+		return ! $this->getContext()->isWriting() && is_array($this->getQueryParamValue());
384
+	}
385
+
386
+
387
+	/**
388
+	 * Returns if the value provided was an associative array (we should have already verified it's an array of some
389
+	 * sort). If the value is an associative array, it had better be in the simplified specified operator structure.
390
+	 *
391
+	 * @return bool
392
+	 * @since 4.9.72.p
393
+	 */
394
+	private function valueIsAssociativeArray(): bool
395
+	{
396
+		return ! EEH_Array::is_array_numerically_and_sequentially_indexed((array) $this->getQueryParamValue());
397
+	}
398
+
399
+
400
+	/**
401
+	 * Checks if the array value is itself an array that fits into the simplified specified operator structure
402
+	 * (eg ["!=" => 123]).
403
+	 *
404
+	 * @return bool
405
+	 * @since 4.9.72.p
406
+	 */
407
+	private function valueIsSimplifiedSpecifiedOperator(): bool
408
+	{
409
+		return count($this->getQueryParamValue()) === 1
410
+			&& array_key_exists(
411
+				key($this->getQueryParamValue()),
412
+				$this->getContext()->getModel()->valid_operators()
413
+			);
414
+	}
415
+
416
+
417
+	/**
418
+	 * Throws an exception if the sub-value is an array (eg ["!=" => []). It needs to just be a string,
419
+	 * of either comma-separated-values, or a JSON array.
420
+	 *
421
+	 * @param $sub_array_key
422
+	 * @param $sub_array_value
423
+	 * @throws RestException
424
+	 * @since 4.9.72.p
425
+	 */
426
+	private function assertSubValueIsntArray($sub_array_key, $sub_array_value)
427
+	{
428
+		if (is_array($sub_array_value) && EED_Core_Rest_Api::debugMode()) {
429
+			throw new RestException(
430
+				'csv_or_json_string_only',
431
+				sprintf(
432
+				/* translators: 1: variable name*/
433
+					esc_html__(
434
+						'The value provided for the operator "%1$s" should be comma-separated value string or a JSON array.',
435
+						'event_espresso'
436
+					),
437
+					$sub_array_key
438
+				),
439
+				[
440
+					'status' => 400,
441
+				]
442
+			);
443
+		}
444
+	}
445
+
446
+
447
+	/**
448
+	 * Determines if the sub-array key is an operator taking 3 or more operators.
449
+	 *
450
+	 * @param $sub_array_key
451
+	 * @return bool
452
+	 * @since 4.9.72.p
453
+	 */
454
+	private function subArrayKeyIsNonBinaryOperator($sub_array_key): bool
455
+	{
456
+		return array_key_exists(
457
+			$sub_array_key,
458
+			array_merge(
459
+				$this->getContext()->getModel()->valid_in_style_operators(),
460
+				$this->getContext()->getModel()->valid_between_style_operators()
461
+			)
462
+		);
463
+	}
464
+
465
+
466
+	/**
467
+	 * Given that the $sub_array_key is a string, checks if it's an operator taking only 1 argument.
468
+	 *
469
+	 * @param string $sub_array_key
470
+	 * @return bool
471
+	 * @since 4.9.72.p
472
+	 */
473
+	private function subArrayKeyIsUnaryOperator(string $sub_array_key): bool
474
+	{
475
+		return array_key_exists(
476
+			$sub_array_key,
477
+			$this->getContext()->getModel()->valid_null_style_operators()
478
+		);
479
+	}
480
+
481
+
482
+	/**
483
+	 * Parses the $sub_array_value string into an array (given it could either be a comma-separated-list or a JSON
484
+	 * array). eg `"1,2,3"` or `"[1,2,3]"` into `array(1,2,3)`.
485
+	 *
486
+	 * @param $sub_array_value
487
+	 * @return array|mixed|object
488
+	 * @since 4.9.72.p
489
+	 */
490
+	private function extractQuickStyleSpecifiedOperatorValue($sub_array_value)
491
+	{
492
+		// the value should be JSON or CSV
493
+		$values = json_decode($sub_array_value);
494
+		if (! is_array($values)) {
495
+			$values = array_filter(
496
+				array_map(
497
+					'trim',
498
+					explode(
499
+						',',
500
+						$sub_array_value
501
+					)
502
+				)
503
+			);
504
+		}
505
+		return $values;
506
+	}
507
+
508
+
509
+	/**
510
+	 * Throws an exception if the value isn't a simplified specified operator (only called when we expect that).
511
+	 *
512
+	 * @throws RestException
513
+	 * @since 4.9.72.p
514
+	 */
515
+	private function assertSimplifiedSpecifiedOperator()
516
+	{
517
+		if (! $this->valueIsSimplifiedSpecifiedOperator() && EED_Core_Rest_Api::debugMode()) {
518
+			throw new RestException(
519
+				'numerically_indexed_array_of_values_only',
520
+				sprintf(
521
+				/* translators: 1: variable name*/
522
+					esc_html__(
523
+						'The array provided for the parameter "%1$s" should be numerically indexed.',
524
+						'event_espresso'
525
+					),
526
+					$this->getQueryParamKey()
527
+				),
528
+				[
529
+					'status' => 400,
530
+				]
531
+			);
532
+		}
533
+	}
534
+
535
+
536
+	/**
537
+	 * If query_param_value were in the simplified specific operator structure, change it into the legacy structure.
538
+	 *
539
+	 * @throws RestException
540
+	 * @since 4.9.72.p
541
+	 */
542
+	private function transformSimplifiedSpecifiedOperatorSyntaxIntoStandardSyntax()
543
+	{
544
+		if ($this->valueIsAssociativeArray()) {
545
+			$this->assertSimplifiedSpecifiedOperator();
546
+			$query_param_value = $this->getQueryParamValue();
547
+			$sub_array_value   = reset($query_param_value);
548
+			$sub_array_key     = key($query_param_value);
549
+			$this->assertSubValueIsntArray($sub_array_key, $sub_array_value);
550
+			// they're doing something like "&where[EVT_ID][IN]=1,2,3" or "&where[EVT_ID][>]=5"
551
+			if ($this->subArrayKeyIsNonBinaryOperator($sub_array_key)) {
552
+				$this->setQueryParamValue(
553
+					[
554
+						$sub_array_key,
555
+						$this->extractQuickStyleSpecifiedOperatorValue($sub_array_value),
556
+					]
557
+				);
558
+			} elseif ($this->subArrayKeyIsUnaryOperator($sub_array_key)) {
559
+				$this->setQueryParamValue([$sub_array_key]);
560
+			} else {
561
+				$this->setQueryParamValue([$sub_array_key, $sub_array_value]);
562
+			}
563
+		}
564
+	}
565
+
566
+
567
+	/**
568
+	 * Returns true is the value is an array using the legacy structure to specify the operator. Eg `array('!=',123)`.
569
+	 *
570
+	 * @return bool
571
+	 * @since 4.9.72.p
572
+	 */
573
+	private function valueIsLegacySpecifiedOperator(): bool
574
+	{
575
+		$valid_operators   = $this->getContext()->getModel()->valid_operators();
576
+		$query_param_value = $this->getQueryParamValue();
577
+		return isset($query_param_value[0])
578
+			&& isset($valid_operators[ $query_param_value[0] ]);
579
+	}
580
+
581
+
582
+	/**
583
+	 * Returns true if the value specified operator accepts arbitrary number of arguments, like "IN".
584
+	 *
585
+	 * @param $operator
586
+	 * @return bool
587
+	 * @since 4.9.72.p
588
+	 */
589
+	private function operatorIsNAry($operator): bool
590
+	{
591
+		$valueArray = $this->getQueryParamValue();
592
+		return array_key_exists(
593
+			$operator,
594
+			$this->getContext()->getModel()->valid_in_style_operators()
595
+		)
596
+			&& isset($valueArray[1])
597
+			&& is_array($valueArray[1])
598
+			&& ! isset($valueArray[2]);
599
+	}
600
+
601
+
602
+	/**
603
+	 * Returns true if the operator accepts 3 arguments (eg "BETWEEN").
604
+	 * So we're looking for a value that looks like
605
+	 * `array('BETWEEN', array('2015-01-01T00:00:00', '2016-01-01T00:00:00'))`.
606
+	 *
607
+	 * @param $operator
608
+	 * @return bool
609
+	 * @since 4.9.72.p
610
+	 */
611
+	private function operatorIsTernary($operator): bool
612
+	{
613
+		$query_param_value = $this->getQueryParamValue();
614
+		return array_key_exists($operator, $this->getContext()->getModel()->valid_between_style_operators())
615
+			&& isset($query_param_value[1])
616
+			&& is_array($query_param_value[1])
617
+			&& isset($query_param_value[1][0], $query_param_value[1][1])
618
+			&& ! isset($query_param_value[1][2])
619
+			&& ! isset($query_param_value[2]);
620
+	}
621
+
622
+
623
+	/**
624
+	 * Returns true if the operator is a similar to LIKE, indicating the value may have wildcards we should leave alone.
625
+	 *
626
+	 * @param $operator
627
+	 * @return bool
628
+	 * @since 4.9.72.p
629
+	 */
630
+	private function operatorIsLike($operator): bool
631
+	{
632
+		$query_param_value = $this->getQueryParamValue();
633
+		return array_key_exists($operator, $this->getContext()->getModel()->valid_like_style_operators())
634
+			&& isset($query_param_value[1])
635
+			&& ! isset($query_param_value[2]);
636
+	}
637
+
638
+
639
+	/**
640
+	 * Returns true if the operator only takes one argument (eg it's like `IS NULL`).
641
+	 *
642
+	 * @param $operator
643
+	 * @return bool
644
+	 * @since 4.9.72.p
645
+	 */
646
+	private function operatorIsUnary($operator): bool
647
+	{
648
+		$query_param_value = $this->getQueryParamValue();
649
+		return array_key_exists($operator, $this->getContext()->getModel()->valid_null_style_operators())
650
+			&& ! isset($query_param_value[1]);
651
+	}
652
+
653
+
654
+	/**
655
+	 * Returns true if the operator specified is a binary operator (eg `=`, `!=`)
656
+	 *
657
+	 * @param $operator
658
+	 * @return bool
659
+	 * @since 4.9.72.p
660
+	 */
661
+	private function operatorIsBinary($operator): bool
662
+	{
663
+		$query_param_value = $this->getQueryParamValue();
664
+		$model             = $this->getContext()->getModel();
665
+		return isset($query_param_value[1])
666
+			&& ! isset($query_param_value[2])
667
+			&& ! array_key_exists(
668
+				$operator,
669
+				array_merge(
670
+					$model->valid_in_style_operators(),
671
+					$model->valid_null_style_operators(),
672
+					$model->valid_like_style_operators(),
673
+					$model->valid_between_style_operators()
674
+				)
675
+			);
676
+	}
677
+
678
+
679
+	/**
680
+	 * If we're debugging, throws an exception saying that the wrong number of arguments was provided.
681
+	 *
682
+	 * @param $operator
683
+	 * @throws RestException
684
+	 * @since 4.9.72.p
685
+	 */
686
+	private function throwWrongNumberOfArgsExceptionIfDebugging($operator)
687
+	{
688
+		if (EED_Core_Rest_Api::debugMode()) {
689
+			throw new RestException(
690
+				'wrong_number_of_arguments',
691
+				sprintf(
692
+					esc_html__(
693
+						'The operator you provided, "%1$s" had the wrong number of arguments',
694
+						'event_espresso'
695
+					),
696
+					$operator
697
+				),
698
+				[
699
+					'status' => 400,
700
+				]
701
+			);
702
+		}
703
+	}
704
+
705
+
706
+	/**
707
+	 * Wrapper for ModelDataTranslator::prepareFieldValuesFromJson(), just a tad more DRY.
708
+	 *
709
+	 * @param $value
710
+	 * @return mixed
711
+	 * @throws RestException
712
+	 * @throws EE_Error
713
+	 * @since 4.9.72.p
714
+	 */
715
+	private function prepareValuesFromJson($value)
716
+	{
717
+		return ModelDataTranslator::prepareFieldValuesFromJson(
718
+			$this->getField(),
719
+			$value,
720
+			$this->getContext()->getRequestedVersion(),
721
+			$this->getTimezone()
722
+		);
723
+	}
724
+
725
+
726
+	/**
727
+	 * Throws an exception if an invalid operator was specified and we're debugging.
728
+	 *
729
+	 * @throws RestException
730
+	 * @since 4.9.72.p
731
+	 */
732
+	private function throwInvalidOperatorExceptionIfDebugging()
733
+	{
734
+		// so they didn't provide a valid operator
735
+		if (EED_Core_Rest_Api::debugMode()) {
736
+			throw new RestException(
737
+				'invalid_operator',
738
+				sprintf(
739
+					esc_html__(
740
+						'You provided an invalid parameter, with key "%1$s" and value "%2$s"',
741
+						'event_espresso'
742
+					),
743
+					$this->getQueryParamKey(),
744
+					$this->getQueryParamValue()
745
+				),
746
+				[
747
+					'status' => 400,
748
+				]
749
+			);
750
+		}
751
+	}
752
+
753
+
754
+	/**
755
+	 * Returns true if the query_param_key was a logic query parameter, eg `OR`, `AND`, `NOT`, `OR*`, etc.
756
+	 *
757
+	 * @return bool
758
+	 * @since 4.9.72.p
759
+	 */
760
+	private function isLogicQueryParam(): bool
761
+	{
762
+		return in_array($this->getQueryParamKeySansStars(), $this->getContext()->getModel()->logic_query_param_keys());
763
+	}
764
+
765
+
766
+	/**
767
+	 * If the query param isn't for a field, it must be a nested query parameter which requires different logic.
768
+	 *
769
+	 * @return array
770
+	 * @throws DomainException
771
+	 * @throws EE_Error
772
+	 * @throws RestException
773
+	 * @throws InvalidDataTypeException
774
+	 * @throws InvalidInterfaceException
775
+	 * @throws InvalidArgumentException
776
+	 * @since 4.9.72.p
777
+	 */
778
+	public function determineNestedConditionQueryParameters(): array
779
+	{
780
+		// so this param doesn't correspond to a field eh?
781
+		if ($this->getContext()->isWriting()) {
782
+			// always tell API clients about invalid parameters when they're creating data. Otherwise,
783
+			// they are probably going to create invalid data
784
+			throw new RestException(
785
+				'invalid_field',
786
+				sprintf(
787
+				/* translators: 1: variable name */
788
+					esc_html__('You have provided an invalid parameter: "%1$s"', 'event_espresso'),
789
+					$this->getQueryParamKey()
790
+				)
791
+			);
792
+		}
793
+		// so it's not for a field, is it a logic query param key?
794
+		if ($this->isLogicQueryParam()) {
795
+			return ModelDataTranslator::prepareConditionsQueryParamsForModels(
796
+				$this->getQueryParamValue(),
797
+				$this->getContext()->getModel(),
798
+				$this->getContext()->getRequestedVersion()
799
+			);
800
+		}
801
+		if (EED_Core_Rest_Api::debugMode()) {
802
+			// only tell API clients they got it wrong if we're in debug mode
803
+			// otherwise try our best ot fulfill their request by ignoring this invalid data
804
+			throw new RestException(
805
+				'invalid_parameter',
806
+				sprintf(
807
+				/* translators: 1: variable name */
808
+					esc_html__(
809
+						'You provided an invalid parameter, with key "%1$s"',
810
+						'event_espresso'
811
+					),
812
+					$this->getQueryParamKey()
813
+				),
814
+				array(
815
+					'status' => 400,
816
+				)
817
+			);
818
+		}
819
+		return [];
820
+	}
821 821
 }
822 822
 // End of file RestQueryParamMetadata.php
823 823
 // Location: EventEspresso\core\libraries\rest_api/RestQueryParamMetadata.php
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_CVV_Input.input.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -11,38 +11,38 @@
 block discarded – undo
11 11
  */
12 12
 class EE_CVV_Input extends EE_Text_Input
13 13
 {
14
-    /**
15
-     * @param array  $input_settings          {
16
-     * @type boolean $include_whats_this_link defaults to true
17
-     *                                        }
18
-     */
19
-    public function __construct($input_settings = [])
20
-    {
21
-        $this->set_sensitive_data_removal_strategy(new EE_CCV_Sensitive_Data_Removal());
22
-        $this->_add_validation_strategy(
23
-            new EE_Text_Validation_Strategy(
24
-                $input_settings['validation_error_message'] ?? esc_html__(
25
-                    'The CVV is either a 3 digit number on the back of your card, or 4 digit number on the front',
26
-                    'event_espresso'
27
-                ),
28
-                '~^\d{3,4}$~'
29
-            )
30
-        );
31
-        parent::__construct($input_settings);
32
-        if (
33
-            ! isset($input_settings['include_whats_this_link'])
34
-            || $input_settings['include_whats_this_link'] === true
35
-        ) {
36
-            $this->_html_label_text = sprintf(
37
-                esc_html_x(
38
-                    '%1$s %2$s(What\'s this?)%3$s',
39
-                    'CVV (What\'s this?)',
40
-                    'event_espresso'
41
-                ),
42
-                $this->_html_label_text,
43
-                '<a href="https://www.cvvnumber.com/" target="_blank" rel="noopener noreferrer">',
44
-                '</a>'
45
-            );
46
-        }
47
-    }
14
+	/**
15
+	 * @param array  $input_settings          {
16
+	 * @type boolean $include_whats_this_link defaults to true
17
+	 *                                        }
18
+	 */
19
+	public function __construct($input_settings = [])
20
+	{
21
+		$this->set_sensitive_data_removal_strategy(new EE_CCV_Sensitive_Data_Removal());
22
+		$this->_add_validation_strategy(
23
+			new EE_Text_Validation_Strategy(
24
+				$input_settings['validation_error_message'] ?? esc_html__(
25
+					'The CVV is either a 3 digit number on the back of your card, or 4 digit number on the front',
26
+					'event_espresso'
27
+				),
28
+				'~^\d{3,4}$~'
29
+			)
30
+		);
31
+		parent::__construct($input_settings);
32
+		if (
33
+			! isset($input_settings['include_whats_this_link'])
34
+			|| $input_settings['include_whats_this_link'] === true
35
+		) {
36
+			$this->_html_label_text = sprintf(
37
+				esc_html_x(
38
+					'%1$s %2$s(What\'s this?)%3$s',
39
+					'CVV (What\'s this?)',
40
+					'event_espresso'
41
+				),
42
+				$this->_html_label_text,
43
+				'<a href="https://www.cvvnumber.com/" target="_blank" rel="noopener noreferrer">',
44
+				'</a>'
45
+			);
46
+		}
47
+	}
48 48
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Form_Input_Base.input.php 2 patches
Indentation   +1262 added lines, -1262 removed lines patch added patch discarded remove patch
@@ -14,1266 +14,1266 @@
 block discarded – undo
14 14
  */
15 15
 abstract class EE_Form_Input_Base extends EE_Form_Section_Validatable
16 16
 {
17
-    /**
18
-     * the input's name attribute
19
-     *
20
-     * @var string|null
21
-     */
22
-    protected ?string $_html_name = null;
23
-
24
-    /**
25
-     * id for the html label tag
26
-     *
27
-     * @var string
28
-     */
29
-    protected $_html_label_id;
30
-
31
-    /**
32
-     * class for teh html label tag
33
-     *
34
-     * @var string
35
-     */
36
-    protected $_html_label_class;
37
-
38
-    /**
39
-     * style for teh html label tag
40
-     *
41
-     * @var string
42
-     */
43
-    protected $_html_label_style;
44
-
45
-    /**
46
-     * text to be placed in the html label
47
-     *
48
-     * @var string
49
-     */
50
-    protected $_html_label_text;
51
-
52
-    /**
53
-     * the full html label. If used, all other html_label_* properties are invalid
54
-     *
55
-     * @var string
56
-     */
57
-    protected $_html_label;
58
-
59
-    /**
60
-     * HTML to use for help text (normally placed below form input), in a span which normally
61
-     * has a class of 'description'
62
-     *
63
-     * @var string
64
-     */
65
-    protected $_html_help_text;
66
-
67
-    /**
68
-     * CSS classes for displaying the help span
69
-     *
70
-     * @var string
71
-     */
72
-    protected $_html_help_class = 'description';
73
-
74
-    /**
75
-     * CSS to put in the style attribute on the help span
76
-     *
77
-     * @var string
78
-     */
79
-    protected $_html_help_style;
80
-
81
-    /**
82
-     * Stores whether or not this input's response is required.
83
-     * Because certain styling elements may also want to know that this
84
-     * input is required etc.
85
-     *
86
-     * @var boolean
87
-     */
88
-    protected $_required;
89
-
90
-    /**
91
-     * css class added to required inputs
92
-     *
93
-     * @var string
94
-     */
95
-    protected $_required_css_class = 'ee-required';
96
-
97
-    /**
98
-     * css styles applied to button type inputs
99
-     *
100
-     * @var string
101
-     */
102
-    protected $_button_css_attributes;
103
-
104
-    /**
105
-     * The raw post data submitted for this
106
-     * Generally unsafe for usage in client code
107
-     *
108
-     * @var mixed string or array
109
-     */
110
-    protected $_raw_value;
111
-
112
-    /**
113
-     * Value normalized according to the input's normalization strategy.
114
-     * The normalization strategy dictates whether this is a string, int, float,
115
-     * boolean, or array of any of those.
116
-     *
117
-     * @var mixed
118
-     */
119
-    protected $_normalized_value;
120
-
121
-
122
-    /**
123
-     * Normalized default value either initially set on the input, or provided by calling
124
-     * set_default().
125
-     *
126
-     * @var mixed
127
-     */
128
-    protected $_default;
129
-
130
-    /**
131
-     * Strategy used for displaying this field.
132
-     * Child classes must use _get_display_strategy to access it.
133
-     *
134
-     * @var EE_Display_Strategy_Base
135
-     */
136
-    private $_display_strategy;
137
-
138
-    /**
139
-     * Gets all the validation strategies used on this field
140
-     *
141
-     * @var EE_Validation_Strategy_Base[]
142
-     */
143
-    private $_validation_strategies = [];
144
-
145
-    /**
146
-     * The normalization strategy for this field
147
-     *
148
-     * @var EE_Normalization_Strategy_Base
149
-     */
150
-    private $_normalization_strategy;
151
-
152
-    /**
153
-     * Strategy for removing sensitive data after we're done with the form input
154
-     *
155
-     * @var EE_Sensitive_Data_Removal_Base
156
-     */
157
-    protected $_sensitive_data_removal_strategy;
158
-
159
-    /**
160
-     * Whether this input has been disabled or not.
161
-     * If it's disabled while rendering, an extra hidden input is added that indicates it has been knowingly disabled.
162
-     * (Client-side code that wants to dynamically disable it must also add this hidden input).
163
-     * When the form is submitted, if the input is disabled in the PHP form section, then input is ignored.
164
-     * If the input is missing from the request data but the hidden input indicating the input is disabled, then the
165
-     * input is again ignored.
166
-     *
167
-     * @var boolean
168
-     */
169
-    protected $disabled = false;
170
-
171
-    protected array $_data_attributes = [];
172
-
173
-    protected bool $_no_label = false; // if true, then no hrml label will be displayed for this input
174
-
175
-    /**
176
-     * adds a class to the input's container
177
-     *
178
-     * @var string
179
-     */
180
-    protected string $_layout_container_class = '';
181
-
182
-    /**
183
-     * additional HTML to inject into the input's container
184
-     *
185
-     * @var string
186
-     */
187
-    protected string $_extra_container_html = '';
188
-
189
-
190
-    /**
191
-     * @param array                         $input_args       {
192
-     * @type string                         $html_name        the html name for the input
193
-     * @type string                         $html_label_id    the id attribute to give to the html label tag
194
-     * @type string                         $html_label_class the class attribute to give to the html label tag
195
-     * @type string                         $html_label_style the style attribute to give ot teh label tag
196
-     * @type string                         $html_label_text  the text to put in the label tag
197
-     * @type string                         $html_label       the full html label. If used,
198
-     *                                                        all other html_label_* args are invalid
199
-     * @type string                         $html_help_text   text to put in help element
200
-     * @type string                         $html_help_style  style attribute to give to teh help element
201
-     * @type string                         $html_help_class  class attribute to give to the help element
202
-     * @type string                         $default          default value NORMALIZED (eg, if providing the default
203
-     *                                                        for a Yes_No_Input, you should provide TRUE or FALSE, not
204
-     *                                                        '1' or '0')
205
-     * @type EE_Display_Strategy_Base       $display          strategy
206
-     * @type EE_Normalization_Strategy_Base $normalization_strategy
207
-     * @type EE_Validation_Strategy_Base[]  $validation_strategies
208
-     * @type boolean                        $ignore_input     special argument which can be used to avoid adding any
209
-     *                                                        validation strategies, and sets the normalization
210
-     *                                                        strategy to the Null normalization. This is good when you
211
-     *                                                        want the input to be totally ignored server-side (like
212
-     *                                                        when using React.js form inputs)
213
-     *                                                        }
214
-     */
215
-    public function __construct($input_args = [])
216
-    {
217
-        $input_args = (array) apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
218
-        // the following properties must be cast as arrays
219
-        if (isset($input_args['validation_strategies'])) {
220
-            foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
221
-                if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
222
-                    $this->_validation_strategies[ get_class($validation_strategy) ] = $validation_strategy;
223
-                }
224
-            }
225
-            unset($input_args['validation_strategies']);
226
-        }
227
-        if (isset($input_args['ignore_input'])) {
228
-            $this->_validation_strategies = [];
229
-        }
230
-        // loop thru incoming options
231
-        foreach ($input_args as $key => $value) {
232
-            if ($key === 'disabled') {
233
-                $this->disable($value);
234
-                continue;
235
-            }
236
-            $setter = 'set_' . $key;
237
-            if (method_exists($this, $setter)) {
238
-                $this->$setter($value);
239
-                unset($input_args[ $key ]);
240
-                continue;
241
-            }
242
-            // add underscore to $key to match property names
243
-            $_key = "_$key";
244
-            if (property_exists($this, $_key)) {
245
-                $this->{$_key} = $value;
246
-                unset($input_args[ $key ]);
247
-            }
248
-        }
249
-        // ensure that "required" is set correctly
250
-        $this->set_required(
251
-            $this->_required,
252
-            $input_args['required_validation_error_message'] ?? null
253
-        );
254
-        // $this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
255
-        $this->_display_strategy->_construct_finalize($this);
256
-        foreach ($this->_validation_strategies as $validation_strategy) {
257
-            $validation_strategy->_construct_finalize($this);
258
-        }
259
-        if (isset($input_args['ignore_input'])) {
260
-            $this->_normalization_strategy = new EE_Null_Normalization();
261
-        }
262
-        if (! $this->_normalization_strategy) {
263
-            $this->_normalization_strategy = new EE_Text_Normalization();
264
-        }
265
-        $this->_normalization_strategy->_construct_finalize($this);
266
-        // at least we can use the normalization strategy to populate the default
267
-        if (isset($input_args['default'])) {
268
-            $this->set_default($input_args['default']);
269
-            unset($input_args['default']);
270
-        }
271
-        if (! $this->_sensitive_data_removal_strategy) {
272
-            $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
273
-        }
274
-        $this->_sensitive_data_removal_strategy->_construct_finalize($this);
275
-        parent::__construct($input_args);
276
-    }
277
-
278
-
279
-    /**
280
-     * Sets the html_name to its default value, if none was specified in teh constructor.
281
-     * Calculation involves using the name and the parent's html_name
282
-     *
283
-     * @throws EE_Error
284
-     */
285
-    protected function _set_default_html_name_if_empty()
286
-    {
287
-        if (! $this->_html_name) {
288
-            $this->_html_name = $this->name();
289
-            if ($this->_parent_section instanceof EE_Form_Section_Proper) {
290
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
291
-            }
292
-        }
293
-    }
294
-
295
-
296
-    /**
297
-     * @param $parent_form_section
298
-     * @param $name
299
-     * @throws EE_Error
300
-     */
301
-    public function _construct_finalize($parent_form_section, $name)
302
-    {
303
-        parent::_construct_finalize($parent_form_section, $name);
304
-        if ($this->_html_label === null && $this->_html_label_text === null && ! $this->_no_label) {
305
-            $this->_html_label_text = ucwords(str_replace("_", " ", $name));
306
-        }
307
-        do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
308
-    }
309
-
310
-
311
-    /**
312
-     * Returns the strategy for displaying this form input. If none is set, throws an exception.
313
-     *
314
-     * @return EE_Display_Strategy_Base
315
-     * @throws EE_Error
316
-     */
317
-    protected function _get_display_strategy()
318
-    {
319
-        $this->ensure_construct_finalized_called();
320
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
321
-            throw new EE_Error(
322
-                sprintf(
323
-                    esc_html__(
324
-                        "Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
325
-                        "event_espresso"
326
-                    ),
327
-                    $this->html_name(),
328
-                    $this->html_id()
329
-                )
330
-            );
331
-        } else {
332
-            return $this->_display_strategy;
333
-        }
334
-    }
335
-
336
-
337
-    /**
338
-     * Sets the display strategy.
339
-     *
340
-     * @param EE_Display_Strategy_Base $strategy
341
-     */
342
-    protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
343
-    {
344
-        $this->_display_strategy = $strategy;
345
-    }
346
-
347
-
348
-    /**
349
-     * Sets the sanitization strategy
350
-     *
351
-     * @param EE_Normalization_Strategy_Base $strategy
352
-     */
353
-    protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
354
-    {
355
-        $this->_normalization_strategy = $strategy;
356
-    }
357
-
358
-
359
-    /**
360
-     * Gets sensitive_data_removal_strategy
361
-     *
362
-     * @return EE_Sensitive_Data_Removal_Base
363
-     */
364
-    public function get_sensitive_data_removal_strategy()
365
-    {
366
-        return $this->_sensitive_data_removal_strategy;
367
-    }
368
-
369
-
370
-    /**
371
-     * Sets sensitive_data_removal_strategy
372
-     *
373
-     * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
374
-     * @return void
375
-     */
376
-    public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
377
-    {
378
-        $this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
379
-    }
380
-
381
-
382
-    /**
383
-     * Gets the display strategy for this input
384
-     *
385
-     * @return EE_Display_Strategy_Base
386
-     */
387
-    public function get_display_strategy()
388
-    {
389
-        return $this->_display_strategy;
390
-    }
391
-
392
-
393
-    /**
394
-     * Overwrites the display strategy
395
-     *
396
-     * @param EE_Display_Strategy_Base $display_strategy
397
-     */
398
-    public function set_display_strategy($display_strategy)
399
-    {
400
-        $this->_display_strategy = $display_strategy;
401
-        $this->_display_strategy->_construct_finalize($this);
402
-    }
403
-
404
-
405
-    /**
406
-     * Gets the normalization strategy set on this input
407
-     *
408
-     * @return EE_Normalization_Strategy_Base
409
-     */
410
-    public function get_normalization_strategy()
411
-    {
412
-        return $this->_normalization_strategy;
413
-    }
414
-
415
-
416
-    /**
417
-     * Overwrites the normalization strategy
418
-     *
419
-     * @param EE_Normalization_Strategy_Base $normalization_strategy
420
-     */
421
-    public function set_normalization_strategy($normalization_strategy)
422
-    {
423
-        $this->_normalization_strategy = $normalization_strategy;
424
-        $this->_normalization_strategy->_construct_finalize($this);
425
-    }
426
-
427
-
428
-    /**
429
-     * Returns all teh validation strategies which apply to this field, numerically indexed
430
-     *
431
-     * @return EE_Validation_Strategy_Base[]
432
-     */
433
-    public function get_validation_strategies()
434
-    {
435
-        return $this->_validation_strategies;
436
-    }
437
-
438
-
439
-    /**
440
-     * Adds this strategy to the field so it will be used in both JS validation and server-side validation
441
-     *
442
-     * @param EE_Validation_Strategy_Base $validation_strategy
443
-     * @return void
444
-     */
445
-    protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
446
-    {
447
-        $validation_strategy->_construct_finalize($this);
448
-        $this->_validation_strategies[] = $validation_strategy;
449
-    }
450
-
451
-
452
-    /**
453
-     * Adds a new validation strategy onto the form input
454
-     *
455
-     * @param EE_Validation_Strategy_Base $validation_strategy
456
-     * @return void
457
-     */
458
-    public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
459
-    {
460
-        $this->_add_validation_strategy($validation_strategy);
461
-    }
462
-
463
-
464
-    /**
465
-     * The classname of the validation strategy to remove
466
-     *
467
-     * @param string $validation_strategy_classname
468
-     */
469
-    public function remove_validation_strategy($validation_strategy_classname)
470
-    {
471
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
472
-            if (
473
-                $validation_strategy instanceof $validation_strategy_classname
474
-                || is_subclass_of($validation_strategy, $validation_strategy_classname)
475
-            ) {
476
-                unset($this->_validation_strategies[ $key ]);
477
-            }
478
-        }
479
-    }
480
-
481
-
482
-    /**
483
-     * returns true if input employs any of the validation strategy defined by the supplied array of classnames
484
-     *
485
-     * @param array $validation_strategy_classnames
486
-     * @return bool
487
-     */
488
-    public function has_validation_strategy($validation_strategy_classnames)
489
-    {
490
-        $validation_strategy_classnames = is_array($validation_strategy_classnames)
491
-            ? $validation_strategy_classnames
492
-            : [$validation_strategy_classnames];
493
-        foreach ($this->_validation_strategies as $key => $validation_strategy) {
494
-            if (in_array($key, $validation_strategy_classnames)) {
495
-                return true;
496
-            }
497
-        }
498
-        return false;
499
-    }
500
-
501
-
502
-    /**
503
-     * Gets the HTML
504
-     *
505
-     * @return string
506
-     */
507
-    public function get_html()
508
-    {
509
-        return $this->_parent_section->get_html_for_input($this);
510
-    }
511
-
512
-
513
-    /**
514
-     * Gets the HTML for the input itself (no label or errors) according to the
515
-     * input's display strategy
516
-     * Makes sure the JS and CSS are enqueued for it
517
-     *
518
-     * @return string
519
-     * @throws EE_Error
520
-     */
521
-    public function get_html_for_input()
522
-    {
523
-        return $this->_form_html_filter
524
-            ? $this->_form_html_filter->filterHtml(
525
-                $this->_get_display_strategy()->display(),
526
-                $this
527
-            )
528
-            : $this->_get_display_strategy()->display();
529
-    }
530
-
531
-
532
-    /**
533
-     * @return string
534
-     */
535
-    public function html_other_attributes()
536
-    {
537
-        EE_Error::doing_it_wrong(
538
-            __METHOD__,
539
-            sprintf(
540
-                esc_html__(
541
-                    'This method is no longer in use. You should replace it by %s',
542
-                    'event_espresso'
543
-                ),
544
-                'EE_Form_Section_Base::other_html_attributes()'
545
-            ),
546
-            '4.10.2.p'
547
-        );
548
-
549
-        return $this->other_html_attributes();
550
-    }
551
-
552
-
553
-    /**
554
-     * @param string $html_other_attributes
555
-     */
556
-    public function set_html_other_attributes($html_other_attributes)
557
-    {
558
-        EE_Error::doing_it_wrong(
559
-            __METHOD__,
560
-            sprintf(
561
-                esc_html__(
562
-                    'This method is no longer in use. You should replace it by %s',
563
-                    'event_espresso'
564
-                ),
565
-                'EE_Form_Section_Base::set_other_html_attributes()'
566
-            ),
567
-            '4.10.2.p'
568
-        );
569
-
570
-        $this->set_other_html_attributes($html_other_attributes);
571
-    }
572
-
573
-
574
-    /**
575
-     * Gets the HTML for displaying the label for this form input
576
-     * according to the form section's layout strategy
577
-     *
578
-     * @return string
579
-     * @throws EE_Error
580
-     */
581
-    public function get_html_for_label()
582
-    {
583
-        return $this->_parent_section->get_layout_strategy()->display_label($this);
584
-    }
585
-
586
-
587
-    /**
588
-     * Gets the HTML for displaying the errors section for this form input
589
-     * according to the form section's layout strategy
590
-     *
591
-     * @return string
592
-     * @throws EE_Error
593
-     */
594
-    public function get_html_for_errors()
595
-    {
596
-        return $this->_parent_section->get_layout_strategy()->display_errors($this);
597
-    }
598
-
599
-
600
-    /**
601
-     * Gets the HTML for displaying the help text for this form input
602
-     * according to the form section's layout strategy
603
-     *
604
-     * @return string
605
-     * @throws EE_Error
606
-     */
607
-    public function get_html_for_help()
608
-    {
609
-        return $this->_parent_section->get_layout_strategy()->display_help_text($this);
610
-    }
611
-
612
-
613
-    /**
614
-     * Validates the input's sanitized value (assumes _sanitize() has already been called)
615
-     * and returns whether or not the form input's submitted value is value
616
-     *
617
-     * @return boolean
618
-     */
619
-    protected function _validate()
620
-    {
621
-        if ($this->isDisabled()) {
622
-            return true;
623
-        }
624
-        foreach ($this->_validation_strategies as $validation_strategy) {
625
-            if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
626
-                try {
627
-                    $validation_strategy->validate($this->normalized_value());
628
-                } catch (EE_Validation_Error $e) {
629
-                    $this->add_validation_error($e);
630
-                }
631
-            }
632
-        }
633
-        if ($this->get_validation_errors()) {
634
-            return false;
635
-        } else {
636
-            return true;
637
-        }
638
-    }
639
-
640
-
641
-    /**
642
-     * Performs basic sanitization on this value. But what sanitization can be performed anyways?
643
-     * This value MIGHT be allowed to have tags, so we can't really remove them.
644
-     *
645
-     * @param string $value
646
-     * @return null|string
647
-     */
648
-    protected function _sanitize($value)
649
-    {
650
-        return $value !== null
651
-            ? stripslashes(html_entity_decode(trim((string) $value)))
652
-            : null;
653
-    }
654
-
655
-
656
-    /**
657
-     * Picks out the form value that relates to this form input,
658
-     * and stores it as the sanitized value on the form input, and sets the normalized value.
659
-     * Returns whether or not any validation errors occurred
660
-     *
661
-     * @param array $req_data
662
-     * @return boolean whether or not there was an error
663
-     * @throws EE_Error
664
-     */
665
-    protected function _normalize($req_data)
666
-    {
667
-        // any existing validation errors don't apply so clear them
668
-        $this->_validation_errors = [];
669
-        // if the input is disabled, ignore whatever input was sent in
670
-        if ($this->isDisabled()) {
671
-            $this->_set_raw_value(null);
672
-            $this->_set_normalized_value($this->get_default());
673
-            return false;
674
-        }
675
-        try {
676
-            $raw_input = $this->find_form_data_for_this_section($req_data);
677
-            // super simple sanitization for now
678
-            if (is_array($raw_input)) {
679
-                $raw_value = [];
680
-                foreach ($raw_input as $key => $value) {
681
-                    $raw_value[ $key ] = $this->_sanitize($value);
682
-                }
683
-                $this->_set_raw_value($raw_value);
684
-            } else {
685
-                $this->_set_raw_value($this->_sanitize($raw_input));
686
-            }
687
-            // we want to mostly leave the input alone in case we need to re-display it to the user
688
-            $this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
689
-            return false;
690
-        } catch (EE_Validation_Error $e) {
691
-            $this->add_validation_error($e);
692
-            return true;
693
-        }
694
-    }
695
-
696
-
697
-    /**
698
-     * @return string
699
-     * @throws EE_Error
700
-     */
701
-    public function html_name()
702
-    {
703
-        $this->_set_default_html_name_if_empty();
704
-        return $this->_html_name ?? '';
705
-    }
706
-
707
-
708
-    /**
709
-     * @return string
710
-     * @throws EE_Error
711
-     */
712
-    public function html_label_id()
713
-    {
714
-        return ! empty($this->_html_label_id)
715
-            ? $this->_html_label_id
716
-            : $this->html_id() . '-lbl';
717
-    }
718
-
719
-
720
-    /**
721
-     * @return string
722
-     */
723
-    public function html_label_class()
724
-    {
725
-        return $this->_html_label_class ?? '';
726
-    }
727
-
728
-
729
-    /**
730
-     * @param string $html_class
731
-     */
732
-    public function add_html_label_class(string $html_class)
733
-    {
734
-        $this->_html_label_class .= ' ' . trim($html_class);
735
-    }
736
-
737
-
738
-    /**
739
-     * @return string
740
-     */
741
-    public function html_label_style()
742
-    {
743
-        return $this->_html_label_style ?? '';
744
-    }
745
-
746
-
747
-    /**
748
-     * @return string
749
-     */
750
-    public function html_label_text()
751
-    {
752
-        return $this->_html_label_text ?? '';
753
-    }
754
-
755
-
756
-    /**
757
-     * @return string
758
-     */
759
-    public function html_help_text()
760
-    {
761
-        return $this->_html_help_text ?? '';
762
-    }
763
-
764
-
765
-    /**
766
-     * @return string
767
-     */
768
-    public function html_help_class()
769
-    {
770
-        return $this->_html_help_class ?? '';
771
-    }
772
-
773
-
774
-    /**
775
-     * @return string
776
-     */
777
-    public function html_help_style()
778
-    {
779
-        return $this->_html_style ?? '';
780
-    }
781
-
782
-
783
-    /**
784
-     * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
785
-     * Please note that almost all client code should instead use the normalized_value;
786
-     * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
787
-     * mostly by escaping quotes)
788
-     * Note, we do not store the exact original value sent in the user's request because
789
-     * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
790
-     * in which case, we would have stored the malicious content to our database.
791
-     *
792
-     * @return mixed
793
-     */
794
-    public function raw_value()
795
-    {
796
-        return $this->_raw_value;
797
-    }
798
-
799
-
800
-    /**
801
-     * Returns a string safe to usage in form inputs when displaying, because
802
-     * it escapes all html entities
803
-     *
804
-     * @return string
805
-     */
806
-    public function raw_value_in_form(): string
807
-    {
808
-        return htmlentities((string) $this->raw_value(), ENT_QUOTES, 'UTF-8');
809
-    }
810
-
811
-
812
-    /**
813
-     * returns the value after it's been sanitized, and then converted into it's proper type
814
-     * in PHP. Eg, a string, an int, an array,
815
-     *
816
-     * @return mixed
817
-     */
818
-    public function normalized_value()
819
-    {
820
-        return $this->_normalized_value;
821
-    }
822
-
823
-
824
-    /**
825
-     * Returns the normalized value is a presentable way. By default this is just
826
-     * the normalized value by itself, but it can be overridden for when that's not
827
-     * the best thing to display
828
-     *
829
-     * @return mixed
830
-     */
831
-    public function pretty_value()
832
-    {
833
-        return $this->_normalized_value;
834
-    }
835
-
836
-
837
-    /**
838
-     * When generating the JS for the jquery validation rules like<br>
839
-     * <code>$( "#myform" ).validate({
840
-     * rules: {
841
-     * password: "required",
842
-     * password_again: {
843
-     * equalTo: "#password"
844
-     * }
845
-     * }
846
-     * });</code>
847
-     * if this field had the name 'password_again', it should return
848
-     * <br><code>password_again: {
849
-     * equalTo: "#password"
850
-     * }</code>
851
-     *
852
-     * @return array
853
-     * @throws EE_Error
854
-     */
855
-    public function get_jquery_validation_rules(): array
856
-    {
857
-        $jquery_validation_js    = [];
858
-        $jquery_validation_rules = [];
859
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
860
-            $jquery_validation_rules = array_replace_recursive(
861
-                $jquery_validation_rules,
862
-                $validation_strategy->get_jquery_validation_rule_array()
863
-            );
864
-        }
865
-        if (! empty($jquery_validation_rules)) {
866
-            foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
867
-                $jquery_validation_js[ $html_id_with_pound_sign ] = $jquery_validation_rules;
868
-            }
869
-        }
870
-        return $jquery_validation_js;
871
-    }
872
-
873
-
874
-    /**
875
-     * Sets the input's default value for use in displaying in the form. Note: value should be
876
-     * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
877
-     *
878
-     * @param mixed $value
879
-     * @return void
880
-     */
881
-    public function set_default($value)
882
-    {
883
-        $this->_default = $value;
884
-        $this->_set_normalized_value($value);
885
-        $this->_set_raw_value($value);
886
-    }
887
-
888
-
889
-    /**
890
-     * Sets the normalized value on this input
891
-     *
892
-     * @param mixed $value
893
-     */
894
-    protected function _set_normalized_value($value)
895
-    {
896
-        $this->_normalized_value = $value;
897
-    }
898
-
899
-
900
-    /**
901
-     * Sets the raw value on this input (ie, exactly as the user submitted it)
902
-     *
903
-     * @param mixed $value
904
-     */
905
-    protected function _set_raw_value($value)
906
-    {
907
-        $this->_raw_value = $this->_normalization_strategy->unnormalize($value);
908
-    }
909
-
910
-
911
-    /**
912
-     * Sets the HTML label text after it has already been defined
913
-     *
914
-     * @param string $label
915
-     * @return void
916
-     */
917
-    public function set_html_label_text($label)
918
-    {
919
-        $this->_html_label_text = $label;
920
-    }
921
-
922
-
923
-    /**
924
-     * Sets whether or not this field is required, and adjusts the validation strategy.
925
-     * If you want to use the EE_Conditionally_Required_Validation_Strategy,
926
-     * please add it as a validation strategy using add_validation_strategy as normal
927
-     *
928
-     * @param boolean $required boolean
929
-     * @param null    $required_text
930
-     */
931
-    public function set_required($required = true, $required_text = null)
932
-    {
933
-        $required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
934
-        // whether $required is a string or a boolean, we want to add a required validation strategy
935
-        if ($required) {
936
-            $this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
937
-        } else {
938
-            $this->remove_validation_strategy('EE_Required_Validation_Strategy');
939
-        }
940
-        $this->_required = $required;
941
-    }
942
-
943
-
944
-    /**
945
-     * Returns whether or not this field is required
946
-     *
947
-     * @return boolean
948
-     */
949
-    public function required()
950
-    {
951
-        return $this->_required;
952
-    }
953
-
954
-
955
-    /**
956
-     * @param string $required_css_class
957
-     */
958
-    public function set_required_css_class($required_css_class)
959
-    {
960
-        $this->_required_css_class = $required_css_class;
961
-    }
962
-
963
-
964
-    /**
965
-     * @return string
966
-     */
967
-    public function required_css_class()
968
-    {
969
-        return $this->_required_css_class;
970
-    }
971
-
972
-
973
-    /**
974
-     * @param bool $add_required
975
-     * @return string
976
-     */
977
-    public function html_class($add_required = false)
978
-    {
979
-        return $add_required && $this->required()
980
-            ? $this->required_css_class() . ' ' . $this->_html_class
981
-            : $this->_html_class;
982
-    }
983
-
984
-
985
-    /**
986
-     * Sets the help text, in case
987
-     *
988
-     * @param string $text
989
-     */
990
-    public function set_html_help_text($text)
991
-    {
992
-        $this->_html_help_text = $text;
993
-    }
994
-
995
-
996
-    /**
997
-     * Uses the sensitive data removal strategy to remove the sensitive data from this
998
-     * input. If there is any kind of sensitive data removal on this input, we clear
999
-     * out the raw value completely
1000
-     *
1001
-     * @return void
1002
-     */
1003
-    public function clean_sensitive_data()
1004
-    {
1005
-        // if we do ANY kind of sensitive data removal on this, then just clear out the raw value
1006
-        // if we need more logic than this we'll make a strategy for it
1007
-        if (
1008
-            $this->_sensitive_data_removal_strategy
1009
-            && ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
1010
-        ) {
1011
-            $this->_set_raw_value(null);
1012
-        }
1013
-        // and clean the normalized value according to the appropriate strategy
1014
-        $this->_set_normalized_value(
1015
-            $this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
1016
-                $this->_normalized_value
1017
-            )
1018
-        );
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * @param bool   $primary
1024
-     * @param string $button_size
1025
-     * @param string $other_attributes
1026
-     */
1027
-    public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
1028
-    {
1029
-        $button_css_attributes = 'button';
1030
-        $button_css_attributes .= $primary === true
1031
-            ? ' button--primary'
1032
-            : ' button--secondary';
1033
-        switch ($button_size) {
1034
-            case 'xs':
1035
-            case 'extra-small':
1036
-                $button_css_attributes .= ' button-xs';
1037
-                break;
1038
-            case 'sm':
1039
-            case 'small':
1040
-                $button_css_attributes .= ' button-sm';
1041
-                break;
1042
-            case 'lg':
1043
-            case 'large':
1044
-                $button_css_attributes .= ' button-lg';
1045
-                break;
1046
-            case 'block':
1047
-                $button_css_attributes .= ' button-block';
1048
-                break;
1049
-            case 'md':
1050
-            case 'medium':
1051
-            default:
1052
-                $button_css_attributes .= '';
1053
-        }
1054
-        $this->_button_css_attributes .= ! empty($other_attributes)
1055
-            ? $button_css_attributes . ' ' . $other_attributes
1056
-            : $button_css_attributes;
1057
-    }
1058
-
1059
-
1060
-    /**
1061
-     * @return string
1062
-     */
1063
-    public function button_css_attributes()
1064
-    {
1065
-        if (empty($this->_button_css_attributes)) {
1066
-            $this->set_button_css_attributes();
1067
-        }
1068
-        return $this->_button_css_attributes;
1069
-    }
1070
-
1071
-
1072
-    /**
1073
-     * find_form_data_for_this_section
1074
-     * using this section's name and its parents, finds the value of the form data that corresponds to it.
1075
-     * For example, if this form section's HTML name is my_form[subform][form_input_1],
1076
-     * then it's value should be in request at request['my_form']['subform']['form_input_1'].
1077
-     * (If that doesn't exist, we also check for this subsection's name
1078
-     * at the TOP LEVEL of the request data. Eg request['form_input_1'].)
1079
-     * This function finds its value in the form.
1080
-     *
1081
-     * @param array $req_data
1082
-     * @return mixed whatever the raw value of this form section is in the request data
1083
-     * @throws EE_Error
1084
-     */
1085
-    public function find_form_data_for_this_section($req_data)
1086
-    {
1087
-        $name_parts = $this->getInputNameParts();
1088
-        // now get the value for the input
1089
-        $value = $this->findRequestForSectionUsingNameParts($name_parts, $req_data);
1090
-        // check if this thing's name is at the TOP level of the request data
1091
-        if ($value === null && isset($req_data[ $this->name() ])) {
1092
-            $value = $req_data[ $this->name() ];
1093
-        }
1094
-        return $value;
1095
-    }
1096
-
1097
-
1098
-    /**
1099
-     * If this input's name is something like "foo[bar][baz]"
1100
-     * returns an array like `array('foo','bar',baz')`
1101
-     *
1102
-     * @return array
1103
-     * @throws EE_Error
1104
-     */
1105
-    protected function getInputNameParts()
1106
-    {
1107
-        // break up the html name by "[]"
1108
-        if (strpos($this->html_name(), '[') !== false) {
1109
-            $before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1110
-        } else {
1111
-            $before_any_brackets = $this->html_name();
1112
-        }
1113
-        // grab all of the segments
1114
-        preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1115
-        if (isset($matches[1]) && is_array($matches[1])) {
1116
-            $name_parts = $matches[1];
1117
-            array_unshift($name_parts, $before_any_brackets);
1118
-        } else {
1119
-            $name_parts = [$before_any_brackets];
1120
-        }
1121
-        return $name_parts;
1122
-    }
1123
-
1124
-
1125
-    /**
1126
-     * @param array $html_name_parts
1127
-     * @param array $req_data
1128
-     * @return array | NULL
1129
-     */
1130
-    public function findRequestForSectionUsingNameParts($html_name_parts, $req_data)
1131
-    {
1132
-        $first_part_to_consider = array_shift($html_name_parts);
1133
-        if (isset($req_data[ $first_part_to_consider ])) {
1134
-            if (empty($html_name_parts)) {
1135
-                return $req_data[ $first_part_to_consider ];
1136
-            } else {
1137
-                return $this->findRequestForSectionUsingNameParts(
1138
-                    $html_name_parts,
1139
-                    $req_data[ $first_part_to_consider ]
1140
-                );
1141
-            }
1142
-        }
1143
-        return null;
1144
-    }
1145
-
1146
-
1147
-    /**
1148
-     * Checks if this form input's data is in the request data
1149
-     *
1150
-     * @param array $req_data
1151
-     * @return boolean
1152
-     * @throws EE_Error
1153
-     */
1154
-    public function form_data_present_in($req_data = null)
1155
-    {
1156
-        if ($req_data === null) {
1157
-            /** @var RequestInterface $request */
1158
-            $request  = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1159
-            $req_data = $request->postParams();
1160
-        }
1161
-
1162
-        return $this->find_form_data_for_this_section($req_data) !== null;
1163
-    }
1164
-
1165
-
1166
-    /**
1167
-     * Overrides parent to add js data from validation and display strategies
1168
-     *
1169
-     * @param array $form_other_js_data
1170
-     * @return array
1171
-     */
1172
-    public function get_other_js_data($form_other_js_data = [])
1173
-    {
1174
-        return $this->get_other_js_data_from_strategies($form_other_js_data);
1175
-    }
1176
-
1177
-
1178
-    /**
1179
-     * Gets other JS data for localization from this input's strategies, like
1180
-     * the validation strategies and the display strategy
1181
-     *
1182
-     * @param array $form_other_js_data
1183
-     * @return array
1184
-     */
1185
-    public function get_other_js_data_from_strategies($form_other_js_data = [])
1186
-    {
1187
-        $form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1188
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1189
-            $form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1190
-        }
1191
-        return $form_other_js_data;
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1197
-     *
1198
-     * @return void
1199
-     */
1200
-    public function enqueue_js()
1201
-    {
1202
-        // ask our display strategy and validation strategies if they have js to enqueue
1203
-        $this->enqueue_js_from_strategies();
1204
-    }
1205
-
1206
-
1207
-    /**
1208
-     * Tells strategies when its ok to enqueue their js and css
1209
-     *
1210
-     * @return void
1211
-     */
1212
-    public function enqueue_js_from_strategies()
1213
-    {
1214
-        $this->get_display_strategy()->enqueue_js();
1215
-        foreach ($this->get_validation_strategies() as $validation_strategy) {
1216
-            $validation_strategy->enqueue_js();
1217
-        }
1218
-    }
1219
-
1220
-
1221
-    /**
1222
-     * Gets the default value set on the input (not the current value, which may have been
1223
-     * changed because of a form submission). If no default was set, this us null.
1224
-     *
1225
-     * @return mixed
1226
-     */
1227
-    public function get_default()
1228
-    {
1229
-        return $this->_default;
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Makes this input disabled. That means it will have the HTML attribute 'disabled="disabled"',
1235
-     * and server-side if any input was received it will be ignored
1236
-     */
1237
-    public function disable($disable = true)
1238
-    {
1239
-        $disabled_attribute = ' disabled="disabled"';
1240
-        $this->disabled     = filter_var($disable, FILTER_VALIDATE_BOOLEAN);
1241
-        if ($this->disabled) {
1242
-            if (strpos($this->_other_html_attributes, $disabled_attribute) === false) {
1243
-                $this->_other_html_attributes .= $disabled_attribute;
1244
-            }
1245
-            $this->_set_normalized_value($this->get_default());
1246
-        } else {
1247
-            $this->_other_html_attributes = str_replace($disabled_attribute, '', $this->_other_html_attributes);
1248
-        }
1249
-    }
1250
-
1251
-
1252
-    /**
1253
-     * Returns whether this input is currently disabled.
1254
-     *
1255
-     * @return bool
1256
-     */
1257
-    public function isDisabled(): bool
1258
-    {
1259
-        return $this->disabled;
1260
-    }
1261
-
1262
-
1263
-    public function dataAttributes(): array
1264
-    {
1265
-        return $this->_data_attributes;
1266
-    }
1267
-
1268
-
1269
-    public function layoutContainerClass(): string
1270
-    {
1271
-        return $this->_layout_container_class;
1272
-    }
1273
-
1274
-
1275
-    public function extraContainerHtml(): string
1276
-    {
1277
-        return $this->_extra_container_html;
1278
-    }
17
+	/**
18
+	 * the input's name attribute
19
+	 *
20
+	 * @var string|null
21
+	 */
22
+	protected ?string $_html_name = null;
23
+
24
+	/**
25
+	 * id for the html label tag
26
+	 *
27
+	 * @var string
28
+	 */
29
+	protected $_html_label_id;
30
+
31
+	/**
32
+	 * class for teh html label tag
33
+	 *
34
+	 * @var string
35
+	 */
36
+	protected $_html_label_class;
37
+
38
+	/**
39
+	 * style for teh html label tag
40
+	 *
41
+	 * @var string
42
+	 */
43
+	protected $_html_label_style;
44
+
45
+	/**
46
+	 * text to be placed in the html label
47
+	 *
48
+	 * @var string
49
+	 */
50
+	protected $_html_label_text;
51
+
52
+	/**
53
+	 * the full html label. If used, all other html_label_* properties are invalid
54
+	 *
55
+	 * @var string
56
+	 */
57
+	protected $_html_label;
58
+
59
+	/**
60
+	 * HTML to use for help text (normally placed below form input), in a span which normally
61
+	 * has a class of 'description'
62
+	 *
63
+	 * @var string
64
+	 */
65
+	protected $_html_help_text;
66
+
67
+	/**
68
+	 * CSS classes for displaying the help span
69
+	 *
70
+	 * @var string
71
+	 */
72
+	protected $_html_help_class = 'description';
73
+
74
+	/**
75
+	 * CSS to put in the style attribute on the help span
76
+	 *
77
+	 * @var string
78
+	 */
79
+	protected $_html_help_style;
80
+
81
+	/**
82
+	 * Stores whether or not this input's response is required.
83
+	 * Because certain styling elements may also want to know that this
84
+	 * input is required etc.
85
+	 *
86
+	 * @var boolean
87
+	 */
88
+	protected $_required;
89
+
90
+	/**
91
+	 * css class added to required inputs
92
+	 *
93
+	 * @var string
94
+	 */
95
+	protected $_required_css_class = 'ee-required';
96
+
97
+	/**
98
+	 * css styles applied to button type inputs
99
+	 *
100
+	 * @var string
101
+	 */
102
+	protected $_button_css_attributes;
103
+
104
+	/**
105
+	 * The raw post data submitted for this
106
+	 * Generally unsafe for usage in client code
107
+	 *
108
+	 * @var mixed string or array
109
+	 */
110
+	protected $_raw_value;
111
+
112
+	/**
113
+	 * Value normalized according to the input's normalization strategy.
114
+	 * The normalization strategy dictates whether this is a string, int, float,
115
+	 * boolean, or array of any of those.
116
+	 *
117
+	 * @var mixed
118
+	 */
119
+	protected $_normalized_value;
120
+
121
+
122
+	/**
123
+	 * Normalized default value either initially set on the input, or provided by calling
124
+	 * set_default().
125
+	 *
126
+	 * @var mixed
127
+	 */
128
+	protected $_default;
129
+
130
+	/**
131
+	 * Strategy used for displaying this field.
132
+	 * Child classes must use _get_display_strategy to access it.
133
+	 *
134
+	 * @var EE_Display_Strategy_Base
135
+	 */
136
+	private $_display_strategy;
137
+
138
+	/**
139
+	 * Gets all the validation strategies used on this field
140
+	 *
141
+	 * @var EE_Validation_Strategy_Base[]
142
+	 */
143
+	private $_validation_strategies = [];
144
+
145
+	/**
146
+	 * The normalization strategy for this field
147
+	 *
148
+	 * @var EE_Normalization_Strategy_Base
149
+	 */
150
+	private $_normalization_strategy;
151
+
152
+	/**
153
+	 * Strategy for removing sensitive data after we're done with the form input
154
+	 *
155
+	 * @var EE_Sensitive_Data_Removal_Base
156
+	 */
157
+	protected $_sensitive_data_removal_strategy;
158
+
159
+	/**
160
+	 * Whether this input has been disabled or not.
161
+	 * If it's disabled while rendering, an extra hidden input is added that indicates it has been knowingly disabled.
162
+	 * (Client-side code that wants to dynamically disable it must also add this hidden input).
163
+	 * When the form is submitted, if the input is disabled in the PHP form section, then input is ignored.
164
+	 * If the input is missing from the request data but the hidden input indicating the input is disabled, then the
165
+	 * input is again ignored.
166
+	 *
167
+	 * @var boolean
168
+	 */
169
+	protected $disabled = false;
170
+
171
+	protected array $_data_attributes = [];
172
+
173
+	protected bool $_no_label = false; // if true, then no hrml label will be displayed for this input
174
+
175
+	/**
176
+	 * adds a class to the input's container
177
+	 *
178
+	 * @var string
179
+	 */
180
+	protected string $_layout_container_class = '';
181
+
182
+	/**
183
+	 * additional HTML to inject into the input's container
184
+	 *
185
+	 * @var string
186
+	 */
187
+	protected string $_extra_container_html = '';
188
+
189
+
190
+	/**
191
+	 * @param array                         $input_args       {
192
+	 * @type string                         $html_name        the html name for the input
193
+	 * @type string                         $html_label_id    the id attribute to give to the html label tag
194
+	 * @type string                         $html_label_class the class attribute to give to the html label tag
195
+	 * @type string                         $html_label_style the style attribute to give ot teh label tag
196
+	 * @type string                         $html_label_text  the text to put in the label tag
197
+	 * @type string                         $html_label       the full html label. If used,
198
+	 *                                                        all other html_label_* args are invalid
199
+	 * @type string                         $html_help_text   text to put in help element
200
+	 * @type string                         $html_help_style  style attribute to give to teh help element
201
+	 * @type string                         $html_help_class  class attribute to give to the help element
202
+	 * @type string                         $default          default value NORMALIZED (eg, if providing the default
203
+	 *                                                        for a Yes_No_Input, you should provide TRUE or FALSE, not
204
+	 *                                                        '1' or '0')
205
+	 * @type EE_Display_Strategy_Base       $display          strategy
206
+	 * @type EE_Normalization_Strategy_Base $normalization_strategy
207
+	 * @type EE_Validation_Strategy_Base[]  $validation_strategies
208
+	 * @type boolean                        $ignore_input     special argument which can be used to avoid adding any
209
+	 *                                                        validation strategies, and sets the normalization
210
+	 *                                                        strategy to the Null normalization. This is good when you
211
+	 *                                                        want the input to be totally ignored server-side (like
212
+	 *                                                        when using React.js form inputs)
213
+	 *                                                        }
214
+	 */
215
+	public function __construct($input_args = [])
216
+	{
217
+		$input_args = (array) apply_filters('FHEE__EE_Form_Input_Base___construct__input_args', $input_args, $this);
218
+		// the following properties must be cast as arrays
219
+		if (isset($input_args['validation_strategies'])) {
220
+			foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
221
+				if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
222
+					$this->_validation_strategies[ get_class($validation_strategy) ] = $validation_strategy;
223
+				}
224
+			}
225
+			unset($input_args['validation_strategies']);
226
+		}
227
+		if (isset($input_args['ignore_input'])) {
228
+			$this->_validation_strategies = [];
229
+		}
230
+		// loop thru incoming options
231
+		foreach ($input_args as $key => $value) {
232
+			if ($key === 'disabled') {
233
+				$this->disable($value);
234
+				continue;
235
+			}
236
+			$setter = 'set_' . $key;
237
+			if (method_exists($this, $setter)) {
238
+				$this->$setter($value);
239
+				unset($input_args[ $key ]);
240
+				continue;
241
+			}
242
+			// add underscore to $key to match property names
243
+			$_key = "_$key";
244
+			if (property_exists($this, $_key)) {
245
+				$this->{$_key} = $value;
246
+				unset($input_args[ $key ]);
247
+			}
248
+		}
249
+		// ensure that "required" is set correctly
250
+		$this->set_required(
251
+			$this->_required,
252
+			$input_args['required_validation_error_message'] ?? null
253
+		);
254
+		// $this->_html_name_specified = isset( $input_args['html_name'] ) ? TRUE : FALSE;
255
+		$this->_display_strategy->_construct_finalize($this);
256
+		foreach ($this->_validation_strategies as $validation_strategy) {
257
+			$validation_strategy->_construct_finalize($this);
258
+		}
259
+		if (isset($input_args['ignore_input'])) {
260
+			$this->_normalization_strategy = new EE_Null_Normalization();
261
+		}
262
+		if (! $this->_normalization_strategy) {
263
+			$this->_normalization_strategy = new EE_Text_Normalization();
264
+		}
265
+		$this->_normalization_strategy->_construct_finalize($this);
266
+		// at least we can use the normalization strategy to populate the default
267
+		if (isset($input_args['default'])) {
268
+			$this->set_default($input_args['default']);
269
+			unset($input_args['default']);
270
+		}
271
+		if (! $this->_sensitive_data_removal_strategy) {
272
+			$this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
273
+		}
274
+		$this->_sensitive_data_removal_strategy->_construct_finalize($this);
275
+		parent::__construct($input_args);
276
+	}
277
+
278
+
279
+	/**
280
+	 * Sets the html_name to its default value, if none was specified in teh constructor.
281
+	 * Calculation involves using the name and the parent's html_name
282
+	 *
283
+	 * @throws EE_Error
284
+	 */
285
+	protected function _set_default_html_name_if_empty()
286
+	{
287
+		if (! $this->_html_name) {
288
+			$this->_html_name = $this->name();
289
+			if ($this->_parent_section instanceof EE_Form_Section_Proper) {
290
+				$this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
291
+			}
292
+		}
293
+	}
294
+
295
+
296
+	/**
297
+	 * @param $parent_form_section
298
+	 * @param $name
299
+	 * @throws EE_Error
300
+	 */
301
+	public function _construct_finalize($parent_form_section, $name)
302
+	{
303
+		parent::_construct_finalize($parent_form_section, $name);
304
+		if ($this->_html_label === null && $this->_html_label_text === null && ! $this->_no_label) {
305
+			$this->_html_label_text = ucwords(str_replace("_", " ", $name));
306
+		}
307
+		do_action('AHEE__EE_Form_Input_Base___construct_finalize__end', $this, $parent_form_section, $name);
308
+	}
309
+
310
+
311
+	/**
312
+	 * Returns the strategy for displaying this form input. If none is set, throws an exception.
313
+	 *
314
+	 * @return EE_Display_Strategy_Base
315
+	 * @throws EE_Error
316
+	 */
317
+	protected function _get_display_strategy()
318
+	{
319
+		$this->ensure_construct_finalized_called();
320
+		if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
321
+			throw new EE_Error(
322
+				sprintf(
323
+					esc_html__(
324
+						"Cannot get display strategy for form input with name %s and id %s, because it has not been set in the constructor",
325
+						"event_espresso"
326
+					),
327
+					$this->html_name(),
328
+					$this->html_id()
329
+				)
330
+			);
331
+		} else {
332
+			return $this->_display_strategy;
333
+		}
334
+	}
335
+
336
+
337
+	/**
338
+	 * Sets the display strategy.
339
+	 *
340
+	 * @param EE_Display_Strategy_Base $strategy
341
+	 */
342
+	protected function _set_display_strategy(EE_Display_Strategy_Base $strategy)
343
+	{
344
+		$this->_display_strategy = $strategy;
345
+	}
346
+
347
+
348
+	/**
349
+	 * Sets the sanitization strategy
350
+	 *
351
+	 * @param EE_Normalization_Strategy_Base $strategy
352
+	 */
353
+	protected function _set_normalization_strategy(EE_Normalization_Strategy_Base $strategy)
354
+	{
355
+		$this->_normalization_strategy = $strategy;
356
+	}
357
+
358
+
359
+	/**
360
+	 * Gets sensitive_data_removal_strategy
361
+	 *
362
+	 * @return EE_Sensitive_Data_Removal_Base
363
+	 */
364
+	public function get_sensitive_data_removal_strategy()
365
+	{
366
+		return $this->_sensitive_data_removal_strategy;
367
+	}
368
+
369
+
370
+	/**
371
+	 * Sets sensitive_data_removal_strategy
372
+	 *
373
+	 * @param EE_Sensitive_Data_Removal_Base $sensitive_data_removal_strategy
374
+	 * @return void
375
+	 */
376
+	public function set_sensitive_data_removal_strategy($sensitive_data_removal_strategy)
377
+	{
378
+		$this->_sensitive_data_removal_strategy = $sensitive_data_removal_strategy;
379
+	}
380
+
381
+
382
+	/**
383
+	 * Gets the display strategy for this input
384
+	 *
385
+	 * @return EE_Display_Strategy_Base
386
+	 */
387
+	public function get_display_strategy()
388
+	{
389
+		return $this->_display_strategy;
390
+	}
391
+
392
+
393
+	/**
394
+	 * Overwrites the display strategy
395
+	 *
396
+	 * @param EE_Display_Strategy_Base $display_strategy
397
+	 */
398
+	public function set_display_strategy($display_strategy)
399
+	{
400
+		$this->_display_strategy = $display_strategy;
401
+		$this->_display_strategy->_construct_finalize($this);
402
+	}
403
+
404
+
405
+	/**
406
+	 * Gets the normalization strategy set on this input
407
+	 *
408
+	 * @return EE_Normalization_Strategy_Base
409
+	 */
410
+	public function get_normalization_strategy()
411
+	{
412
+		return $this->_normalization_strategy;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Overwrites the normalization strategy
418
+	 *
419
+	 * @param EE_Normalization_Strategy_Base $normalization_strategy
420
+	 */
421
+	public function set_normalization_strategy($normalization_strategy)
422
+	{
423
+		$this->_normalization_strategy = $normalization_strategy;
424
+		$this->_normalization_strategy->_construct_finalize($this);
425
+	}
426
+
427
+
428
+	/**
429
+	 * Returns all teh validation strategies which apply to this field, numerically indexed
430
+	 *
431
+	 * @return EE_Validation_Strategy_Base[]
432
+	 */
433
+	public function get_validation_strategies()
434
+	{
435
+		return $this->_validation_strategies;
436
+	}
437
+
438
+
439
+	/**
440
+	 * Adds this strategy to the field so it will be used in both JS validation and server-side validation
441
+	 *
442
+	 * @param EE_Validation_Strategy_Base $validation_strategy
443
+	 * @return void
444
+	 */
445
+	protected function _add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
446
+	{
447
+		$validation_strategy->_construct_finalize($this);
448
+		$this->_validation_strategies[] = $validation_strategy;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Adds a new validation strategy onto the form input
454
+	 *
455
+	 * @param EE_Validation_Strategy_Base $validation_strategy
456
+	 * @return void
457
+	 */
458
+	public function add_validation_strategy(EE_Validation_Strategy_Base $validation_strategy)
459
+	{
460
+		$this->_add_validation_strategy($validation_strategy);
461
+	}
462
+
463
+
464
+	/**
465
+	 * The classname of the validation strategy to remove
466
+	 *
467
+	 * @param string $validation_strategy_classname
468
+	 */
469
+	public function remove_validation_strategy($validation_strategy_classname)
470
+	{
471
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
472
+			if (
473
+				$validation_strategy instanceof $validation_strategy_classname
474
+				|| is_subclass_of($validation_strategy, $validation_strategy_classname)
475
+			) {
476
+				unset($this->_validation_strategies[ $key ]);
477
+			}
478
+		}
479
+	}
480
+
481
+
482
+	/**
483
+	 * returns true if input employs any of the validation strategy defined by the supplied array of classnames
484
+	 *
485
+	 * @param array $validation_strategy_classnames
486
+	 * @return bool
487
+	 */
488
+	public function has_validation_strategy($validation_strategy_classnames)
489
+	{
490
+		$validation_strategy_classnames = is_array($validation_strategy_classnames)
491
+			? $validation_strategy_classnames
492
+			: [$validation_strategy_classnames];
493
+		foreach ($this->_validation_strategies as $key => $validation_strategy) {
494
+			if (in_array($key, $validation_strategy_classnames)) {
495
+				return true;
496
+			}
497
+		}
498
+		return false;
499
+	}
500
+
501
+
502
+	/**
503
+	 * Gets the HTML
504
+	 *
505
+	 * @return string
506
+	 */
507
+	public function get_html()
508
+	{
509
+		return $this->_parent_section->get_html_for_input($this);
510
+	}
511
+
512
+
513
+	/**
514
+	 * Gets the HTML for the input itself (no label or errors) according to the
515
+	 * input's display strategy
516
+	 * Makes sure the JS and CSS are enqueued for it
517
+	 *
518
+	 * @return string
519
+	 * @throws EE_Error
520
+	 */
521
+	public function get_html_for_input()
522
+	{
523
+		return $this->_form_html_filter
524
+			? $this->_form_html_filter->filterHtml(
525
+				$this->_get_display_strategy()->display(),
526
+				$this
527
+			)
528
+			: $this->_get_display_strategy()->display();
529
+	}
530
+
531
+
532
+	/**
533
+	 * @return string
534
+	 */
535
+	public function html_other_attributes()
536
+	{
537
+		EE_Error::doing_it_wrong(
538
+			__METHOD__,
539
+			sprintf(
540
+				esc_html__(
541
+					'This method is no longer in use. You should replace it by %s',
542
+					'event_espresso'
543
+				),
544
+				'EE_Form_Section_Base::other_html_attributes()'
545
+			),
546
+			'4.10.2.p'
547
+		);
548
+
549
+		return $this->other_html_attributes();
550
+	}
551
+
552
+
553
+	/**
554
+	 * @param string $html_other_attributes
555
+	 */
556
+	public function set_html_other_attributes($html_other_attributes)
557
+	{
558
+		EE_Error::doing_it_wrong(
559
+			__METHOD__,
560
+			sprintf(
561
+				esc_html__(
562
+					'This method is no longer in use. You should replace it by %s',
563
+					'event_espresso'
564
+				),
565
+				'EE_Form_Section_Base::set_other_html_attributes()'
566
+			),
567
+			'4.10.2.p'
568
+		);
569
+
570
+		$this->set_other_html_attributes($html_other_attributes);
571
+	}
572
+
573
+
574
+	/**
575
+	 * Gets the HTML for displaying the label for this form input
576
+	 * according to the form section's layout strategy
577
+	 *
578
+	 * @return string
579
+	 * @throws EE_Error
580
+	 */
581
+	public function get_html_for_label()
582
+	{
583
+		return $this->_parent_section->get_layout_strategy()->display_label($this);
584
+	}
585
+
586
+
587
+	/**
588
+	 * Gets the HTML for displaying the errors section for this form input
589
+	 * according to the form section's layout strategy
590
+	 *
591
+	 * @return string
592
+	 * @throws EE_Error
593
+	 */
594
+	public function get_html_for_errors()
595
+	{
596
+		return $this->_parent_section->get_layout_strategy()->display_errors($this);
597
+	}
598
+
599
+
600
+	/**
601
+	 * Gets the HTML for displaying the help text for this form input
602
+	 * according to the form section's layout strategy
603
+	 *
604
+	 * @return string
605
+	 * @throws EE_Error
606
+	 */
607
+	public function get_html_for_help()
608
+	{
609
+		return $this->_parent_section->get_layout_strategy()->display_help_text($this);
610
+	}
611
+
612
+
613
+	/**
614
+	 * Validates the input's sanitized value (assumes _sanitize() has already been called)
615
+	 * and returns whether or not the form input's submitted value is value
616
+	 *
617
+	 * @return boolean
618
+	 */
619
+	protected function _validate()
620
+	{
621
+		if ($this->isDisabled()) {
622
+			return true;
623
+		}
624
+		foreach ($this->_validation_strategies as $validation_strategy) {
625
+			if ($validation_strategy instanceof EE_Validation_Strategy_Base) {
626
+				try {
627
+					$validation_strategy->validate($this->normalized_value());
628
+				} catch (EE_Validation_Error $e) {
629
+					$this->add_validation_error($e);
630
+				}
631
+			}
632
+		}
633
+		if ($this->get_validation_errors()) {
634
+			return false;
635
+		} else {
636
+			return true;
637
+		}
638
+	}
639
+
640
+
641
+	/**
642
+	 * Performs basic sanitization on this value. But what sanitization can be performed anyways?
643
+	 * This value MIGHT be allowed to have tags, so we can't really remove them.
644
+	 *
645
+	 * @param string $value
646
+	 * @return null|string
647
+	 */
648
+	protected function _sanitize($value)
649
+	{
650
+		return $value !== null
651
+			? stripslashes(html_entity_decode(trim((string) $value)))
652
+			: null;
653
+	}
654
+
655
+
656
+	/**
657
+	 * Picks out the form value that relates to this form input,
658
+	 * and stores it as the sanitized value on the form input, and sets the normalized value.
659
+	 * Returns whether or not any validation errors occurred
660
+	 *
661
+	 * @param array $req_data
662
+	 * @return boolean whether or not there was an error
663
+	 * @throws EE_Error
664
+	 */
665
+	protected function _normalize($req_data)
666
+	{
667
+		// any existing validation errors don't apply so clear them
668
+		$this->_validation_errors = [];
669
+		// if the input is disabled, ignore whatever input was sent in
670
+		if ($this->isDisabled()) {
671
+			$this->_set_raw_value(null);
672
+			$this->_set_normalized_value($this->get_default());
673
+			return false;
674
+		}
675
+		try {
676
+			$raw_input = $this->find_form_data_for_this_section($req_data);
677
+			// super simple sanitization for now
678
+			if (is_array($raw_input)) {
679
+				$raw_value = [];
680
+				foreach ($raw_input as $key => $value) {
681
+					$raw_value[ $key ] = $this->_sanitize($value);
682
+				}
683
+				$this->_set_raw_value($raw_value);
684
+			} else {
685
+				$this->_set_raw_value($this->_sanitize($raw_input));
686
+			}
687
+			// we want to mostly leave the input alone in case we need to re-display it to the user
688
+			$this->_set_normalized_value($this->_normalization_strategy->normalize($this->raw_value()));
689
+			return false;
690
+		} catch (EE_Validation_Error $e) {
691
+			$this->add_validation_error($e);
692
+			return true;
693
+		}
694
+	}
695
+
696
+
697
+	/**
698
+	 * @return string
699
+	 * @throws EE_Error
700
+	 */
701
+	public function html_name()
702
+	{
703
+		$this->_set_default_html_name_if_empty();
704
+		return $this->_html_name ?? '';
705
+	}
706
+
707
+
708
+	/**
709
+	 * @return string
710
+	 * @throws EE_Error
711
+	 */
712
+	public function html_label_id()
713
+	{
714
+		return ! empty($this->_html_label_id)
715
+			? $this->_html_label_id
716
+			: $this->html_id() . '-lbl';
717
+	}
718
+
719
+
720
+	/**
721
+	 * @return string
722
+	 */
723
+	public function html_label_class()
724
+	{
725
+		return $this->_html_label_class ?? '';
726
+	}
727
+
728
+
729
+	/**
730
+	 * @param string $html_class
731
+	 */
732
+	public function add_html_label_class(string $html_class)
733
+	{
734
+		$this->_html_label_class .= ' ' . trim($html_class);
735
+	}
736
+
737
+
738
+	/**
739
+	 * @return string
740
+	 */
741
+	public function html_label_style()
742
+	{
743
+		return $this->_html_label_style ?? '';
744
+	}
745
+
746
+
747
+	/**
748
+	 * @return string
749
+	 */
750
+	public function html_label_text()
751
+	{
752
+		return $this->_html_label_text ?? '';
753
+	}
754
+
755
+
756
+	/**
757
+	 * @return string
758
+	 */
759
+	public function html_help_text()
760
+	{
761
+		return $this->_html_help_text ?? '';
762
+	}
763
+
764
+
765
+	/**
766
+	 * @return string
767
+	 */
768
+	public function html_help_class()
769
+	{
770
+		return $this->_html_help_class ?? '';
771
+	}
772
+
773
+
774
+	/**
775
+	 * @return string
776
+	 */
777
+	public function html_help_style()
778
+	{
779
+		return $this->_html_style ?? '';
780
+	}
781
+
782
+
783
+	/**
784
+	 * returns the raw, UNSAFE, input, almost exactly as the user submitted it.
785
+	 * Please note that almost all client code should instead use the normalized_value;
786
+	 * or possibly raw_value_in_form (which prepares the string for displaying in an HTML attribute on a tag,
787
+	 * mostly by escaping quotes)
788
+	 * Note, we do not store the exact original value sent in the user's request because
789
+	 * it may have malicious content, and we MIGHT want to store the form input in a transient or something...
790
+	 * in which case, we would have stored the malicious content to our database.
791
+	 *
792
+	 * @return mixed
793
+	 */
794
+	public function raw_value()
795
+	{
796
+		return $this->_raw_value;
797
+	}
798
+
799
+
800
+	/**
801
+	 * Returns a string safe to usage in form inputs when displaying, because
802
+	 * it escapes all html entities
803
+	 *
804
+	 * @return string
805
+	 */
806
+	public function raw_value_in_form(): string
807
+	{
808
+		return htmlentities((string) $this->raw_value(), ENT_QUOTES, 'UTF-8');
809
+	}
810
+
811
+
812
+	/**
813
+	 * returns the value after it's been sanitized, and then converted into it's proper type
814
+	 * in PHP. Eg, a string, an int, an array,
815
+	 *
816
+	 * @return mixed
817
+	 */
818
+	public function normalized_value()
819
+	{
820
+		return $this->_normalized_value;
821
+	}
822
+
823
+
824
+	/**
825
+	 * Returns the normalized value is a presentable way. By default this is just
826
+	 * the normalized value by itself, but it can be overridden for when that's not
827
+	 * the best thing to display
828
+	 *
829
+	 * @return mixed
830
+	 */
831
+	public function pretty_value()
832
+	{
833
+		return $this->_normalized_value;
834
+	}
835
+
836
+
837
+	/**
838
+	 * When generating the JS for the jquery validation rules like<br>
839
+	 * <code>$( "#myform" ).validate({
840
+	 * rules: {
841
+	 * password: "required",
842
+	 * password_again: {
843
+	 * equalTo: "#password"
844
+	 * }
845
+	 * }
846
+	 * });</code>
847
+	 * if this field had the name 'password_again', it should return
848
+	 * <br><code>password_again: {
849
+	 * equalTo: "#password"
850
+	 * }</code>
851
+	 *
852
+	 * @return array
853
+	 * @throws EE_Error
854
+	 */
855
+	public function get_jquery_validation_rules(): array
856
+	{
857
+		$jquery_validation_js    = [];
858
+		$jquery_validation_rules = [];
859
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
860
+			$jquery_validation_rules = array_replace_recursive(
861
+				$jquery_validation_rules,
862
+				$validation_strategy->get_jquery_validation_rule_array()
863
+			);
864
+		}
865
+		if (! empty($jquery_validation_rules)) {
866
+			foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
867
+				$jquery_validation_js[ $html_id_with_pound_sign ] = $jquery_validation_rules;
868
+			}
869
+		}
870
+		return $jquery_validation_js;
871
+	}
872
+
873
+
874
+	/**
875
+	 * Sets the input's default value for use in displaying in the form. Note: value should be
876
+	 * normalized (Eg, if providing a default of ra Yes_NO_Input you would provide TRUE or FALSE, not '1' or '0')
877
+	 *
878
+	 * @param mixed $value
879
+	 * @return void
880
+	 */
881
+	public function set_default($value)
882
+	{
883
+		$this->_default = $value;
884
+		$this->_set_normalized_value($value);
885
+		$this->_set_raw_value($value);
886
+	}
887
+
888
+
889
+	/**
890
+	 * Sets the normalized value on this input
891
+	 *
892
+	 * @param mixed $value
893
+	 */
894
+	protected function _set_normalized_value($value)
895
+	{
896
+		$this->_normalized_value = $value;
897
+	}
898
+
899
+
900
+	/**
901
+	 * Sets the raw value on this input (ie, exactly as the user submitted it)
902
+	 *
903
+	 * @param mixed $value
904
+	 */
905
+	protected function _set_raw_value($value)
906
+	{
907
+		$this->_raw_value = $this->_normalization_strategy->unnormalize($value);
908
+	}
909
+
910
+
911
+	/**
912
+	 * Sets the HTML label text after it has already been defined
913
+	 *
914
+	 * @param string $label
915
+	 * @return void
916
+	 */
917
+	public function set_html_label_text($label)
918
+	{
919
+		$this->_html_label_text = $label;
920
+	}
921
+
922
+
923
+	/**
924
+	 * Sets whether or not this field is required, and adjusts the validation strategy.
925
+	 * If you want to use the EE_Conditionally_Required_Validation_Strategy,
926
+	 * please add it as a validation strategy using add_validation_strategy as normal
927
+	 *
928
+	 * @param boolean $required boolean
929
+	 * @param null    $required_text
930
+	 */
931
+	public function set_required($required = true, $required_text = null)
932
+	{
933
+		$required = filter_var($required, FILTER_VALIDATE_BOOLEAN);
934
+		// whether $required is a string or a boolean, we want to add a required validation strategy
935
+		if ($required) {
936
+			$this->_add_validation_strategy(new EE_Required_Validation_Strategy($required_text));
937
+		} else {
938
+			$this->remove_validation_strategy('EE_Required_Validation_Strategy');
939
+		}
940
+		$this->_required = $required;
941
+	}
942
+
943
+
944
+	/**
945
+	 * Returns whether or not this field is required
946
+	 *
947
+	 * @return boolean
948
+	 */
949
+	public function required()
950
+	{
951
+		return $this->_required;
952
+	}
953
+
954
+
955
+	/**
956
+	 * @param string $required_css_class
957
+	 */
958
+	public function set_required_css_class($required_css_class)
959
+	{
960
+		$this->_required_css_class = $required_css_class;
961
+	}
962
+
963
+
964
+	/**
965
+	 * @return string
966
+	 */
967
+	public function required_css_class()
968
+	{
969
+		return $this->_required_css_class;
970
+	}
971
+
972
+
973
+	/**
974
+	 * @param bool $add_required
975
+	 * @return string
976
+	 */
977
+	public function html_class($add_required = false)
978
+	{
979
+		return $add_required && $this->required()
980
+			? $this->required_css_class() . ' ' . $this->_html_class
981
+			: $this->_html_class;
982
+	}
983
+
984
+
985
+	/**
986
+	 * Sets the help text, in case
987
+	 *
988
+	 * @param string $text
989
+	 */
990
+	public function set_html_help_text($text)
991
+	{
992
+		$this->_html_help_text = $text;
993
+	}
994
+
995
+
996
+	/**
997
+	 * Uses the sensitive data removal strategy to remove the sensitive data from this
998
+	 * input. If there is any kind of sensitive data removal on this input, we clear
999
+	 * out the raw value completely
1000
+	 *
1001
+	 * @return void
1002
+	 */
1003
+	public function clean_sensitive_data()
1004
+	{
1005
+		// if we do ANY kind of sensitive data removal on this, then just clear out the raw value
1006
+		// if we need more logic than this we'll make a strategy for it
1007
+		if (
1008
+			$this->_sensitive_data_removal_strategy
1009
+			&& ! $this->_sensitive_data_removal_strategy instanceof EE_No_Sensitive_Data_Removal
1010
+		) {
1011
+			$this->_set_raw_value(null);
1012
+		}
1013
+		// and clean the normalized value according to the appropriate strategy
1014
+		$this->_set_normalized_value(
1015
+			$this->get_sensitive_data_removal_strategy()->remove_sensitive_data(
1016
+				$this->_normalized_value
1017
+			)
1018
+		);
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * @param bool   $primary
1024
+	 * @param string $button_size
1025
+	 * @param string $other_attributes
1026
+	 */
1027
+	public function set_button_css_attributes($primary = true, $button_size = '', $other_attributes = '')
1028
+	{
1029
+		$button_css_attributes = 'button';
1030
+		$button_css_attributes .= $primary === true
1031
+			? ' button--primary'
1032
+			: ' button--secondary';
1033
+		switch ($button_size) {
1034
+			case 'xs':
1035
+			case 'extra-small':
1036
+				$button_css_attributes .= ' button-xs';
1037
+				break;
1038
+			case 'sm':
1039
+			case 'small':
1040
+				$button_css_attributes .= ' button-sm';
1041
+				break;
1042
+			case 'lg':
1043
+			case 'large':
1044
+				$button_css_attributes .= ' button-lg';
1045
+				break;
1046
+			case 'block':
1047
+				$button_css_attributes .= ' button-block';
1048
+				break;
1049
+			case 'md':
1050
+			case 'medium':
1051
+			default:
1052
+				$button_css_attributes .= '';
1053
+		}
1054
+		$this->_button_css_attributes .= ! empty($other_attributes)
1055
+			? $button_css_attributes . ' ' . $other_attributes
1056
+			: $button_css_attributes;
1057
+	}
1058
+
1059
+
1060
+	/**
1061
+	 * @return string
1062
+	 */
1063
+	public function button_css_attributes()
1064
+	{
1065
+		if (empty($this->_button_css_attributes)) {
1066
+			$this->set_button_css_attributes();
1067
+		}
1068
+		return $this->_button_css_attributes;
1069
+	}
1070
+
1071
+
1072
+	/**
1073
+	 * find_form_data_for_this_section
1074
+	 * using this section's name and its parents, finds the value of the form data that corresponds to it.
1075
+	 * For example, if this form section's HTML name is my_form[subform][form_input_1],
1076
+	 * then it's value should be in request at request['my_form']['subform']['form_input_1'].
1077
+	 * (If that doesn't exist, we also check for this subsection's name
1078
+	 * at the TOP LEVEL of the request data. Eg request['form_input_1'].)
1079
+	 * This function finds its value in the form.
1080
+	 *
1081
+	 * @param array $req_data
1082
+	 * @return mixed whatever the raw value of this form section is in the request data
1083
+	 * @throws EE_Error
1084
+	 */
1085
+	public function find_form_data_for_this_section($req_data)
1086
+	{
1087
+		$name_parts = $this->getInputNameParts();
1088
+		// now get the value for the input
1089
+		$value = $this->findRequestForSectionUsingNameParts($name_parts, $req_data);
1090
+		// check if this thing's name is at the TOP level of the request data
1091
+		if ($value === null && isset($req_data[ $this->name() ])) {
1092
+			$value = $req_data[ $this->name() ];
1093
+		}
1094
+		return $value;
1095
+	}
1096
+
1097
+
1098
+	/**
1099
+	 * If this input's name is something like "foo[bar][baz]"
1100
+	 * returns an array like `array('foo','bar',baz')`
1101
+	 *
1102
+	 * @return array
1103
+	 * @throws EE_Error
1104
+	 */
1105
+	protected function getInputNameParts()
1106
+	{
1107
+		// break up the html name by "[]"
1108
+		if (strpos($this->html_name(), '[') !== false) {
1109
+			$before_any_brackets = substr($this->html_name(), 0, strpos($this->html_name(), '['));
1110
+		} else {
1111
+			$before_any_brackets = $this->html_name();
1112
+		}
1113
+		// grab all of the segments
1114
+		preg_match_all('~\[([^]]*)\]~', $this->html_name(), $matches);
1115
+		if (isset($matches[1]) && is_array($matches[1])) {
1116
+			$name_parts = $matches[1];
1117
+			array_unshift($name_parts, $before_any_brackets);
1118
+		} else {
1119
+			$name_parts = [$before_any_brackets];
1120
+		}
1121
+		return $name_parts;
1122
+	}
1123
+
1124
+
1125
+	/**
1126
+	 * @param array $html_name_parts
1127
+	 * @param array $req_data
1128
+	 * @return array | NULL
1129
+	 */
1130
+	public function findRequestForSectionUsingNameParts($html_name_parts, $req_data)
1131
+	{
1132
+		$first_part_to_consider = array_shift($html_name_parts);
1133
+		if (isset($req_data[ $first_part_to_consider ])) {
1134
+			if (empty($html_name_parts)) {
1135
+				return $req_data[ $first_part_to_consider ];
1136
+			} else {
1137
+				return $this->findRequestForSectionUsingNameParts(
1138
+					$html_name_parts,
1139
+					$req_data[ $first_part_to_consider ]
1140
+				);
1141
+			}
1142
+		}
1143
+		return null;
1144
+	}
1145
+
1146
+
1147
+	/**
1148
+	 * Checks if this form input's data is in the request data
1149
+	 *
1150
+	 * @param array $req_data
1151
+	 * @return boolean
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	public function form_data_present_in($req_data = null)
1155
+	{
1156
+		if ($req_data === null) {
1157
+			/** @var RequestInterface $request */
1158
+			$request  = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1159
+			$req_data = $request->postParams();
1160
+		}
1161
+
1162
+		return $this->find_form_data_for_this_section($req_data) !== null;
1163
+	}
1164
+
1165
+
1166
+	/**
1167
+	 * Overrides parent to add js data from validation and display strategies
1168
+	 *
1169
+	 * @param array $form_other_js_data
1170
+	 * @return array
1171
+	 */
1172
+	public function get_other_js_data($form_other_js_data = [])
1173
+	{
1174
+		return $this->get_other_js_data_from_strategies($form_other_js_data);
1175
+	}
1176
+
1177
+
1178
+	/**
1179
+	 * Gets other JS data for localization from this input's strategies, like
1180
+	 * the validation strategies and the display strategy
1181
+	 *
1182
+	 * @param array $form_other_js_data
1183
+	 * @return array
1184
+	 */
1185
+	public function get_other_js_data_from_strategies($form_other_js_data = [])
1186
+	{
1187
+		$form_other_js_data = $this->get_display_strategy()->get_other_js_data($form_other_js_data);
1188
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1189
+			$form_other_js_data = $validation_strategy->get_other_js_data($form_other_js_data);
1190
+		}
1191
+		return $form_other_js_data;
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * Override parent because we want to give our strategies an opportunity to enqueue some js and css
1197
+	 *
1198
+	 * @return void
1199
+	 */
1200
+	public function enqueue_js()
1201
+	{
1202
+		// ask our display strategy and validation strategies if they have js to enqueue
1203
+		$this->enqueue_js_from_strategies();
1204
+	}
1205
+
1206
+
1207
+	/**
1208
+	 * Tells strategies when its ok to enqueue their js and css
1209
+	 *
1210
+	 * @return void
1211
+	 */
1212
+	public function enqueue_js_from_strategies()
1213
+	{
1214
+		$this->get_display_strategy()->enqueue_js();
1215
+		foreach ($this->get_validation_strategies() as $validation_strategy) {
1216
+			$validation_strategy->enqueue_js();
1217
+		}
1218
+	}
1219
+
1220
+
1221
+	/**
1222
+	 * Gets the default value set on the input (not the current value, which may have been
1223
+	 * changed because of a form submission). If no default was set, this us null.
1224
+	 *
1225
+	 * @return mixed
1226
+	 */
1227
+	public function get_default()
1228
+	{
1229
+		return $this->_default;
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Makes this input disabled. That means it will have the HTML attribute 'disabled="disabled"',
1235
+	 * and server-side if any input was received it will be ignored
1236
+	 */
1237
+	public function disable($disable = true)
1238
+	{
1239
+		$disabled_attribute = ' disabled="disabled"';
1240
+		$this->disabled     = filter_var($disable, FILTER_VALIDATE_BOOLEAN);
1241
+		if ($this->disabled) {
1242
+			if (strpos($this->_other_html_attributes, $disabled_attribute) === false) {
1243
+				$this->_other_html_attributes .= $disabled_attribute;
1244
+			}
1245
+			$this->_set_normalized_value($this->get_default());
1246
+		} else {
1247
+			$this->_other_html_attributes = str_replace($disabled_attribute, '', $this->_other_html_attributes);
1248
+		}
1249
+	}
1250
+
1251
+
1252
+	/**
1253
+	 * Returns whether this input is currently disabled.
1254
+	 *
1255
+	 * @return bool
1256
+	 */
1257
+	public function isDisabled(): bool
1258
+	{
1259
+		return $this->disabled;
1260
+	}
1261
+
1262
+
1263
+	public function dataAttributes(): array
1264
+	{
1265
+		return $this->_data_attributes;
1266
+	}
1267
+
1268
+
1269
+	public function layoutContainerClass(): string
1270
+	{
1271
+		return $this->_layout_container_class;
1272
+	}
1273
+
1274
+
1275
+	public function extraContainerHtml(): string
1276
+	{
1277
+		return $this->_extra_container_html;
1278
+	}
1279 1279
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
         if (isset($input_args['validation_strategies'])) {
220 220
             foreach ((array) $input_args['validation_strategies'] as $validation_strategy) {
221 221
                 if ($validation_strategy instanceof EE_Validation_Strategy_Base && empty($input_args['ignore_input'])) {
222
-                    $this->_validation_strategies[ get_class($validation_strategy) ] = $validation_strategy;
222
+                    $this->_validation_strategies[get_class($validation_strategy)] = $validation_strategy;
223 223
                 }
224 224
             }
225 225
             unset($input_args['validation_strategies']);
@@ -233,17 +233,17 @@  discard block
 block discarded – undo
233 233
                 $this->disable($value);
234 234
                 continue;
235 235
             }
236
-            $setter = 'set_' . $key;
236
+            $setter = 'set_'.$key;
237 237
             if (method_exists($this, $setter)) {
238 238
                 $this->$setter($value);
239
-                unset($input_args[ $key ]);
239
+                unset($input_args[$key]);
240 240
                 continue;
241 241
             }
242 242
             // add underscore to $key to match property names
243 243
             $_key = "_$key";
244 244
             if (property_exists($this, $_key)) {
245 245
                 $this->{$_key} = $value;
246
-                unset($input_args[ $key ]);
246
+                unset($input_args[$key]);
247 247
             }
248 248
         }
249 249
         // ensure that "required" is set correctly
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
         if (isset($input_args['ignore_input'])) {
260 260
             $this->_normalization_strategy = new EE_Null_Normalization();
261 261
         }
262
-        if (! $this->_normalization_strategy) {
262
+        if ( ! $this->_normalization_strategy) {
263 263
             $this->_normalization_strategy = new EE_Text_Normalization();
264 264
         }
265 265
         $this->_normalization_strategy->_construct_finalize($this);
@@ -268,7 +268,7 @@  discard block
 block discarded – undo
268 268
             $this->set_default($input_args['default']);
269 269
             unset($input_args['default']);
270 270
         }
271
-        if (! $this->_sensitive_data_removal_strategy) {
271
+        if ( ! $this->_sensitive_data_removal_strategy) {
272 272
             $this->_sensitive_data_removal_strategy = new EE_No_Sensitive_Data_Removal();
273 273
         }
274 274
         $this->_sensitive_data_removal_strategy->_construct_finalize($this);
@@ -284,10 +284,10 @@  discard block
 block discarded – undo
284 284
      */
285 285
     protected function _set_default_html_name_if_empty()
286 286
     {
287
-        if (! $this->_html_name) {
287
+        if ( ! $this->_html_name) {
288 288
             $this->_html_name = $this->name();
289 289
             if ($this->_parent_section instanceof EE_Form_Section_Proper) {
290
-                $this->_html_name = $this->_parent_section->html_name_prefix() . "[{$this->name()}]";
290
+                $this->_html_name = $this->_parent_section->html_name_prefix()."[{$this->name()}]";
291 291
             }
292 292
         }
293 293
     }
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
     protected function _get_display_strategy()
318 318
     {
319 319
         $this->ensure_construct_finalized_called();
320
-        if (! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
320
+        if ( ! $this->_display_strategy || ! $this->_display_strategy instanceof EE_Display_Strategy_Base) {
321 321
             throw new EE_Error(
322 322
                 sprintf(
323 323
                     esc_html__(
@@ -473,7 +473,7 @@  discard block
 block discarded – undo
473 473
                 $validation_strategy instanceof $validation_strategy_classname
474 474
                 || is_subclass_of($validation_strategy, $validation_strategy_classname)
475 475
             ) {
476
-                unset($this->_validation_strategies[ $key ]);
476
+                unset($this->_validation_strategies[$key]);
477 477
             }
478 478
         }
479 479
     }
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
             if (is_array($raw_input)) {
679 679
                 $raw_value = [];
680 680
                 foreach ($raw_input as $key => $value) {
681
-                    $raw_value[ $key ] = $this->_sanitize($value);
681
+                    $raw_value[$key] = $this->_sanitize($value);
682 682
                 }
683 683
                 $this->_set_raw_value($raw_value);
684 684
             } else {
@@ -713,7 +713,7 @@  discard block
 block discarded – undo
713 713
     {
714 714
         return ! empty($this->_html_label_id)
715 715
             ? $this->_html_label_id
716
-            : $this->html_id() . '-lbl';
716
+            : $this->html_id().'-lbl';
717 717
     }
718 718
 
719 719
 
@@ -731,7 +731,7 @@  discard block
 block discarded – undo
731 731
      */
732 732
     public function add_html_label_class(string $html_class)
733 733
     {
734
-        $this->_html_label_class .= ' ' . trim($html_class);
734
+        $this->_html_label_class .= ' '.trim($html_class);
735 735
     }
736 736
 
737 737
 
@@ -862,9 +862,9 @@  discard block
 block discarded – undo
862 862
                 $validation_strategy->get_jquery_validation_rule_array()
863 863
             );
864 864
         }
865
-        if (! empty($jquery_validation_rules)) {
865
+        if ( ! empty($jquery_validation_rules)) {
866 866
             foreach ($this->get_display_strategy()->get_html_input_ids(true) as $html_id_with_pound_sign) {
867
-                $jquery_validation_js[ $html_id_with_pound_sign ] = $jquery_validation_rules;
867
+                $jquery_validation_js[$html_id_with_pound_sign] = $jquery_validation_rules;
868 868
             }
869 869
         }
870 870
         return $jquery_validation_js;
@@ -977,7 +977,7 @@  discard block
 block discarded – undo
977 977
     public function html_class($add_required = false)
978 978
     {
979 979
         return $add_required && $this->required()
980
-            ? $this->required_css_class() . ' ' . $this->_html_class
980
+            ? $this->required_css_class().' '.$this->_html_class
981 981
             : $this->_html_class;
982 982
     }
983 983
 
@@ -1052,7 +1052,7 @@  discard block
 block discarded – undo
1052 1052
                 $button_css_attributes .= '';
1053 1053
         }
1054 1054
         $this->_button_css_attributes .= ! empty($other_attributes)
1055
-            ? $button_css_attributes . ' ' . $other_attributes
1055
+            ? $button_css_attributes.' '.$other_attributes
1056 1056
             : $button_css_attributes;
1057 1057
     }
1058 1058
 
@@ -1088,8 +1088,8 @@  discard block
 block discarded – undo
1088 1088
         // now get the value for the input
1089 1089
         $value = $this->findRequestForSectionUsingNameParts($name_parts, $req_data);
1090 1090
         // check if this thing's name is at the TOP level of the request data
1091
-        if ($value === null && isset($req_data[ $this->name() ])) {
1092
-            $value = $req_data[ $this->name() ];
1091
+        if ($value === null && isset($req_data[$this->name()])) {
1092
+            $value = $req_data[$this->name()];
1093 1093
         }
1094 1094
         return $value;
1095 1095
     }
@@ -1130,13 +1130,13 @@  discard block
 block discarded – undo
1130 1130
     public function findRequestForSectionUsingNameParts($html_name_parts, $req_data)
1131 1131
     {
1132 1132
         $first_part_to_consider = array_shift($html_name_parts);
1133
-        if (isset($req_data[ $first_part_to_consider ])) {
1133
+        if (isset($req_data[$first_part_to_consider])) {
1134 1134
             if (empty($html_name_parts)) {
1135
-                return $req_data[ $first_part_to_consider ];
1135
+                return $req_data[$first_part_to_consider];
1136 1136
             } else {
1137 1137
                 return $this->findRequestForSectionUsingNameParts(
1138 1138
                     $html_name_parts,
1139
-                    $req_data[ $first_part_to_consider ]
1139
+                    $req_data[$first_part_to_consider]
1140 1140
                 );
1141 1141
             }
1142 1142
         }
Please login to merge, or discard this patch.
strategies/display/EE_Admin_File_Uploader_Display_Strategy.strategy.php 2 patches
Indentation   +89 added lines, -89 removed lines patch added patch discarded remove patch
@@ -10,100 +10,100 @@
 block discarded – undo
10 10
  */
11 11
 class EE_Admin_File_Uploader_Display_Strategy extends EE_Display_Strategy_Base
12 12
 {
13
-    /**
14
-     * Its important this media only get enqueued AFTER init, but before the footer... where the
15
-     * rest of our forms JS gets enqueued. Otherwise the JS gets enqueued fine, and loaded on the page fine,
16
-     * but when you upload an image it gets uploaded fine to the server, but it doesn't display and reports an error
17
-     * (also it doesn't show any of the currently existing media in the modal window that pops up when you click the
18
-     * button to select media). Besides that, no special consideration should be required to make the media uploader
19
-     * appear, besides having this input displayed.
20
-     *
21
-     * @deprecated enqueue_js should be called automatically now
22
-     */
23
-    public static function enqueue_scripts()
24
-    {
25
-        EE_Error::doing_it_wrong(
26
-            __FUNCTION__,
27
-            esc_html__(
28
-                'EE_Admin_File_Uploader_Display_Strategy::enqueue_scripts() no longer needs to be called in order to display the admin uploader input correctly. This is handled now by EE_Admin_File_Uploader_Display_Strategy::enqueue_js() which is called automatically when enqueueing JS and CSS for the form',
29
-                'event_espresso'
30
-            ),
31
-            '4.9.8.rc.015'
32
-        );
33
-        wp_enqueue_media();
34
-        wp_enqueue_script('media-upload');
35
-        wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL . 'scripts/ee-media-uploader.js');
36
-    }
13
+	/**
14
+	 * Its important this media only get enqueued AFTER init, but before the footer... where the
15
+	 * rest of our forms JS gets enqueued. Otherwise the JS gets enqueued fine, and loaded on the page fine,
16
+	 * but when you upload an image it gets uploaded fine to the server, but it doesn't display and reports an error
17
+	 * (also it doesn't show any of the currently existing media in the modal window that pops up when you click the
18
+	 * button to select media). Besides that, no special consideration should be required to make the media uploader
19
+	 * appear, besides having this input displayed.
20
+	 *
21
+	 * @deprecated enqueue_js should be called automatically now
22
+	 */
23
+	public static function enqueue_scripts()
24
+	{
25
+		EE_Error::doing_it_wrong(
26
+			__FUNCTION__,
27
+			esc_html__(
28
+				'EE_Admin_File_Uploader_Display_Strategy::enqueue_scripts() no longer needs to be called in order to display the admin uploader input correctly. This is handled now by EE_Admin_File_Uploader_Display_Strategy::enqueue_js() which is called automatically when enqueueing JS and CSS for the form',
29
+				'event_espresso'
30
+			),
31
+			'4.9.8.rc.015'
32
+		);
33
+		wp_enqueue_media();
34
+		wp_enqueue_script('media-upload');
35
+		wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL . 'scripts/ee-media-uploader.js');
36
+	}
37 37
 
38 38
 
39
-    /**
40
-     * Enqueues the JS and CSS needed to display this input
41
-     */
42
-    public function enqueue_js()
43
-    {
44
-        wp_enqueue_media();
45
-        wp_enqueue_script('media-upload');
46
-        wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL . 'scripts/ee-media-uploader.js');
47
-        parent::enqueue_js();
48
-    }
39
+	/**
40
+	 * Enqueues the JS and CSS needed to display this input
41
+	 */
42
+	public function enqueue_js()
43
+	{
44
+		wp_enqueue_media();
45
+		wp_enqueue_script('media-upload');
46
+		wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL . 'scripts/ee-media-uploader.js');
47
+		parent::enqueue_js();
48
+	}
49 49
 
50 50
 
51
-    /**
52
-     * @return string of html to display the field
53
-     * @throws EE_Error
54
-     */
51
+	/**
52
+	 * @return string of html to display the field
53
+	 * @throws EE_Error
54
+	 */
55 55
 
56
-    public function display(): string
57
-    {
58
-        // the actual input
59
-        $input = '<input type="text" size="34" ';
60
-        $input .= 'name="' . $this->_input->html_name() . '" ';
61
-        $input .= $this->_input->html_class() !== ''
62
-            ? 'class="large-text ee_media_url ' . $this->_input->html_class() . '" '
63
-            : 'class="large-text ee_media_url" ';
64
-        $input .= 'value="' . $this->_input->raw_value_in_form() . '" ';
65
-        $input .= $this->_input->other_html_attributes();
66
-        $input .= $this->dataAttributesString($this->_input->dataAttributes());
67
-        $input .= '>';
68
-        // image uploader
69
-        $uploader = EEH_HTML::link(
70
-            '#',
71
-            '<span class="dashicons dashicons-format-image"></span>',
72
-            esc_html__('click to add an image', 'event_espresso'),
73
-            '',
74
-            'ee_media_upload button button--secondary button--icon-only'
75
-        );
76
-        // only attempt to show the image if it at least exists
77
-        $image = $this->_input->raw_value() && $this->src_exists($this->_input->raw_value())
78
-            ? EEH_HTML::br() . EEH_HTML::img(
79
-                $this->_input->raw_value(),
80
-                esc_html__('logo', 'event_espresso'),
81
-                '',
82
-                'ee_media_image'
83
-            )
84
-            : '';
85
-        // html string
86
-        return EEH_HTML::div(
87
-            $input . $uploader,
88
-            '',
89
-            'ee_media_uploader_area'
90
-        ) . $image;
91
-    }
56
+	public function display(): string
57
+	{
58
+		// the actual input
59
+		$input = '<input type="text" size="34" ';
60
+		$input .= 'name="' . $this->_input->html_name() . '" ';
61
+		$input .= $this->_input->html_class() !== ''
62
+			? 'class="large-text ee_media_url ' . $this->_input->html_class() . '" '
63
+			: 'class="large-text ee_media_url" ';
64
+		$input .= 'value="' . $this->_input->raw_value_in_form() . '" ';
65
+		$input .= $this->_input->other_html_attributes();
66
+		$input .= $this->dataAttributesString($this->_input->dataAttributes());
67
+		$input .= '>';
68
+		// image uploader
69
+		$uploader = EEH_HTML::link(
70
+			'#',
71
+			'<span class="dashicons dashicons-format-image"></span>',
72
+			esc_html__('click to add an image', 'event_espresso'),
73
+			'',
74
+			'ee_media_upload button button--secondary button--icon-only'
75
+		);
76
+		// only attempt to show the image if it at least exists
77
+		$image = $this->_input->raw_value() && $this->src_exists($this->_input->raw_value())
78
+			? EEH_HTML::br() . EEH_HTML::img(
79
+				$this->_input->raw_value(),
80
+				esc_html__('logo', 'event_espresso'),
81
+				'',
82
+				'ee_media_image'
83
+			)
84
+			: '';
85
+		// html string
86
+		return EEH_HTML::div(
87
+			$input . $uploader,
88
+			'',
89
+			'ee_media_uploader_area'
90
+		) . $image;
91
+	}
92 92
 
93 93
 
94
-    /**
95
-     * Asserts an image actually exists as quickly as possible by sending a HEAD
96
-     * request
97
-     *
98
-     * @param string $src
99
-     * @return boolean
100
-     */
101
-    protected function src_exists(string $src): bool
102
-    {
103
-        $results = wp_remote_head($src);
104
-        if (is_array($results) && ! $results instanceof WP_Error) {
105
-            return strpos($results['headers']['content-type'], "image") !== false;
106
-        }
107
-        return false;
108
-    }
94
+	/**
95
+	 * Asserts an image actually exists as quickly as possible by sending a HEAD
96
+	 * request
97
+	 *
98
+	 * @param string $src
99
+	 * @return boolean
100
+	 */
101
+	protected function src_exists(string $src): bool
102
+	{
103
+		$results = wp_remote_head($src);
104
+		if (is_array($results) && ! $results instanceof WP_Error) {
105
+			return strpos($results['headers']['content-type'], "image") !== false;
106
+		}
107
+		return false;
108
+	}
109 109
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -32,7 +32,7 @@  discard block
 block discarded – undo
32 32
         );
33 33
         wp_enqueue_media();
34 34
         wp_enqueue_script('media-upload');
35
-        wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL . 'scripts/ee-media-uploader.js');
35
+        wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL.'scripts/ee-media-uploader.js');
36 36
     }
37 37
 
38 38
 
@@ -43,7 +43,7 @@  discard block
 block discarded – undo
43 43
     {
44 44
         wp_enqueue_media();
45 45
         wp_enqueue_script('media-upload');
46
-        wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL . 'scripts/ee-media-uploader.js');
46
+        wp_enqueue_script('ee-payments', EE_GLOBAL_ASSETS_URL.'scripts/ee-media-uploader.js');
47 47
         parent::enqueue_js();
48 48
     }
49 49
 
@@ -57,11 +57,11 @@  discard block
 block discarded – undo
57 57
     {
58 58
         // the actual input
59 59
         $input = '<input type="text" size="34" ';
60
-        $input .= 'name="' . $this->_input->html_name() . '" ';
60
+        $input .= 'name="'.$this->_input->html_name().'" ';
61 61
         $input .= $this->_input->html_class() !== ''
62
-            ? 'class="large-text ee_media_url ' . $this->_input->html_class() . '" '
62
+            ? 'class="large-text ee_media_url '.$this->_input->html_class().'" '
63 63
             : 'class="large-text ee_media_url" ';
64
-        $input .= 'value="' . $this->_input->raw_value_in_form() . '" ';
64
+        $input .= 'value="'.$this->_input->raw_value_in_form().'" ';
65 65
         $input .= $this->_input->other_html_attributes();
66 66
         $input .= $this->dataAttributesString($this->_input->dataAttributes());
67 67
         $input .= '>';
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
         );
76 76
         // only attempt to show the image if it at least exists
77 77
         $image = $this->_input->raw_value() && $this->src_exists($this->_input->raw_value())
78
-            ? EEH_HTML::br() . EEH_HTML::img(
78
+            ? EEH_HTML::br().EEH_HTML::img(
79 79
                 $this->_input->raw_value(),
80 80
                 esc_html__('logo', 'event_espresso'),
81 81
                 '',
@@ -84,10 +84,10 @@  discard block
 block discarded – undo
84 84
             : '';
85 85
         // html string
86 86
         return EEH_HTML::div(
87
-            $input . $uploader,
87
+            $input.$uploader,
88 88
             '',
89 89
             'ee_media_uploader_area'
90
-        ) . $image;
90
+        ).$image;
91 91
     }
92 92
 
93 93
 
Please login to merge, or discard this patch.
display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php 2 patches
Indentation   +168 added lines, -168 removed lines patch added patch discarded remove patch
@@ -10,182 +10,182 @@
 block discarded – undo
10 10
  */
11 11
 class EE_Checkbox_Dropdown_Selector_Display_Strategy extends EE_Compound_Input_Display_Strategy
12 12
 {
13
-    /**
14
-     * enqueues css and js, so that this can be called statically
15
-     */
16
-    public static function enqueue_styles_and_scripts()
17
-    {
18
-        wp_register_style(
19
-            'checkbox_dropdown_selector',
20
-            EE_GLOBAL_ASSETS_URL . 'css/checkbox_dropdown_selector.css',
21
-            ['espresso_default'],
22
-            EVENT_ESPRESSO_VERSION
23
-        );
24
-        wp_register_style(
25
-            'espresso_default',
26
-            EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
27
-            ['dashicons'],
28
-            EVENT_ESPRESSO_VERSION
29
-        );
30
-        wp_enqueue_style('checkbox_dropdown_selector');
31
-        wp_register_script(
32
-            'checkbox_dropdown_selector',
33
-            EE_GLOBAL_ASSETS_URL . 'scripts/checkbox_dropdown_selector.js',
34
-            ['jquery'],
35
-            EVENT_ESPRESSO_VERSION,
36
-            true
37
-        );
38
-        wp_localize_script(
39
-            'ticket_selector',
40
-            'eeDTS',
41
-            [
42
-                'maxChecked' => EE_Registry::instance()
43
-                    ->CFG
44
-                    ->template_settings
45
-                    ->EED_Ticket_Selector
46
-                    ->getDatetimeSelectorMaxChecked(),
47
-            ]
48
-        );
49
-        wp_enqueue_script('checkbox_dropdown_selector');
50
-    }
13
+	/**
14
+	 * enqueues css and js, so that this can be called statically
15
+	 */
16
+	public static function enqueue_styles_and_scripts()
17
+	{
18
+		wp_register_style(
19
+			'checkbox_dropdown_selector',
20
+			EE_GLOBAL_ASSETS_URL . 'css/checkbox_dropdown_selector.css',
21
+			['espresso_default'],
22
+			EVENT_ESPRESSO_VERSION
23
+		);
24
+		wp_register_style(
25
+			'espresso_default',
26
+			EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
27
+			['dashicons'],
28
+			EVENT_ESPRESSO_VERSION
29
+		);
30
+		wp_enqueue_style('checkbox_dropdown_selector');
31
+		wp_register_script(
32
+			'checkbox_dropdown_selector',
33
+			EE_GLOBAL_ASSETS_URL . 'scripts/checkbox_dropdown_selector.js',
34
+			['jquery'],
35
+			EVENT_ESPRESSO_VERSION,
36
+			true
37
+		);
38
+		wp_localize_script(
39
+			'ticket_selector',
40
+			'eeDTS',
41
+			[
42
+				'maxChecked' => EE_Registry::instance()
43
+					->CFG
44
+					->template_settings
45
+					->EED_Ticket_Selector
46
+					->getDatetimeSelectorMaxChecked(),
47
+			]
48
+		);
49
+		wp_enqueue_script('checkbox_dropdown_selector');
50
+	}
51 51
 
52 52
 
53
-    /**
54
-     * Informs the rest of the forms system what CSS and JS is needed to display the input
55
-     */
56
-    public function enqueue_js()
57
-    {
58
-        EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
59
-    }
53
+	/**
54
+	 * Informs the rest of the forms system what CSS and JS is needed to display the input
55
+	 */
56
+	public function enqueue_js()
57
+	{
58
+		EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
59
+	}
60 60
 
61 61
 
62
-    /**
63
-     * callback for Iframe::addStylesheets() child class methods
64
-     *
65
-     * @param array $iframe_css
66
-     * @return array
67
-     */
68
-    public function iframe_css(array $iframe_css): array
69
-    {
70
-        $iframe_css['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL . 'css/checkbox_dropdown_selector.css';
71
-        return $iframe_css;
72
-    }
62
+	/**
63
+	 * callback for Iframe::addStylesheets() child class methods
64
+	 *
65
+	 * @param array $iframe_css
66
+	 * @return array
67
+	 */
68
+	public function iframe_css(array $iframe_css): array
69
+	{
70
+		$iframe_css['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL . 'css/checkbox_dropdown_selector.css';
71
+		return $iframe_css;
72
+	}
73 73
 
74 74
 
75
-    /**
76
-     * callback for Iframe::addScripts() child class methods
77
-     *
78
-     * @param array $iframe_js
79
-     * @return array
80
-     */
81
-    public function iframe_js(array $iframe_js): array
82
-    {
83
-        $iframe_js['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL . 'scripts/checkbox_dropdown_selector.js';
84
-        return $iframe_js;
85
-    }
75
+	/**
76
+	 * callback for Iframe::addScripts() child class methods
77
+	 *
78
+	 * @param array $iframe_js
79
+	 * @return array
80
+	 */
81
+	public function iframe_js(array $iframe_js): array
82
+	{
83
+		$iframe_js['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL . 'scripts/checkbox_dropdown_selector.js';
84
+		return $iframe_js;
85
+	}
86 86
 
87 87
 
88
-    /**
89
-     * @return string of html to display the field
90
-     * @throws EE_Error
91
-     */
92
-    public function display(): string
93
-    {
94
-        $input              = $this->get_input();
95
-        $select_button_text = $input instanceof EE_Checkbox_Dropdown_Selector_Input
96
-            ? $input->select_button_text()
97
-            : '';
98
-        // $multi = count( $input->options() ) > 1 ? TRUE : FALSE;
99
-        $input->set_label_sizes();
100
-        $label_size_class = $input->get_label_size_class();
101
-        if (! is_array($input->raw_value()) && $input->raw_value() !== null) {
102
-            EE_Error::doing_it_wrong(
103
-                'EE_Checkbox_Display_Strategy::display()',
104
-                sprintf(
105
-                    esc_html__(
106
-                        'Input values for checkboxes should be an array of values, but the value for input "%1$s" is "%2$s". Please verify that the input name is exactly "%3$s"',
107
-                        'event_espresso'
108
-                    ),
109
-                    $input->html_id(),
110
-                    var_export($input->raw_value(), true),
111
-                    $input->html_name() . '[]'
112
-                ),
113
-                '4.8.1'
114
-            );
115
-        }
88
+	/**
89
+	 * @return string of html to display the field
90
+	 * @throws EE_Error
91
+	 */
92
+	public function display(): string
93
+	{
94
+		$input              = $this->get_input();
95
+		$select_button_text = $input instanceof EE_Checkbox_Dropdown_Selector_Input
96
+			? $input->select_button_text()
97
+			: '';
98
+		// $multi = count( $input->options() ) > 1 ? TRUE : FALSE;
99
+		$input->set_label_sizes();
100
+		$label_size_class = $input->get_label_size_class();
101
+		if (! is_array($input->raw_value()) && $input->raw_value() !== null) {
102
+			EE_Error::doing_it_wrong(
103
+				'EE_Checkbox_Display_Strategy::display()',
104
+				sprintf(
105
+					esc_html__(
106
+						'Input values for checkboxes should be an array of values, but the value for input "%1$s" is "%2$s". Please verify that the input name is exactly "%3$s"',
107
+						'event_espresso'
108
+					),
109
+					$input->html_id(),
110
+					var_export($input->raw_value(), true),
111
+					$input->html_name() . '[]'
112
+				),
113
+				'4.8.1'
114
+			);
115
+		}
116 116
 
117 117
 
118
-        $html = EEH_HTML::div('', '', 'checkbox-dropdown-selector-wrap-dv');
119
-        $html .= '<button id="' . $input->html_id() . '-btn"';
120
-        // $html .= ' name="' . $input->html_name() . '"';
121
-        $html            .= ' class="' . $input->html_class(
122
-        ) . ' checkbox-dropdown-selector-btn button--secondary button"';
123
-        $html            .= ' style="' . $input->html_style() . '"';
124
-        $html            .= ' data-target="' . $input->html_id() . '-options-dv"';
125
-        $html            .= ' ' . $input->other_html_attributes() . '>';
126
-        $html            .= '<span class="checkbox-dropdown-selector-selected-spn">';
127
-        $html            .= $select_button_text;
128
-        $html            .= '</span> <span class="dashicons dashicons-arrow-down"></span>';
129
-        $html            .= '</button>';
130
-        $html            .= EEH_HTML::div(
131
-            '',
132
-            $input->html_id() . '-options-dv',
133
-            'checkbox-dropdown-selector'
134
-        );
135
-        $html            .= EEH_HTML::link(
136
-            '',
137
-            '<span class="dashicons dashicons-no"></span>',
138
-            esc_html__('close datetime selector', 'event_espresso'),
139
-            '',
140
-            'close-espresso-notice'
141
-        );
142
-        $html            .= EEH_HTML::ul();
143
-        $input_raw_value = (array) $input->raw_value();
144
-        foreach ($input->options() as $value => $display_text) {
145
-            $html    .= EEH_HTML::li();
146
-            $value   = $input->get_normalization_strategy()->unnormalize_one($value);
147
-            $html_id = $this->get_sub_input_id($value);
148
-            $html    .= EEH_HTML::nl(0, 'checkbox');
149
-            $html    .= '<label for="'
150
-                        . $html_id
151
-                        . '" id="'
152
-                        . $html_id
153
-                        . '-lbl" class="ee-checkbox-label-after'
154
-                        . $label_size_class
155
-                        . '">';
156
-            $html    .= EEH_HTML::nl(1, 'checkbox');
157
-            $html    .= '<input type="checkbox"';
158
-            $html    .= ' name="' . $input->html_name() . '[]"';
159
-            $html    .= ' id="' . $html_id . '"';
160
-            $html    .= ' class="' . $input->html_class() . '-option"';
161
-            $html    .= $input->html_style()
162
-                ? ' style="' . $input->html_style() . '"'
163
-                : '';
164
-            $html    .= ' value="' . esc_attr($value) . '"';
165
-            $html    .= ! empty($input_raw_value) && in_array($value, $input_raw_value, true)
166
-                ? ' checked'
167
-                : '';
168
-            $html    .= ' ' . $this->_input->other_html_attributes();
169
-            $html    .= '>';
170
-            $html    .= '<span class="datetime-selector-option-text-spn">' . $display_text . '</span>';
171
-            $html    .= EEH_HTML::nl(-1, 'checkbox') . '</label>';
172
-            $html    .= EEH_HTML::lix();
173
-        }
174
-        $html .= EEH_HTML::ulx();
175
-        $html .= EEH_HTML::divx();
176
-        $html .= EEH_HTML::divx();
177
-        $html .= EEH_HTML::p(
178
-            apply_filters(
179
-                'FHEE__EE_Checkbox_Dropdown_Selector_Display_Strategy__display__html',
180
-                esc_html__(
181
-                    'To view additional ticket options, click the "Filter by Date" button and select more dates.',
182
-                    'event_espresso'
183
-                )
184
-            ),
185
-            $input->html_id() . '-date-time-filter-notice-pg',
186
-            'date-time-filter-notice-pg small-text lt-grey-text'
187
-        );
188
-        $html .= EEH_HTML::br();
189
-        return $html;
190
-    }
118
+		$html = EEH_HTML::div('', '', 'checkbox-dropdown-selector-wrap-dv');
119
+		$html .= '<button id="' . $input->html_id() . '-btn"';
120
+		// $html .= ' name="' . $input->html_name() . '"';
121
+		$html            .= ' class="' . $input->html_class(
122
+		) . ' checkbox-dropdown-selector-btn button--secondary button"';
123
+		$html            .= ' style="' . $input->html_style() . '"';
124
+		$html            .= ' data-target="' . $input->html_id() . '-options-dv"';
125
+		$html            .= ' ' . $input->other_html_attributes() . '>';
126
+		$html            .= '<span class="checkbox-dropdown-selector-selected-spn">';
127
+		$html            .= $select_button_text;
128
+		$html            .= '</span> <span class="dashicons dashicons-arrow-down"></span>';
129
+		$html            .= '</button>';
130
+		$html            .= EEH_HTML::div(
131
+			'',
132
+			$input->html_id() . '-options-dv',
133
+			'checkbox-dropdown-selector'
134
+		);
135
+		$html            .= EEH_HTML::link(
136
+			'',
137
+			'<span class="dashicons dashicons-no"></span>',
138
+			esc_html__('close datetime selector', 'event_espresso'),
139
+			'',
140
+			'close-espresso-notice'
141
+		);
142
+		$html            .= EEH_HTML::ul();
143
+		$input_raw_value = (array) $input->raw_value();
144
+		foreach ($input->options() as $value => $display_text) {
145
+			$html    .= EEH_HTML::li();
146
+			$value   = $input->get_normalization_strategy()->unnormalize_one($value);
147
+			$html_id = $this->get_sub_input_id($value);
148
+			$html    .= EEH_HTML::nl(0, 'checkbox');
149
+			$html    .= '<label for="'
150
+						. $html_id
151
+						. '" id="'
152
+						. $html_id
153
+						. '-lbl" class="ee-checkbox-label-after'
154
+						. $label_size_class
155
+						. '">';
156
+			$html    .= EEH_HTML::nl(1, 'checkbox');
157
+			$html    .= '<input type="checkbox"';
158
+			$html    .= ' name="' . $input->html_name() . '[]"';
159
+			$html    .= ' id="' . $html_id . '"';
160
+			$html    .= ' class="' . $input->html_class() . '-option"';
161
+			$html    .= $input->html_style()
162
+				? ' style="' . $input->html_style() . '"'
163
+				: '';
164
+			$html    .= ' value="' . esc_attr($value) . '"';
165
+			$html    .= ! empty($input_raw_value) && in_array($value, $input_raw_value, true)
166
+				? ' checked'
167
+				: '';
168
+			$html    .= ' ' . $this->_input->other_html_attributes();
169
+			$html    .= '>';
170
+			$html    .= '<span class="datetime-selector-option-text-spn">' . $display_text . '</span>';
171
+			$html    .= EEH_HTML::nl(-1, 'checkbox') . '</label>';
172
+			$html    .= EEH_HTML::lix();
173
+		}
174
+		$html .= EEH_HTML::ulx();
175
+		$html .= EEH_HTML::divx();
176
+		$html .= EEH_HTML::divx();
177
+		$html .= EEH_HTML::p(
178
+			apply_filters(
179
+				'FHEE__EE_Checkbox_Dropdown_Selector_Display_Strategy__display__html',
180
+				esc_html__(
181
+					'To view additional ticket options, click the "Filter by Date" button and select more dates.',
182
+					'event_espresso'
183
+				)
184
+			),
185
+			$input->html_id() . '-date-time-filter-notice-pg',
186
+			'date-time-filter-notice-pg small-text lt-grey-text'
187
+		);
188
+		$html .= EEH_HTML::br();
189
+		return $html;
190
+	}
191 191
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -17,20 +17,20 @@  discard block
 block discarded – undo
17 17
     {
18 18
         wp_register_style(
19 19
             'checkbox_dropdown_selector',
20
-            EE_GLOBAL_ASSETS_URL . 'css/checkbox_dropdown_selector.css',
20
+            EE_GLOBAL_ASSETS_URL.'css/checkbox_dropdown_selector.css',
21 21
             ['espresso_default'],
22 22
             EVENT_ESPRESSO_VERSION
23 23
         );
24 24
         wp_register_style(
25 25
             'espresso_default',
26
-            EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
26
+            EE_GLOBAL_ASSETS_URL.'css/espresso_default.css',
27 27
             ['dashicons'],
28 28
             EVENT_ESPRESSO_VERSION
29 29
         );
30 30
         wp_enqueue_style('checkbox_dropdown_selector');
31 31
         wp_register_script(
32 32
             'checkbox_dropdown_selector',
33
-            EE_GLOBAL_ASSETS_URL . 'scripts/checkbox_dropdown_selector.js',
33
+            EE_GLOBAL_ASSETS_URL.'scripts/checkbox_dropdown_selector.js',
34 34
             ['jquery'],
35 35
             EVENT_ESPRESSO_VERSION,
36 36
             true
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
      */
68 68
     public function iframe_css(array $iframe_css): array
69 69
     {
70
-        $iframe_css['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL . 'css/checkbox_dropdown_selector.css';
70
+        $iframe_css['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL.'css/checkbox_dropdown_selector.css';
71 71
         return $iframe_css;
72 72
     }
73 73
 
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
      */
81 81
     public function iframe_js(array $iframe_js): array
82 82
     {
83
-        $iframe_js['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL . 'scripts/checkbox_dropdown_selector.js';
83
+        $iframe_js['checkbox_dropdown_selector'] = EE_GLOBAL_ASSETS_URL.'scripts/checkbox_dropdown_selector.js';
84 84
         return $iframe_js;
85 85
     }
86 86
 
@@ -98,7 +98,7 @@  discard block
 block discarded – undo
98 98
         // $multi = count( $input->options() ) > 1 ? TRUE : FALSE;
99 99
         $input->set_label_sizes();
100 100
         $label_size_class = $input->get_label_size_class();
101
-        if (! is_array($input->raw_value()) && $input->raw_value() !== null) {
101
+        if ( ! is_array($input->raw_value()) && $input->raw_value() !== null) {
102 102
             EE_Error::doing_it_wrong(
103 103
                 'EE_Checkbox_Display_Strategy::display()',
104 104
                 sprintf(
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
                     ),
109 109
                     $input->html_id(),
110 110
                     var_export($input->raw_value(), true),
111
-                    $input->html_name() . '[]'
111
+                    $input->html_name().'[]'
112 112
                 ),
113 113
                 '4.8.1'
114 114
             );
@@ -116,30 +116,30 @@  discard block
 block discarded – undo
116 116
 
117 117
 
118 118
         $html = EEH_HTML::div('', '', 'checkbox-dropdown-selector-wrap-dv');
119
-        $html .= '<button id="' . $input->html_id() . '-btn"';
119
+        $html .= '<button id="'.$input->html_id().'-btn"';
120 120
         // $html .= ' name="' . $input->html_name() . '"';
121
-        $html            .= ' class="' . $input->html_class(
122
-        ) . ' checkbox-dropdown-selector-btn button--secondary button"';
123
-        $html            .= ' style="' . $input->html_style() . '"';
124
-        $html            .= ' data-target="' . $input->html_id() . '-options-dv"';
125
-        $html            .= ' ' . $input->other_html_attributes() . '>';
121
+        $html            .= ' class="'.$input->html_class(
122
+        ).' checkbox-dropdown-selector-btn button--secondary button"';
123
+        $html            .= ' style="'.$input->html_style().'"';
124
+        $html            .= ' data-target="'.$input->html_id().'-options-dv"';
125
+        $html            .= ' '.$input->other_html_attributes().'>';
126 126
         $html            .= '<span class="checkbox-dropdown-selector-selected-spn">';
127 127
         $html            .= $select_button_text;
128 128
         $html            .= '</span> <span class="dashicons dashicons-arrow-down"></span>';
129 129
         $html            .= '</button>';
130 130
         $html            .= EEH_HTML::div(
131 131
             '',
132
-            $input->html_id() . '-options-dv',
132
+            $input->html_id().'-options-dv',
133 133
             'checkbox-dropdown-selector'
134 134
         );
135
-        $html            .= EEH_HTML::link(
135
+        $html .= EEH_HTML::link(
136 136
             '',
137 137
             '<span class="dashicons dashicons-no"></span>',
138 138
             esc_html__('close datetime selector', 'event_espresso'),
139 139
             '',
140 140
             'close-espresso-notice'
141 141
         );
142
-        $html            .= EEH_HTML::ul();
142
+        $html .= EEH_HTML::ul();
143 143
         $input_raw_value = (array) $input->raw_value();
144 144
         foreach ($input->options() as $value => $display_text) {
145 145
             $html    .= EEH_HTML::li();
@@ -155,20 +155,20 @@  discard block
 block discarded – undo
155 155
                         . '">';
156 156
             $html    .= EEH_HTML::nl(1, 'checkbox');
157 157
             $html    .= '<input type="checkbox"';
158
-            $html    .= ' name="' . $input->html_name() . '[]"';
159
-            $html    .= ' id="' . $html_id . '"';
160
-            $html    .= ' class="' . $input->html_class() . '-option"';
158
+            $html    .= ' name="'.$input->html_name().'[]"';
159
+            $html    .= ' id="'.$html_id.'"';
160
+            $html    .= ' class="'.$input->html_class().'-option"';
161 161
             $html    .= $input->html_style()
162
-                ? ' style="' . $input->html_style() . '"'
162
+                ? ' style="'.$input->html_style().'"'
163 163
                 : '';
164
-            $html    .= ' value="' . esc_attr($value) . '"';
164
+            $html    .= ' value="'.esc_attr($value).'"';
165 165
             $html    .= ! empty($input_raw_value) && in_array($value, $input_raw_value, true)
166 166
                 ? ' checked'
167 167
                 : '';
168
-            $html    .= ' ' . $this->_input->other_html_attributes();
168
+            $html    .= ' '.$this->_input->other_html_attributes();
169 169
             $html    .= '>';
170
-            $html    .= '<span class="datetime-selector-option-text-spn">' . $display_text . '</span>';
171
-            $html    .= EEH_HTML::nl(-1, 'checkbox') . '</label>';
170
+            $html    .= '<span class="datetime-selector-option-text-spn">'.$display_text.'</span>';
171
+            $html    .= EEH_HTML::nl(-1, 'checkbox').'</label>';
172 172
             $html    .= EEH_HTML::lix();
173 173
         }
174 174
         $html .= EEH_HTML::ulx();
@@ -182,7 +182,7 @@  discard block
 block discarded – undo
182 182
                     'event_espresso'
183 183
                 )
184 184
             ),
185
-            $input->html_id() . '-date-time-filter-notice-pg',
185
+            $input->html_id().'-date-time-filter-notice-pg',
186 186
             'date-time-filter-notice-pg small-text lt-grey-text'
187 187
         );
188 188
         $html .= EEH_HTML::br();
Please login to merge, or discard this patch.
form_sections/payment_methods/EE_Billing_Attendee_Info_Form.form.php 1 patch
Indentation   +214 added lines, -214 removed lines patch added patch discarded remove patch
@@ -13,229 +13,229 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Billing_Attendee_Info_Form extends EE_Billing_Info_Form
15 15
 {
16
-    /**
17
-     *
18
-     * @param EE_Payment_Method $payment_method
19
-     * @param array             $options_array @see EE_Form_Section_Proper::__construct()
20
-     * @throws EE_Error
21
-     * @throws ReflectionException
22
-     */
23
-    public function __construct(EE_Payment_Method $payment_method, $options_array = [])
24
-    {
25
-        $options_array['subsections'] = array_merge(
26
-            [
27
-                'first_name' => new EE_Text_Input(
28
-                    [
29
-                        'required'        => true,
30
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-fname',
31
-                        'html_label_text' => esc_html__('First Name', 'event_espresso'),
32
-                    ]
33
-                ),
34
-                'last_name'  => new EE_Text_Input(
35
-                    [
36
-                        'required'        => true,
37
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-lname',
38
-                        'html_label_text' => esc_html__('Last Name', 'event_espresso'),
39
-                    ]
40
-                ),
41
-                'email'      => new EE_Email_Input(
42
-                    [
43
-                        'required'        => true,
44
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-email',
45
-                        'html_label_text' => esc_html__('Email', 'event_espresso'),
46
-                    ]
47
-                ),
48
-                'address'    => new EE_Text_Input(
49
-                    [
50
-                        'html_label_text' => esc_html__('Address', 'event_espresso'),
51
-                        'required'        => true,
52
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-address',
53
-                    ]
54
-                ),
55
-                'address2'   => new EE_Text_Input(
56
-                    [
57
-                        'html_label_text' => esc_html__('Address 2', 'event_espresso'),
58
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-address2',
59
-                    ]
60
-                ),
61
-                'city'       => new EE_Text_Input(
62
-                    [
63
-                        'required'        => true,
64
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-city',
65
-                        'html_label_text' => esc_html__('City', 'event_espresso'),
66
-                    ]
67
-                ),
68
-                'state'      => apply_filters(
69
-                    'FHEE__EE_Billing_Attendee_Info_Form__state_field',
70
-                    new EE_State_Select_Input(
71
-                        null,
72
-                        [
73
-                        'required'        => true,
74
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-state',
75
-                        'html_label_text' => esc_html__('State', 'event_espresso'),
76
-                        ]
77
-                    )
78
-                ),
79
-                'country'    => apply_filters(
80
-                    'FHEE__EE_Billing_Attendee_Info_Form__country_field',
81
-                    new EE_Country_Select_Input(
82
-                        null,
83
-                        [
84
-                        'required'        => true,
85
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-country',
86
-                        'html_label_text' => esc_html__('Country', 'event_espresso'),
87
-                        ]
88
-                    )
89
-                ),
90
-                'zip'        => new EE_Text_Input(
91
-                    [
92
-                        'required'        => true,
93
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-zip',
94
-                        'html_label_text' => esc_html__('Zip', 'event_espresso'),
95
-                    ]
96
-                ),
97
-                'phone'      => new EE_Text_Input(
98
-                    [
99
-                        'html_class'      => 'ee-billing-qstn ee-billing-qstn-phone',
100
-                        'html_label_text' => esc_html__('Phone', 'event_espresso'),
101
-                    ]
102
-                ),
103
-            ],
104
-            $options_array['subsections'] ?? []
105
-        );
16
+	/**
17
+	 *
18
+	 * @param EE_Payment_Method $payment_method
19
+	 * @param array             $options_array @see EE_Form_Section_Proper::__construct()
20
+	 * @throws EE_Error
21
+	 * @throws ReflectionException
22
+	 */
23
+	public function __construct(EE_Payment_Method $payment_method, $options_array = [])
24
+	{
25
+		$options_array['subsections'] = array_merge(
26
+			[
27
+				'first_name' => new EE_Text_Input(
28
+					[
29
+						'required'        => true,
30
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-fname',
31
+						'html_label_text' => esc_html__('First Name', 'event_espresso'),
32
+					]
33
+				),
34
+				'last_name'  => new EE_Text_Input(
35
+					[
36
+						'required'        => true,
37
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-lname',
38
+						'html_label_text' => esc_html__('Last Name', 'event_espresso'),
39
+					]
40
+				),
41
+				'email'      => new EE_Email_Input(
42
+					[
43
+						'required'        => true,
44
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-email',
45
+						'html_label_text' => esc_html__('Email', 'event_espresso'),
46
+					]
47
+				),
48
+				'address'    => new EE_Text_Input(
49
+					[
50
+						'html_label_text' => esc_html__('Address', 'event_espresso'),
51
+						'required'        => true,
52
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-address',
53
+					]
54
+				),
55
+				'address2'   => new EE_Text_Input(
56
+					[
57
+						'html_label_text' => esc_html__('Address 2', 'event_espresso'),
58
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-address2',
59
+					]
60
+				),
61
+				'city'       => new EE_Text_Input(
62
+					[
63
+						'required'        => true,
64
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-city',
65
+						'html_label_text' => esc_html__('City', 'event_espresso'),
66
+					]
67
+				),
68
+				'state'      => apply_filters(
69
+					'FHEE__EE_Billing_Attendee_Info_Form__state_field',
70
+					new EE_State_Select_Input(
71
+						null,
72
+						[
73
+						'required'        => true,
74
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-state',
75
+						'html_label_text' => esc_html__('State', 'event_espresso'),
76
+						]
77
+					)
78
+				),
79
+				'country'    => apply_filters(
80
+					'FHEE__EE_Billing_Attendee_Info_Form__country_field',
81
+					new EE_Country_Select_Input(
82
+						null,
83
+						[
84
+						'required'        => true,
85
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-country',
86
+						'html_label_text' => esc_html__('Country', 'event_espresso'),
87
+						]
88
+					)
89
+				),
90
+				'zip'        => new EE_Text_Input(
91
+					[
92
+						'required'        => true,
93
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-zip',
94
+						'html_label_text' => esc_html__('Zip', 'event_espresso'),
95
+					]
96
+				),
97
+				'phone'      => new EE_Text_Input(
98
+					[
99
+						'html_class'      => 'ee-billing-qstn ee-billing-qstn-phone',
100
+						'html_label_text' => esc_html__('Phone', 'event_espresso'),
101
+					]
102
+				),
103
+			],
104
+			$options_array['subsections'] ?? []
105
+		);
106 106
 
107
-        parent::__construct($payment_method, $options_array);
108
-    }
107
+		parent::__construct($payment_method, $options_array);
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * Sets the defaults for the billing form according to the attendee's details
113
-     *
114
-     * @param EE_Attendee $attendee
115
-     * @throws EE_Error
116
-     * @throws ReflectionException
117
-     */
118
-    public function populate_from_attendee(EE_Attendee $attendee)
119
-    {
120
-        /** @var $attendee EE_Attendee */
121
-        $attendee = EEM_Attendee::instance()->ensure_is_obj($attendee);
122
-        $this->populate_defaults(
123
-            apply_filters(
124
-                'FHEE__EE_Billing_Attendee_Info_Form__populate_from_attendee',
125
-                [
126
-                    'first_name' => $attendee->fname(),
127
-                    'last_name'  => $attendee->lname(),
128
-                    'email'      => $attendee->email(),
129
-                    'address'    => $attendee->address(),
130
-                    'address2'   => $attendee->address2(),
131
-                    'city'       => $attendee->city(),
132
-                    'state'      => $this->getAttendeeStateValueForForm($attendee),
133
-                    'country'    => $attendee->country_ID(),
134
-                    'zip'        => $attendee->zip(),
135
-                    'phone'      => $attendee->phone(),
136
-                ],
137
-                $attendee,
138
-                $this
139
-            )
140
-        );
141
-    }
111
+	/**
112
+	 * Sets the defaults for the billing form according to the attendee's details
113
+	 *
114
+	 * @param EE_Attendee $attendee
115
+	 * @throws EE_Error
116
+	 * @throws ReflectionException
117
+	 */
118
+	public function populate_from_attendee(EE_Attendee $attendee)
119
+	{
120
+		/** @var $attendee EE_Attendee */
121
+		$attendee = EEM_Attendee::instance()->ensure_is_obj($attendee);
122
+		$this->populate_defaults(
123
+			apply_filters(
124
+				'FHEE__EE_Billing_Attendee_Info_Form__populate_from_attendee',
125
+				[
126
+					'first_name' => $attendee->fname(),
127
+					'last_name'  => $attendee->lname(),
128
+					'email'      => $attendee->email(),
129
+					'address'    => $attendee->address(),
130
+					'address2'   => $attendee->address2(),
131
+					'city'       => $attendee->city(),
132
+					'state'      => $this->getAttendeeStateValueForForm($attendee),
133
+					'country'    => $attendee->country_ID(),
134
+					'zip'        => $attendee->zip(),
135
+					'phone'      => $attendee->phone(),
136
+				],
137
+				$attendee,
138
+				$this
139
+			)
140
+		);
141
+	}
142 142
 
143 143
 
144
-    /**
145
-     * Gets the default value to use for the billing form's state value.
146
-     *
147
-     * @param EE_Attendee $attendee
148
-     * @return string
149
-     * @throws EE_Error
150
-     * @throws ReflectionException
151
-     * @since 4.10.0.p
152
-     */
153
-    protected function getAttendeeStateValueForForm(EE_Attendee $attendee): string
154
-    {
155
-        // If the state input was removed, just return a blank string.
156
-        if (! $this->has_subsection('state')) {
157
-            return '';
158
-        }
159
-        $state_input = $this->get_input('state', false);
160
-        if ($state_input instanceof EE_State_Select_Input) {
161
-            $state_field_to_use = $state_input->valueFieldName();
162
-        } else {
163
-            $state_field_to_use = 'STA_ID';
164
-        }
165
-        switch ($state_field_to_use) {
166
-            case 'STA_abbrev':
167
-                $state_value = $attendee->state_abbrev();
168
-                break;
169
-            case 'STA_name':
170
-                $state_value = $attendee->state_name();
171
-                break;
172
-            default:
173
-                $state_value = $attendee->state_ID();
174
-        }
175
-        return $state_value;
176
-    }
144
+	/**
145
+	 * Gets the default value to use for the billing form's state value.
146
+	 *
147
+	 * @param EE_Attendee $attendee
148
+	 * @return string
149
+	 * @throws EE_Error
150
+	 * @throws ReflectionException
151
+	 * @since 4.10.0.p
152
+	 */
153
+	protected function getAttendeeStateValueForForm(EE_Attendee $attendee): string
154
+	{
155
+		// If the state input was removed, just return a blank string.
156
+		if (! $this->has_subsection('state')) {
157
+			return '';
158
+		}
159
+		$state_input = $this->get_input('state', false);
160
+		if ($state_input instanceof EE_State_Select_Input) {
161
+			$state_field_to_use = $state_input->valueFieldName();
162
+		} else {
163
+			$state_field_to_use = 'STA_ID';
164
+		}
165
+		switch ($state_field_to_use) {
166
+			case 'STA_abbrev':
167
+				$state_value = $attendee->state_abbrev();
168
+				break;
169
+			case 'STA_name':
170
+				$state_value = $attendee->state_name();
171
+				break;
172
+			default:
173
+				$state_value = $attendee->state_ID();
174
+		}
175
+		return $state_value;
176
+	}
177 177
 
178 178
 
179
-    /**
180
-     * copy_billing_form_data_to_attendee
181
-     * copies info from the billing form to the attendee's details
182
-     *
183
-     * @param EE_Attendee $attendee the attendee object to copy details to
184
-     * @return EE_Attendee
185
-     * @throws EE_Error
186
-     */
187
-    public function copy_billing_form_data_to_attendee(EE_Attendee $attendee): EE_Attendee
188
-    {
189
-        // grab billing form data
190
-        $data = $this->valid_data();
179
+	/**
180
+	 * copy_billing_form_data_to_attendee
181
+	 * copies info from the billing form to the attendee's details
182
+	 *
183
+	 * @param EE_Attendee $attendee the attendee object to copy details to
184
+	 * @return EE_Attendee
185
+	 * @throws EE_Error
186
+	 */
187
+	public function copy_billing_form_data_to_attendee(EE_Attendee $attendee): EE_Attendee
188
+	{
189
+		// grab billing form data
190
+		$data = $this->valid_data();
191 191
 
192
-        $fields_and_setters = [
193
-            'first_name' => 'set_fname',
194
-            'last_name'  => 'set_lname',
195
-            'email'      => 'set_email',
196
-            'address'    => 'set_address',
197
-            'address2'   => 'set_address2',
198
-            'city'       => 'set_city',
199
-            'state'      => 'set_state',
200
-            'country'    => 'set_country',
201
-            'zip'        => 'set_zip',
202
-            'phone'      => 'set_phone',
203
-        ];
204
-        foreach ($fields_and_setters as $field => $setter) {
205
-            if (! empty($data[ $field ]) && method_exists($attendee, $setter)) {
206
-                $attendee->{$setter}($data[ $field ]);
207
-            }
208
-        }
209
-        return $attendee;
210
-    }
192
+		$fields_and_setters = [
193
+			'first_name' => 'set_fname',
194
+			'last_name'  => 'set_lname',
195
+			'email'      => 'set_email',
196
+			'address'    => 'set_address',
197
+			'address2'   => 'set_address2',
198
+			'city'       => 'set_city',
199
+			'state'      => 'set_state',
200
+			'country'    => 'set_country',
201
+			'zip'        => 'set_zip',
202
+			'phone'      => 'set_phone',
203
+		];
204
+		foreach ($fields_and_setters as $field => $setter) {
205
+			if (! empty($data[ $field ]) && method_exists($attendee, $setter)) {
206
+				$attendee->{$setter}($data[ $field ]);
207
+			}
208
+		}
209
+		return $attendee;
210
+	}
211 211
 
212 212
 
213
-    /**
214
-     * create_attendee_from_billing_form_data
215
-     * uses info from the billing form to create a new attendee
216
-     *
217
-     * @return EE_Attendee
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    public function create_attendee_from_billing_form_data()
222
-    {
223
-        // grab billing form data
224
-        $data = $this->valid_data();
225
-        return EE_Attendee::new_instance(
226
-            [
227
-                'ATT_fname'    => ! empty($data['first_name']) ? $data['first_name'] : '',
228
-                'ATT_lname'    => ! empty($data['last_name']) ? $data['last_name'] : '',
229
-                'ATT_email'    => ! empty($data['email']) ? $data['email'] : '',
230
-                'ATT_address'  => ! empty($data['address']) ? $data['address'] : '',
231
-                'ATT_address2' => ! empty($data['address2']) ? $data['address2'] : '',
232
-                'ATT_city'     => ! empty($data['city']) ? $data['city'] : '',
233
-                'STA_ID'       => ! empty($data['state']) ? $data['state'] : '',
234
-                'CNT_ISO'      => ! empty($data['country']) ? $data['country'] : '',
235
-                'ATT_zip'      => ! empty($data['zip']) ? $data['zip'] : '',
236
-                'ATT_phone'    => ! empty($data['phone']) ? $data['phone'] : '',
237
-            ]
238
-        );
239
-    }
213
+	/**
214
+	 * create_attendee_from_billing_form_data
215
+	 * uses info from the billing form to create a new attendee
216
+	 *
217
+	 * @return EE_Attendee
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	public function create_attendee_from_billing_form_data()
222
+	{
223
+		// grab billing form data
224
+		$data = $this->valid_data();
225
+		return EE_Attendee::new_instance(
226
+			[
227
+				'ATT_fname'    => ! empty($data['first_name']) ? $data['first_name'] : '',
228
+				'ATT_lname'    => ! empty($data['last_name']) ? $data['last_name'] : '',
229
+				'ATT_email'    => ! empty($data['email']) ? $data['email'] : '',
230
+				'ATT_address'  => ! empty($data['address']) ? $data['address'] : '',
231
+				'ATT_address2' => ! empty($data['address2']) ? $data['address2'] : '',
232
+				'ATT_city'     => ! empty($data['city']) ? $data['city'] : '',
233
+				'STA_ID'       => ! empty($data['state']) ? $data['state'] : '',
234
+				'CNT_ISO'      => ! empty($data['country']) ? $data['country'] : '',
235
+				'ATT_zip'      => ! empty($data['zip']) ? $data['zip'] : '',
236
+				'ATT_phone'    => ! empty($data['phone']) ? $data['phone'] : '',
237
+			]
238
+		);
239
+	}
240 240
 }
241 241
 // End of file EE_Billing_Attendee_Info_Form.form.php
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 2 patches
Indentation   +1535 added lines, -1535 removed lines patch added patch discarded remove patch
@@ -15,1539 +15,1539 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
17 17
 {
18
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
19
-
20
-    /**
21
-     * Subsections
22
-     *
23
-     * @var EE_Form_Section_Validatable[]
24
-     */
25
-    protected $_subsections = array();
26
-
27
-    /**
28
-     * Strategy for laying out the form
29
-     *
30
-     * @var EE_Form_Section_Layout_Base
31
-     */
32
-    protected $_layout_strategy;
33
-
34
-    /**
35
-     * Whether or not this form has received and validated a form submission yet
36
-     *
37
-     * @var boolean
38
-     */
39
-    protected $_received_submission = false;
40
-
41
-    /**
42
-     * message displayed to users upon successful form submission
43
-     *
44
-     * @var string
45
-     */
46
-    protected $_form_submission_success_message = '';
47
-
48
-    /**
49
-     * message displayed to users upon unsuccessful form submission
50
-     *
51
-     * @var string
52
-     */
53
-    protected $_form_submission_error_message = '';
54
-
55
-    /**
56
-     * @var array like post / request
57
-     */
58
-    protected $cached_request_data;
59
-
60
-    /**
61
-     * Stores whether this form (and its sub-sections) were found to be valid or not.
62
-     * Starts off as null, but once the form is validated, it set to either true or false
63
-     * @var boolean|null
64
-     */
65
-    protected $is_valid;
66
-
67
-    /**
68
-     * Stores all the data that will localized for form validation
69
-     *
70
-     * @var array
71
-     */
72
-    protected static $_js_localization = array();
73
-
74
-    /**
75
-     * whether or not the form's localized validation JS vars have been set
76
-     *
77
-     * @type boolean
78
-     */
79
-    protected static $_scripts_localized = false;
80
-
81
-
82
-    /**
83
-     * when constructing a proper form section, calls _construct_finalize on children
84
-     * so that they know who their parent is, and what name they've been given.
85
-     *
86
-     * @param array[] $options_array   {
87
-     * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
88
-     * @type          $include         string[] numerically-indexed where values are section names to be included,
89
-     *                                 and in that order. This is handy if you want
90
-     *                                 the subsections to be ordered differently than the default, and if you override
91
-     *                                 which fields are shown
92
-     * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
93
-     *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
94
-     *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
95
-     *                                 items from that list of inclusions)
96
-     * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
97
-     *                                 } @see EE_Form_Section_Validatable::__construct()
98
-     * @throws EE_Error
99
-     */
100
-    public function __construct($options_array = array())
101
-    {
102
-        $options_array = (array) apply_filters(
103
-            'FHEE__EE_Form_Section_Proper___construct__options_array',
104
-            $options_array,
105
-            $this
106
-        );
107
-        // call parent first, as it may be setting the name
108
-        parent::__construct($options_array);
109
-        // if they've included subsections in the constructor, add them now
110
-        if (isset($options_array['include'])) {
111
-            // we are going to make sure we ONLY have those subsections to include
112
-            // AND we are going to make sure they're in that specified order
113
-            $reordered_subsections = array();
114
-            foreach ($options_array['include'] as $input_name) {
115
-                if (isset($this->_subsections[ $input_name ])) {
116
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
117
-                }
118
-            }
119
-            $this->_subsections = $reordered_subsections;
120
-        }
121
-        if (isset($options_array['exclude'])) {
122
-            $exclude            = $options_array['exclude'];
123
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
124
-        }
125
-        if (isset($options_array['layout_strategy'])) {
126
-            $this->_layout_strategy = $options_array['layout_strategy'];
127
-        }
128
-        if (! $this->_layout_strategy) {
129
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
130
-        }
131
-        $this->_layout_strategy->_construct_finalize($this);
132
-        // ok so we are definitely going to want the forms JS,
133
-        // so enqueue it or remember to enqueue it during wp_enqueue_scripts
134
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
135
-            // ok so they've constructed this object after when they should have.
136
-            // just enqueue the generic form scripts and initialize the form immediately in the JS
137
-            EE_Form_Section_Proper::wp_enqueue_scripts(true);
138
-        } else {
139
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
141
-        }
142
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
143
-        /**
144
-         * Gives other plugins a chance to hook in before construct finalize is called.
145
-         * The form probably doesn't yet have a parent form section.
146
-         * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
147
-         * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
148
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
149
-         *
150
-         * @since 4.9.32
151
-         * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
152
-         *                                              except maybe calling _construct_finalize has been done
153
-         * @param array                  $options_array options passed into the constructor
154
-         */
155
-        do_action(
156
-            'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
157
-            $this,
158
-            $options_array
159
-        );
160
-        if (isset($options_array['name'])) {
161
-            $this->_construct_finalize(null, $options_array['name']);
162
-        }
163
-    }
164
-
165
-
166
-    /**
167
-     * Finishes construction given the parent form section and this form section's name
168
-     *
169
-     * @param EE_Form_Section_Proper|null $parent_form_section
170
-     * @param string                 $name
171
-     * @throws EE_Error
172
-     */
173
-    public function _construct_finalize($parent_form_section, $name)
174
-    {
175
-        parent::_construct_finalize($parent_form_section, $name);
176
-        $this->_set_default_name_if_empty();
177
-        $this->_set_default_html_id_if_empty();
178
-        foreach ($this->_subsections as $subsection_name => $subsection) {
179
-            if ($subsection instanceof EE_Form_Section_Base) {
180
-                $subsection->_construct_finalize($this, $subsection_name);
181
-            } else {
182
-                throw new EE_Error(
183
-                    sprintf(
184
-                        esc_html__(
185
-                            'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
186
-                            'event_espresso'
187
-                        ),
188
-                        $subsection_name,
189
-                        get_class($this),
190
-                        $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
191
-                    )
192
-                );
193
-            }
194
-        }
195
-        /**
196
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
197
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
198
-         * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
199
-         * This might only happen just before displaying the form, or just before it receives form submission data.
200
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
201
-         * ensured it has a name, HTML IDs, etc
202
-         *
203
-         * @param EE_Form_Section_Proper      $this
204
-         * @param EE_Form_Section_Proper|null $parent_form_section
205
-         * @param string                      $name
206
-         */
207
-        do_action(
208
-            'AHEE__EE_Form_Section_Proper___construct_finalize__end',
209
-            $this,
210
-            $parent_form_section,
211
-            $name
212
-        );
213
-    }
214
-
215
-
216
-    /**
217
-     * Gets the layout strategy for this form section
218
-     *
219
-     * @return EE_Form_Section_Layout_Base
220
-     */
221
-    public function get_layout_strategy()
222
-    {
223
-        return $this->_layout_strategy;
224
-    }
225
-
226
-
227
-    /**
228
-     * Gets the HTML for a single input for this form section according
229
-     * to the layout strategy
230
-     *
231
-     * @param EE_Form_Input_Base $input
232
-     * @return string
233
-     */
234
-    public function get_html_for_input($input)
235
-    {
236
-        return $this->_layout_strategy->layout_input($input);
237
-    }
238
-
239
-
240
-    /**
241
-     * was_submitted - checks if form inputs are present in request data
242
-     * Basically an alias for form_data_present_in() (which is used by both
243
-     * proper form sections and form inputs)
244
-     *
245
-     * @param null $form_data
246
-     * @return boolean
247
-     * @throws EE_Error
248
-     */
249
-    public function was_submitted($form_data = null)
250
-    {
251
-        return $this->form_data_present_in($form_data);
252
-    }
253
-
254
-    /**
255
-     * Gets the cached request data; but if there is none, or $req_data was set with
256
-     * something different, refresh the cache, and then return it
257
-     * @param null $req_data
258
-     * @return array
259
-     */
260
-    protected function getCachedRequest($req_data = null)
261
-    {
262
-        if (
263
-            $this->cached_request_data === null
264
-            || (
265
-                $req_data !== null
266
-                && $req_data !== $this->cached_request_data
267
-            )
268
-        ) {
269
-            $req_data = apply_filters(
270
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
271
-                $req_data,
272
-                $this
273
-            );
274
-            if ($req_data === null) {
275
-                /** @var RequestInterface $request */
276
-                $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
277
-                $req_data = $request->requestParams();
278
-            }
279
-            $req_data = apply_filters(
280
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
281
-                $req_data,
282
-                $this
283
-            );
284
-            $this->cached_request_data = (array) $req_data;
285
-        }
286
-        return $this->cached_request_data;
287
-    }
288
-
289
-
290
-    /**
291
-     * After the form section is initially created, call this to sanitize the data in the submission
292
-     * which relates to this form section, validate it, and set it as properties on the form.
293
-     *
294
-     * @param array|null $req_data should usually be post data (the default).
295
-     *                             However, you CAN supply a different array.
296
-     *                             Consider using set_defaults() instead however.
297
-     *                             (If you rendered the form in the page using $form_x->get_html()
298
-     *                             the inputs will have the correct name in the request data for this function
299
-     *                             to find them and populate the form with them.
300
-     *                             If you have a flat form (with only input subsections),
301
-     *                             you can supply a flat array where keys
302
-     *                             are the form input names and values are their values)
303
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
304
-     *                             of course, to validate that data, and set errors on the invalid values.
305
-     *                             But if the data has already been validated
306
-     *                             (eg you validated the data then stored it in the DB)
307
-     *                             you may want to skip this step.
308
-     * @throws InvalidArgumentException
309
-     * @throws InvalidInterfaceException
310
-     * @throws InvalidDataTypeException
311
-     * @throws EE_Error
312
-     */
313
-    public function receive_form_submission($req_data = null, $validate = true)
314
-    {
315
-        $req_data = $this->getCachedRequest($req_data);
316
-        $this->_normalize($req_data);
317
-        if ($validate) {
318
-            $this->_validate();
319
-            // if it's invalid, we're going to want to re-display so remember what they submitted
320
-            if (! $this->is_valid()) {
321
-                $this->store_submitted_form_data_in_session();
322
-            }
323
-        }
324
-        if ($this->submission_error_message() === '' && ! $this->is_valid()) {
325
-            $this->set_submission_error_message();
326
-        }
327
-        do_action(
328
-            'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
329
-            $req_data,
330
-            $this,
331
-            $validate
332
-        );
333
-    }
334
-
335
-
336
-    /**
337
-     * caches the originally submitted input values in the session
338
-     * so that they can be used to repopulate the form if it failed validation
339
-     *
340
-     * @return boolean whether or not the data was successfully stored in the session
341
-     * @throws InvalidArgumentException
342
-     * @throws InvalidInterfaceException
343
-     * @throws InvalidDataTypeException
344
-     * @throws EE_Error
345
-     */
346
-    protected function store_submitted_form_data_in_session()
347
-    {
348
-        $session = EE_Registry::instance()->SSN;
349
-        if ($session instanceof EE_Session) {
350
-            return EE_Registry::instance()->SSN->set_session_data(
351
-                [
352
-                    EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
353
-                ]
354
-            );
355
-        }
356
-        return false;
357
-    }
358
-
359
-
360
-    /**
361
-     * retrieves the originally submitted input values in the session
362
-     * so that they can be used to repopulate the form if it failed validation
363
-     *
364
-     * @return array
365
-     * @throws InvalidArgumentException
366
-     * @throws InvalidInterfaceException
367
-     * @throws InvalidDataTypeException
368
-     */
369
-    protected function get_submitted_form_data_from_session()
370
-    {
371
-        $session = EE_Registry::instance()->SSN;
372
-        if ($session instanceof EE_Session) {
373
-            return $session->get_session_data(
374
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
375
-            );
376
-        }
377
-        return array();
378
-    }
379
-
380
-
381
-    /**
382
-     * flushed the originally submitted input values from the session
383
-     *
384
-     * @return boolean whether or not the data was successfully removed from the session
385
-     * @throws InvalidArgumentException
386
-     * @throws InvalidInterfaceException
387
-     * @throws InvalidDataTypeException
388
-     */
389
-    public static function flush_submitted_form_data_from_session()
390
-    {
391
-        return EE_Registry::instance()->SSN->reset_data(
392
-            [EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY]
393
-        );
394
-    }
395
-
396
-
397
-    /**
398
-     * Populates this form and its subsections with data from the session.
399
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
400
-     * validation errors when displaying too)
401
-     * Returns true if the form was populated from the session, false otherwise
402
-     *
403
-     * @return boolean
404
-     * @throws InvalidArgumentException
405
-     * @throws InvalidInterfaceException
406
-     * @throws InvalidDataTypeException
407
-     * @throws EE_Error
408
-     */
409
-    public function populate_from_session()
410
-    {
411
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
412
-        if (empty($form_data_in_session)) {
413
-            return false;
414
-        }
415
-        $this->receive_form_submission($form_data_in_session);
416
-        add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
417
-        if ($this->form_data_present_in($form_data_in_session)) {
418
-            return true;
419
-        }
420
-        return false;
421
-    }
422
-
423
-
424
-    /**
425
-     * Populates the default data for the form, given an array where keys are
426
-     * the input names, and values are their values (preferably normalized to be their
427
-     * proper PHP types, not all strings... although that should be ok too).
428
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
429
-     * the value being an array formatted in teh same way
430
-     *
431
-     * @param array $default_data
432
-     * @throws EE_Error
433
-     */
434
-    public function populate_defaults($default_data)
435
-    {
436
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
437
-            if (isset($default_data[ $subsection_name ])) {
438
-                if ($subsection instanceof EE_Form_Input_Base) {
439
-                    $subsection->set_default($default_data[ $subsection_name ]);
440
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
441
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
442
-                }
443
-            }
444
-        }
445
-    }
446
-
447
-
448
-    /**
449
-     * returns true if subsection exists
450
-     *
451
-     * @param string $name
452
-     * @return boolean
453
-     */
454
-    public function subsection_exists($name)
455
-    {
456
-        return isset($this->_subsections[ $name ]) ? true : false;
457
-    }
458
-
459
-
460
-    /**
461
-     * Gets the subsection specified by its name
462
-     *
463
-     * @param string  $name
464
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
465
-     *                                                      so that the inputs will be properly configured.
466
-     *                                                      However, some client code may be ok
467
-     *                                                      with construction finalize being called later
468
-     *                                                      (realizing that the subsections' html names
469
-     *                                                      might not be set yet, etc.)
470
-     * @return EE_Form_Section_Base
471
-     * @throws EE_Error
472
-     */
473
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
474
-    {
475
-        if ($require_construction_to_be_finalized) {
476
-            $this->ensure_construct_finalized_called();
477
-        }
478
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
479
-    }
480
-
481
-
482
-    /**
483
-     * Gets all the validatable subsections of this form section
484
-     *
485
-     * @return EE_Form_Section_Validatable[]
486
-     * @throws EE_Error
487
-     */
488
-    public function get_validatable_subsections()
489
-    {
490
-        $validatable_subsections = array();
491
-        foreach ($this->subsections() as $name => $obj) {
492
-            if ($obj instanceof EE_Form_Section_Validatable) {
493
-                $validatable_subsections[ $name ] = $obj;
494
-            }
495
-        }
496
-        return $validatable_subsections;
497
-    }
498
-
499
-
500
-    /**
501
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
502
-     * throw an EE_Error.
503
-     *
504
-     * @param string  $name
505
-     * @param boolean $require_construction_to_be_finalized most client code should
506
-     *                                                      leave this as TRUE so that the inputs will be properly
507
-     *                                                      configured. However, some client code may be ok with
508
-     *                                                      construction finalize being called later
509
-     *                                                      (realizing that the subsections' html names might not be
510
-     *                                                      set yet, etc.)
511
-     * @return EE_Form_Input_Base
512
-     * @throws EE_Error
513
-     */
514
-    public function get_input($name, $require_construction_to_be_finalized = true)
515
-    {
516
-        $subsection = $this->get_subsection(
517
-            $name,
518
-            $require_construction_to_be_finalized
519
-        );
520
-        if (! $subsection instanceof EE_Form_Input_Base) {
521
-            throw new EE_Error(
522
-                sprintf(
523
-                    esc_html__(
524
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
525
-                        'event_espresso'
526
-                    ),
527
-                    $name,
528
-                    get_class($this),
529
-                    $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
530
-                )
531
-            );
532
-        }
533
-        return $subsection;
534
-    }
535
-
536
-
537
-    /**
538
-     * Like get_input(), gets the proper subsection of the form given the name,
539
-     * otherwise throws an EE_Error
540
-     *
541
-     * @param string  $name
542
-     * @param boolean $require_construction_to_be_finalized most client code should
543
-     *                                                      leave this as TRUE so that the inputs will be properly
544
-     *                                                      configured. However, some client code may be ok with
545
-     *                                                      construction finalize being called later
546
-     *                                                      (realizing that the subsections' html names might not be
547
-     *                                                      set yet, etc.)
548
-     * @return EE_Form_Section_Proper
549
-     * @throws EE_Error
550
-     */
551
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
552
-    {
553
-        $subsection = $this->get_subsection(
554
-            $name,
555
-            $require_construction_to_be_finalized
556
-        );
557
-        if (! $subsection instanceof EE_Form_Section_Proper) {
558
-            throw new EE_Error(
559
-                sprintf(
560
-                    esc_html__(
561
-                        "Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
562
-                        'event_espresso'
563
-                    ),
564
-                    $name,
565
-                    get_class($this)
566
-                )
567
-            );
568
-        }
569
-        return $subsection;
570
-    }
571
-
572
-
573
-    /**
574
-     * Gets the value of the specified input. Should be called after receive_form_submission()
575
-     * or populate_defaults() on the form, where the normalized value on the input is set.
576
-     *
577
-     * @param string $name
578
-     * @return mixed depending on the input's type and its normalization strategy
579
-     * @throws EE_Error
580
-     */
581
-    public function get_input_value($name)
582
-    {
583
-        $input = $this->get_input($name);
584
-        return $input->normalized_value();
585
-    }
586
-
587
-
588
-    /**
589
-     * Checks if this form section itself is valid, and then checks its subsections
590
-     *
591
-     * @throws EE_Error
592
-     * @return boolean
593
-     */
594
-    public function is_valid()
595
-    {
596
-        if ($this->is_valid === null) {
597
-            if (! $this->has_received_submission()) {
598
-                throw new EE_Error(
599
-                    sprintf(
600
-                        esc_html__(
601
-                            'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
602
-                            'event_espresso'
603
-                        )
604
-                    )
605
-                );
606
-            }
607
-            if (! parent::is_valid()) {
608
-                $this->is_valid = false;
609
-            } else {
610
-                // ok so no general errors to this entire form section.
611
-                // so let's check the subsections, but only set errors if that hasn't been done yet
612
-                $this->is_valid = true;
613
-                foreach ($this->get_validatable_subsections() as $subsection) {
614
-                    if (! $subsection->is_valid()) {
615
-                        $this->is_valid = false;
616
-                    }
617
-                }
618
-            }
619
-        }
620
-        return $this->is_valid;
621
-    }
622
-
623
-
624
-    /**
625
-     * gets the default name of this form section if none is specified
626
-     *
627
-     * @return void
628
-     */
629
-    protected function _set_default_name_if_empty()
630
-    {
631
-        if (! $this->_name) {
632
-            $classname    = get_class($this);
633
-            $default_name = str_replace('EE_', '', $classname);
634
-            $this->_name  = $default_name;
635
-        }
636
-    }
637
-
638
-
639
-    /**
640
-     * Returns the HTML for the form, except for the form opening and closing tags
641
-     * (as the form section doesn't know where you necessarily want to send the information to),
642
-     * and except for a submit button. Enqueues JS and CSS; if called early enough we will
643
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
644
-     * Not doing_it_wrong because theoretically this CAN be used properly,
645
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
646
-     * any CSS.
647
-     *
648
-     * @throws InvalidArgumentException
649
-     * @throws InvalidInterfaceException
650
-     * @throws InvalidDataTypeException
651
-     * @throws EE_Error
652
-     */
653
-    public function get_html_and_js()
654
-    {
655
-        $this->enqueue_js();
656
-        return $this->get_html();
657
-    }
658
-
659
-
660
-    /**
661
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
662
-     *
663
-     * @param bool $display_previously_submitted_data
664
-     * @return string
665
-     * @throws InvalidArgumentException
666
-     * @throws InvalidInterfaceException
667
-     * @throws InvalidDataTypeException
668
-     * @throws EE_Error
669
-     * @throws EE_Error
670
-     * @throws EE_Error
671
-     */
672
-    public function get_html($display_previously_submitted_data = true)
673
-    {
674
-        $this->ensure_construct_finalized_called();
675
-        if ($display_previously_submitted_data) {
676
-            $this->populate_from_session();
677
-        }
678
-        return $this->_form_html_filter
679
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
680
-            : $this->_layout_strategy->layout_form();
681
-    }
682
-
683
-
684
-    /**
685
-     * enqueues JS and CSS for the form.
686
-     * It is preferred to call this before wp_enqueue_scripts so the
687
-     * scripts and styles can be put in the header, but if called later
688
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
689
-     * only be in the header; but in HTML5 its ok in the body.
690
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
691
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
692
-     *
693
-     * @return void
694
-     * @throws EE_Error
695
-     */
696
-    public function enqueue_js()
697
-    {
698
-        $this->_enqueue_and_localize_form_js();
699
-        foreach ($this->subsections() as $subsection) {
700
-            $subsection->enqueue_js();
701
-        }
702
-    }
703
-
704
-
705
-    /**
706
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
707
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
708
-     * the wp_enqueue_scripts hook.
709
-     * However, registering the form js and localizing it can happen when we
710
-     * actually output the form (which is preferred, seeing how teh form's fields
711
-     * could change until it's actually outputted)
712
-     *
713
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
714
-     *                                                    to be triggered automatically or not
715
-     * @return void
716
-     */
717
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
718
-    {
719
-        wp_register_script(
720
-            'ee_form_section_validation',
721
-            EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
722
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
723
-            EVENT_ESPRESSO_VERSION,
724
-            true
725
-        );
726
-        wp_localize_script(
727
-            'ee_form_section_validation',
728
-            'ee_form_section_validation_init',
729
-            array('init' => $init_form_validation_automatically ? '1' : '0')
730
-        );
731
-    }
732
-
733
-
734
-    /**
735
-     * gets the variables used by form_section_validation.js.
736
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
737
-     * but before the wordpress hook wp_loaded
738
-     *
739
-     * @throws EE_Error
740
-     */
741
-    public function _enqueue_and_localize_form_js()
742
-    {
743
-        $this->ensure_construct_finalized_called();
744
-        // actually, we don't want to localize just yet. There may be other forms on the page.
745
-        // so we need to add our form section data to a static variable accessible by all form sections
746
-        // and localize it just before the footer
747
-        $this->localize_validation_rules();
748
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
749
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
750
-    }
751
-
752
-
753
-    /**
754
-     * add our form section data to a static variable accessible by all form sections
755
-     *
756
-     * @param bool $return_for_subsection
757
-     * @return void
758
-     * @throws EE_Error
759
-     */
760
-    public function localize_validation_rules($return_for_subsection = false)
761
-    {
762
-        // we only want to localize vars ONCE for the entire form,
763
-        // so if the form section doesn't have a parent, then it must be the top dog
764
-        if ($return_for_subsection || ! $this->parent_section()) {
765
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
766
-                'form_section_id'  => $this->html_id(true),
767
-                'validation_rules' => $this->get_jquery_validation_rules(),
768
-                'other_data'       => $this->get_other_js_data(),
769
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
770
-            );
771
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
772
-        }
773
-    }
774
-
775
-
776
-    /**
777
-     * Gets an array of extra data that will be useful for client-side javascript.
778
-     * This is primarily data added by inputs and forms in addition to any
779
-     * scripts they might enqueue
780
-     *
781
-     * @param array $form_other_js_data
782
-     * @return array
783
-     * @throws EE_Error
784
-     */
785
-    public function get_other_js_data($form_other_js_data = array())
786
-    {
787
-        foreach ($this->subsections() as $subsection) {
788
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
789
-        }
790
-        return $form_other_js_data;
791
-    }
792
-
793
-
794
-    /**
795
-     * Gets a flat array of inputs for this form section and its subsections.
796
-     * Keys are their form names, and values are the inputs themselves
797
-     *
798
-     * @return EE_Form_Input_Base
799
-     * @throws EE_Error
800
-     */
801
-    public function inputs_in_subsections()
802
-    {
803
-        $inputs = array();
804
-        foreach ($this->subsections() as $subsection) {
805
-            if ($subsection instanceof EE_Form_Input_Base) {
806
-                $inputs[ $subsection->html_name() ] = $subsection;
807
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
808
-                $inputs += $subsection->inputs_in_subsections();
809
-            }
810
-        }
811
-        return $inputs;
812
-    }
813
-
814
-
815
-    /**
816
-     * Gets a flat array of all the validation errors.
817
-     * Keys are html names (because those should be unique)
818
-     * and values are a string of all their validation errors
819
-     *
820
-     * @return string[]
821
-     * @throws EE_Error
822
-     */
823
-    public function subsection_validation_errors_by_html_name()
824
-    {
825
-        $inputs = $this->inputs();
826
-        $errors = array();
827
-        foreach ($inputs as $form_input) {
828
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
829
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
830
-            }
831
-        }
832
-        return $errors;
833
-    }
834
-
835
-
836
-    /**
837
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
838
-     * Should be setup by each form during the _enqueues_and_localize_form_js
839
-     *
840
-     * @throws InvalidArgumentException
841
-     * @throws InvalidInterfaceException
842
-     * @throws InvalidDataTypeException
843
-     */
844
-    public static function localize_script_for_all_forms()
845
-    {
846
-        // allow inputs and stuff to hook in their JS and stuff here
847
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
848
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
849
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
850
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
851
-            : 'wp_default';
852
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
853
-        wp_enqueue_script('ee_form_section_validation');
854
-        wp_localize_script(
855
-            'ee_form_section_validation',
856
-            'ee_form_section_vars',
857
-            EE_Form_Section_Proper::$_js_localization
858
-        );
859
-    }
860
-
861
-
862
-    /**
863
-     * ensure_scripts_localized
864
-     *
865
-     * @throws EE_Error
866
-     */
867
-    public function ensure_scripts_localized()
868
-    {
869
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
870
-            $this->_enqueue_and_localize_form_js();
871
-        }
872
-    }
873
-
874
-
875
-    /**
876
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
877
-     * is that the key here should be the same as the custom validation rule put in the JS file
878
-     *
879
-     * @return array keys are custom validation rules, and values are internationalized strings
880
-     */
881
-    private static function _get_localized_error_messages()
882
-    {
883
-        return array(
884
-            'validUrl' => wp_strip_all_tags(__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso')),
885
-            'regex'    => wp_strip_all_tags(__('Please check your input', 'event_espresso'))
886
-        );
887
-    }
888
-
889
-
890
-    /**
891
-     * @return array
892
-     */
893
-    public static function js_localization()
894
-    {
895
-        return self::$_js_localization;
896
-    }
897
-
898
-
899
-    /**
900
-     * @return void
901
-     */
902
-    public static function reset_js_localization()
903
-    {
904
-        self::$_js_localization = array();
905
-    }
906
-
907
-
908
-    /**
909
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
910
-     * See parent function for more...
911
-     *
912
-     * @return array
913
-     * @throws EE_Error
914
-     */
915
-    public function get_jquery_validation_rules()
916
-    {
917
-        $jquery_validation_rules = array();
918
-        foreach ($this->get_validatable_subsections() as $subsection) {
919
-            $jquery_validation_rules = array_merge(
920
-                $jquery_validation_rules,
921
-                $subsection->get_jquery_validation_rules()
922
-            );
923
-        }
924
-        return $jquery_validation_rules;
925
-    }
926
-
927
-
928
-    /**
929
-     * Sanitizes all the data and sets the sanitized value of each field
930
-     *
931
-     * @param array $req_data
932
-     * @return void
933
-     * @throws EE_Error
934
-     */
935
-    protected function _normalize($req_data)
936
-    {
937
-        $this->_received_submission = true;
938
-        $this->_validation_errors   = array();
939
-        foreach ($this->get_validatable_subsections() as $subsection) {
940
-            try {
941
-                $subsection->_normalize($req_data);
942
-            } catch (EE_Validation_Error $e) {
943
-                $subsection->add_validation_error($e);
944
-            }
945
-        }
946
-    }
947
-
948
-
949
-    /**
950
-     * Performs validation on this form section and its subsections.
951
-     * For each subsection,
952
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
953
-     * and passes it the subsection, then calls _validate on that subsection.
954
-     * If you need to perform validation on the form as a whole (considering multiple)
955
-     * you would be best to override this _validate method,
956
-     * calling parent::_validate() first.
957
-     *
958
-     * @throws EE_Error
959
-     */
960
-    protected function _validate()
961
-    {
962
-        // reset the cache of whether this form is valid or not- we're re-validating it now
963
-        $this->is_valid = null;
964
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
965
-            if (method_exists($this, '_validate_' . $subsection_name)) {
966
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
967
-            }
968
-            $subsection->_validate();
969
-        }
970
-    }
971
-
972
-
973
-    /**
974
-     * Gets all the validated inputs for the form section
975
-     *
976
-     * @return array
977
-     * @throws EE_Error
978
-     */
979
-    public function valid_data()
980
-    {
981
-        $inputs = array();
982
-        foreach ($this->subsections() as $subsection_name => $subsection) {
983
-            if ($subsection instanceof EE_Form_Section_Proper) {
984
-                $inputs[ $subsection_name ] = $subsection->valid_data();
985
-            } elseif ($subsection instanceof EE_Form_Input_Base) {
986
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
987
-            }
988
-        }
989
-        return $inputs;
990
-    }
991
-
992
-
993
-    /**
994
-     * Gets all the inputs on this form section
995
-     *
996
-     * @return EE_Form_Input_Base[]
997
-     * @throws EE_Error
998
-     */
999
-    public function inputs()
1000
-    {
1001
-        $inputs = array();
1002
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1003
-            if ($subsection instanceof EE_Form_Input_Base) {
1004
-                $inputs[ $subsection_name ] = $subsection;
1005
-            }
1006
-        }
1007
-        return $inputs;
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * Gets all the subsections which are a proper form
1013
-     *
1014
-     * @return EE_Form_Section_Proper[]
1015
-     * @throws EE_Error
1016
-     */
1017
-    public function subforms()
1018
-    {
1019
-        $form_sections = array();
1020
-        foreach ($this->subsections() as $name => $obj) {
1021
-            if ($obj instanceof EE_Form_Section_Proper) {
1022
-                $form_sections[ $name ] = $obj;
1023
-            }
1024
-        }
1025
-        return $form_sections;
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
1031
-     * Consider using inputs() or subforms()
1032
-     * if you only want form inputs or proper form sections.
1033
-     *
1034
-     * @param boolean $require_construction_to_be_finalized most client code should
1035
-     *                                                      leave this as TRUE so that the inputs will be properly
1036
-     *                                                      configured. However, some client code may be ok with
1037
-     *                                                      construction finalize being called later
1038
-     *                                                      (realizing that the subsections' html names might not be
1039
-     *                                                      set yet, etc.)
1040
-     * @return EE_Form_Section_Proper[]
1041
-     * @throws EE_Error
1042
-     */
1043
-    public function subsections($require_construction_to_be_finalized = true)
1044
-    {
1045
-        if ($require_construction_to_be_finalized) {
1046
-            $this->ensure_construct_finalized_called();
1047
-        }
1048
-        return $this->_subsections;
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * Returns whether this form has any subforms or inputs
1054
-     * @return bool
1055
-     */
1056
-    public function hasSubsections()
1057
-    {
1058
-        return ! empty($this->_subsections);
1059
-    }
1060
-
1061
-
1062
-    /**
1063
-     * Returns a simple array where keys are input names, and values are their normalized
1064
-     * values. (Similar to calling get_input_value on inputs)
1065
-     *
1066
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1067
-     *                                        or just this forms' direct children inputs
1068
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1069
-     *                                        or allow multidimensional array
1070
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1071
-     *                                        with array keys being input names
1072
-     *                                        (regardless of whether they are from a subsection or not),
1073
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1074
-     *                                        where keys are always subsection names and values are either
1075
-     *                                        the input's normalized value, or an array like the top-level array
1076
-     * @throws EE_Error
1077
-     */
1078
-    public function input_values($include_subform_inputs = false, $flatten = false)
1079
-    {
1080
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
1081
-    }
1082
-
1083
-
1084
-    /**
1085
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1086
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1087
-     * is not necessarily the value we want to display to users. This creates an array
1088
-     * where keys are the input names, and values are their display values
1089
-     *
1090
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1091
-     *                                        or just this forms' direct children inputs
1092
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1093
-     *                                        or allow multidimensional array
1094
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1095
-     *                                        with array keys being input names
1096
-     *                                        (regardless of whether they are from a subsection or not),
1097
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1098
-     *                                        where keys are always subsection names and values are either
1099
-     *                                        the input's normalized value, or an array like the top-level array
1100
-     * @throws EE_Error
1101
-     */
1102
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1103
-    {
1104
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1105
-    }
1106
-
1107
-
1108
-    /**
1109
-     * Gets the input values from the form
1110
-     *
1111
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1112
-     *                                        or just the normalized value
1113
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1114
-     *                                        or just this forms' direct children inputs
1115
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1116
-     *                                        or allow multidimensional array
1117
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1118
-     *                                        input names (regardless of whether they are from a subsection or not),
1119
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1120
-     *                                        where keys are always subsection names and values are either
1121
-     *                                        the input's normalized value, or an array like the top-level array
1122
-     * @throws EE_Error
1123
-     */
1124
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1125
-    {
1126
-        $input_values = array();
1127
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1128
-            if ($subsection instanceof EE_Form_Input_Base) {
1129
-                $input_values[ $subsection_name ] = $pretty
1130
-                    ? $subsection->pretty_value()
1131
-                    : $subsection->normalized_value();
1132
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1133
-                $subform_input_values = $subsection->_input_values(
1134
-                    $pretty,
1135
-                    $include_subform_inputs,
1136
-                    $flatten
1137
-                );
1138
-                if ($flatten) {
1139
-                    $input_values = array_merge($input_values, $subform_input_values);
1140
-                } else {
1141
-                    $input_values[ $subsection_name ] = $subform_input_values;
1142
-                }
1143
-            }
1144
-        }
1145
-        return $input_values;
1146
-    }
1147
-
1148
-
1149
-    /**
1150
-     * Gets the originally submitted input values from the form
1151
-     *
1152
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1153
-     *                                   or just this forms' direct children inputs
1154
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1155
-     *                                   with array keys being input names
1156
-     *                                   (regardless of whether they are from a subsection or not),
1157
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1158
-     *                                   where keys are always subsection names and values are either
1159
-     *                                   the input's normalized value, or an array like the top-level array
1160
-     * @throws EE_Error
1161
-     */
1162
-    public function submitted_values($include_subforms = false)
1163
-    {
1164
-        $submitted_values = array();
1165
-        foreach ($this->subsections() as $subsection) {
1166
-            if ($subsection instanceof EE_Form_Input_Base) {
1167
-                // is this input part of an array of inputs?
1168
-                if (strpos($subsection->html_name(), '[') !== false) {
1169
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1170
-                        explode(
1171
-                            '[',
1172
-                            str_replace(']', '', $subsection->html_name())
1173
-                        ),
1174
-                        $subsection->raw_value()
1175
-                    );
1176
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1177
-                } else {
1178
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1179
-                }
1180
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1181
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1182
-                $submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1183
-            }
1184
-        }
1185
-        return $submitted_values;
1186
-    }
1187
-
1188
-
1189
-    /**
1190
-     * Indicates whether or not this form has received a submission yet
1191
-     * (ie, had receive_form_submission called on it yet)
1192
-     *
1193
-     * @return boolean
1194
-     * @throws EE_Error
1195
-     */
1196
-    public function has_received_submission()
1197
-    {
1198
-        $this->ensure_construct_finalized_called();
1199
-        return $this->_received_submission;
1200
-    }
1201
-
1202
-
1203
-    /**
1204
-     * Equivalent to passing 'exclude' in the constructor's options array.
1205
-     * Removes the listed inputs from the form
1206
-     *
1207
-     * @param array $inputs_to_exclude values are the input names
1208
-     * @return void
1209
-     */
1210
-    public function exclude(array $inputs_to_exclude = array())
1211
-    {
1212
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1213
-            unset($this->_subsections[ $input_to_exclude_name ]);
1214
-        }
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1220
-     * @param array $inputs_to_hide
1221
-     * @throws EE_Error
1222
-     */
1223
-    public function hide(array $inputs_to_hide = array())
1224
-    {
1225
-        foreach ($inputs_to_hide as $input_to_hide) {
1226
-            $input = $this->get_input($input_to_hide);
1227
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1228
-        }
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * add_subsections
1234
-     * Adds the listed subsections to the form section.
1235
-     * If $subsection_name_to_target is provided,
1236
-     * then new subsections are added before or after that subsection,
1237
-     * otherwise to the start or end of the entire subsections array.
1238
-     *
1239
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1240
-     *                                                          where keys are their names
1241
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1242
-     *                                                          should be added before or after
1243
-     *                                                          IF $subsection_name_to_target is null,
1244
-     *                                                          then $new_subsections will be added to
1245
-     *                                                          the beginning or end of the entire subsections array
1246
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1247
-     *                                                          $subsection_name_to_target,
1248
-     *                                                          or if $subsection_name_to_target is null,
1249
-     *                                                          before or after entire subsections array
1250
-     * @return void
1251
-     * @throws EE_Error
1252
-     */
1253
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1254
-    {
1255
-        foreach ($new_subsections as $subsection_name => $subsection) {
1256
-            if (! $subsection instanceof EE_Form_Section_Base) {
1257
-                EE_Error::add_error(
1258
-                    sprintf(
1259
-                        esc_html__(
1260
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1261
-                            'event_espresso'
1262
-                        ),
1263
-                        get_class($subsection),
1264
-                        $subsection_name,
1265
-                        $this->name()
1266
-                    ),
1267
-                    __FILE__,
1268
-                    __FUNCTION__,
1269
-                    __LINE__
1270
-                );
1271
-                unset($new_subsections[ $subsection_name ]);
1272
-            }
1273
-        }
1274
-        $this->_subsections = EEH_Array::insert_into_array(
1275
-            $this->_subsections,
1276
-            $new_subsections,
1277
-            $subsection_name_to_target,
1278
-            $add_before
1279
-        );
1280
-        if ($this->_construction_finalized) {
1281
-            foreach ($this->_subsections as $name => $subsection) {
1282
-                $subsection->_construct_finalize($this, $name);
1283
-            }
1284
-        }
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     * @param string $subsection_name
1290
-     * @param bool   $recursive
1291
-     * @return bool
1292
-     */
1293
-    public function has_subsection($subsection_name, $recursive = false)
1294
-    {
1295
-        foreach ($this->_subsections as $name => $subsection) {
1296
-            if (
1297
-                $name === $subsection_name
1298
-                || (
1299
-                    $recursive
1300
-                    && $subsection instanceof EE_Form_Section_Proper
1301
-                    && $subsection->has_subsection($subsection_name, $recursive)
1302
-                )
1303
-            ) {
1304
-                return true;
1305
-            }
1306
-        }
1307
-        return false;
1308
-    }
1309
-
1310
-
1311
-
1312
-    /**
1313
-     * Just gets all validatable subsections to clean their sensitive data
1314
-     *
1315
-     * @throws EE_Error
1316
-     */
1317
-    public function clean_sensitive_data()
1318
-    {
1319
-        foreach ($this->get_validatable_subsections() as $subsection) {
1320
-            $subsection->clean_sensitive_data();
1321
-        }
1322
-    }
1323
-
1324
-
1325
-    /**
1326
-     * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1327
-     * @param string                           $form_submission_error_message
1328
-     * @param EE_Form_Section_Validatable $form_section unused
1329
-     * @throws EE_Error
1330
-     */
1331
-    public function set_submission_error_message(
1332
-        $form_submission_error_message = ''
1333
-    ) {
1334
-        $this->_form_submission_error_message = ! empty($form_submission_error_message)
1335
-            ? $form_submission_error_message
1336
-            : $this->getAllValidationErrorsString();
1337
-    }
1338
-
1339
-
1340
-    /**
1341
-     * Returns the cached error message. A default value is set for this during _validate(),
1342
-     * (called during receive_form_submission) but it can be explicitly set using
1343
-     * set_submission_error_message
1344
-     *
1345
-     * @return string
1346
-     */
1347
-    public function submission_error_message()
1348
-    {
1349
-        return $this->_form_submission_error_message;
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Sets a message to display if the data submitted to the form was valid.
1355
-     * @param string $form_submission_success_message
1356
-     */
1357
-    public function set_submission_success_message($form_submission_success_message = '')
1358
-    {
1359
-        $this->_form_submission_success_message = ! empty($form_submission_success_message)
1360
-            ? $form_submission_success_message
1361
-            : esc_html__('Form submitted successfully', 'event_espresso');
1362
-    }
1363
-
1364
-
1365
-    /**
1366
-     * Gets a message appropriate for display when the form is correctly submitted
1367
-     * @return string
1368
-     */
1369
-    public function submission_success_message()
1370
-    {
1371
-        return $this->_form_submission_success_message;
1372
-    }
1373
-
1374
-
1375
-    /**
1376
-     * Returns the prefix that should be used on child of this form section for
1377
-     * their html names. If this form section itself has a parent, prepends ITS
1378
-     * prefix onto this form section's prefix. Used primarily by
1379
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1380
-     *
1381
-     * @return string
1382
-     * @throws EE_Error
1383
-     */
1384
-    public function html_name_prefix()
1385
-    {
1386
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1387
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1388
-        }
1389
-        return $this->name();
1390
-    }
1391
-
1392
-
1393
-    /**
1394
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1395
-     * calls it (assumes there is no parent and that we want the name to be whatever
1396
-     * was set, which is probably nothing, or the classname)
1397
-     *
1398
-     * @return string
1399
-     * @throws EE_Error
1400
-     */
1401
-    public function name()
1402
-    {
1403
-        $this->ensure_construct_finalized_called();
1404
-        return parent::name();
1405
-    }
1406
-
1407
-
1408
-    /**
1409
-     * @return EE_Form_Section_Proper
1410
-     * @throws EE_Error
1411
-     */
1412
-    public function parent_section()
1413
-    {
1414
-        $this->ensure_construct_finalized_called();
1415
-        return parent::parent_section();
1416
-    }
1417
-
1418
-
1419
-    /**
1420
-     * make sure construction finalized was called, otherwise children might not be ready
1421
-     *
1422
-     * @return void
1423
-     * @throws EE_Error
1424
-     */
1425
-    public function ensure_construct_finalized_called()
1426
-    {
1427
-        if (! $this->_construction_finalized) {
1428
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1429
-        }
1430
-    }
1431
-
1432
-
1433
-    /**
1434
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1435
-     * are in teh form data. If any are found, returns true. Else false
1436
-     *
1437
-     * @param array $req_data
1438
-     * @return boolean
1439
-     * @throws EE_Error
1440
-     */
1441
-    public function form_data_present_in($req_data = null)
1442
-    {
1443
-        $req_data = $this->getCachedRequest($req_data);
1444
-        foreach ($this->subsections() as $subsection) {
1445
-            if ($subsection instanceof EE_Form_Input_Base) {
1446
-                if ($subsection->form_data_present_in($req_data)) {
1447
-                    return true;
1448
-                }
1449
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1450
-                if ($subsection->form_data_present_in($req_data)) {
1451
-                    return true;
1452
-                }
1453
-            }
1454
-        }
1455
-        return false;
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * Gets validation errors for this form section and subsections
1461
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1462
-     * gets the validation errors for ALL subsection
1463
-     *
1464
-     * @return EE_Validation_Error[]
1465
-     * @throws EE_Error
1466
-     */
1467
-    public function get_validation_errors_accumulated()
1468
-    {
1469
-        $validation_errors = $this->get_validation_errors();
1470
-        foreach ($this->get_validatable_subsections() as $subsection) {
1471
-            if ($subsection instanceof EE_Form_Section_Proper) {
1472
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1473
-            } else {
1474
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1475
-            }
1476
-            if ($validation_errors_on_this_subsection) {
1477
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1478
-            }
1479
-        }
1480
-        return $validation_errors;
1481
-    }
1482
-
1483
-    /**
1484
-     * Fetch validation errors from children and grandchildren and puts them in a single string.
1485
-     * This traverses the form section tree to generate this, but you probably want to instead use
1486
-     * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1487
-     *
1488
-     * @return string
1489
-     * @since 4.9.59.p
1490
-     */
1491
-    protected function getAllValidationErrorsString()
1492
-    {
1493
-        $submission_error_messages = array();
1494
-        // bad, bad, bad registrant
1495
-        foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1496
-            if ($validation_error instanceof EE_Validation_Error) {
1497
-                $form_section = $validation_error->get_form_section();
1498
-                if ($form_section instanceof EE_Form_Input_Base) {
1499
-                    $label = $validation_error->get_form_section()->html_label_text();
1500
-                } elseif ($form_section instanceof EE_Form_Section_Validatable) {
1501
-                    $label = $validation_error->get_form_section()->name();
1502
-                } else {
1503
-                    $label = esc_html__('Unknown', 'event_espresso');
1504
-                }
1505
-                $submission_error_messages[] = sprintf(
1506
-                    esc_html__('%s : %s', 'event_espresso'),
1507
-                    $label,
1508
-                    $validation_error->getMessage()
1509
-                );
1510
-            }
1511
-        }
1512
-        return implode('<br>', $submission_error_messages);
1513
-    }
1514
-
1515
-
1516
-    /**
1517
-     * This isn't just the name of an input, it's a path pointing to an input. The
1518
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1519
-     * dot-dot-slash (../) means to ascend into the parent section.
1520
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1521
-     * which will be returned.
1522
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1523
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1524
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1525
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1526
-     * Etc
1527
-     *
1528
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1529
-     * @return EE_Form_Section_Base
1530
-     * @throws EE_Error
1531
-     */
1532
-    public function find_section_from_path($form_section_path)
1533
-    {
1534
-        // check if we can find the input from purely going straight up the tree
1535
-        $input = parent::find_section_from_path($form_section_path);
1536
-        if ($input instanceof EE_Form_Section_Base) {
1537
-            return $input;
1538
-        }
1539
-        $next_slash_pos = strpos($form_section_path, '/');
1540
-        if ($next_slash_pos !== false) {
1541
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1542
-            $subpath            = substr($form_section_path, $next_slash_pos + 1);
1543
-        } else {
1544
-            $child_section_name = $form_section_path;
1545
-            $subpath            = '';
1546
-        }
1547
-        $child_section = $this->get_subsection($child_section_name);
1548
-        if ($child_section instanceof EE_Form_Section_Base) {
1549
-            return $child_section->find_section_from_path($subpath);
1550
-        }
1551
-        return null;
1552
-    }
18
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
19
+
20
+	/**
21
+	 * Subsections
22
+	 *
23
+	 * @var EE_Form_Section_Validatable[]
24
+	 */
25
+	protected $_subsections = array();
26
+
27
+	/**
28
+	 * Strategy for laying out the form
29
+	 *
30
+	 * @var EE_Form_Section_Layout_Base
31
+	 */
32
+	protected $_layout_strategy;
33
+
34
+	/**
35
+	 * Whether or not this form has received and validated a form submission yet
36
+	 *
37
+	 * @var boolean
38
+	 */
39
+	protected $_received_submission = false;
40
+
41
+	/**
42
+	 * message displayed to users upon successful form submission
43
+	 *
44
+	 * @var string
45
+	 */
46
+	protected $_form_submission_success_message = '';
47
+
48
+	/**
49
+	 * message displayed to users upon unsuccessful form submission
50
+	 *
51
+	 * @var string
52
+	 */
53
+	protected $_form_submission_error_message = '';
54
+
55
+	/**
56
+	 * @var array like post / request
57
+	 */
58
+	protected $cached_request_data;
59
+
60
+	/**
61
+	 * Stores whether this form (and its sub-sections) were found to be valid or not.
62
+	 * Starts off as null, but once the form is validated, it set to either true or false
63
+	 * @var boolean|null
64
+	 */
65
+	protected $is_valid;
66
+
67
+	/**
68
+	 * Stores all the data that will localized for form validation
69
+	 *
70
+	 * @var array
71
+	 */
72
+	protected static $_js_localization = array();
73
+
74
+	/**
75
+	 * whether or not the form's localized validation JS vars have been set
76
+	 *
77
+	 * @type boolean
78
+	 */
79
+	protected static $_scripts_localized = false;
80
+
81
+
82
+	/**
83
+	 * when constructing a proper form section, calls _construct_finalize on children
84
+	 * so that they know who their parent is, and what name they've been given.
85
+	 *
86
+	 * @param array[] $options_array   {
87
+	 * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
88
+	 * @type          $include         string[] numerically-indexed where values are section names to be included,
89
+	 *                                 and in that order. This is handy if you want
90
+	 *                                 the subsections to be ordered differently than the default, and if you override
91
+	 *                                 which fields are shown
92
+	 * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
93
+	 *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
94
+	 *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
95
+	 *                                 items from that list of inclusions)
96
+	 * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
97
+	 *                                 } @see EE_Form_Section_Validatable::__construct()
98
+	 * @throws EE_Error
99
+	 */
100
+	public function __construct($options_array = array())
101
+	{
102
+		$options_array = (array) apply_filters(
103
+			'FHEE__EE_Form_Section_Proper___construct__options_array',
104
+			$options_array,
105
+			$this
106
+		);
107
+		// call parent first, as it may be setting the name
108
+		parent::__construct($options_array);
109
+		// if they've included subsections in the constructor, add them now
110
+		if (isset($options_array['include'])) {
111
+			// we are going to make sure we ONLY have those subsections to include
112
+			// AND we are going to make sure they're in that specified order
113
+			$reordered_subsections = array();
114
+			foreach ($options_array['include'] as $input_name) {
115
+				if (isset($this->_subsections[ $input_name ])) {
116
+					$reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
117
+				}
118
+			}
119
+			$this->_subsections = $reordered_subsections;
120
+		}
121
+		if (isset($options_array['exclude'])) {
122
+			$exclude            = $options_array['exclude'];
123
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
124
+		}
125
+		if (isset($options_array['layout_strategy'])) {
126
+			$this->_layout_strategy = $options_array['layout_strategy'];
127
+		}
128
+		if (! $this->_layout_strategy) {
129
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
130
+		}
131
+		$this->_layout_strategy->_construct_finalize($this);
132
+		// ok so we are definitely going to want the forms JS,
133
+		// so enqueue it or remember to enqueue it during wp_enqueue_scripts
134
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
135
+			// ok so they've constructed this object after when they should have.
136
+			// just enqueue the generic form scripts and initialize the form immediately in the JS
137
+			EE_Form_Section_Proper::wp_enqueue_scripts(true);
138
+		} else {
139
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
141
+		}
142
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
143
+		/**
144
+		 * Gives other plugins a chance to hook in before construct finalize is called.
145
+		 * The form probably doesn't yet have a parent form section.
146
+		 * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
147
+		 * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
148
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
149
+		 *
150
+		 * @since 4.9.32
151
+		 * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
152
+		 *                                              except maybe calling _construct_finalize has been done
153
+		 * @param array                  $options_array options passed into the constructor
154
+		 */
155
+		do_action(
156
+			'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
157
+			$this,
158
+			$options_array
159
+		);
160
+		if (isset($options_array['name'])) {
161
+			$this->_construct_finalize(null, $options_array['name']);
162
+		}
163
+	}
164
+
165
+
166
+	/**
167
+	 * Finishes construction given the parent form section and this form section's name
168
+	 *
169
+	 * @param EE_Form_Section_Proper|null $parent_form_section
170
+	 * @param string                 $name
171
+	 * @throws EE_Error
172
+	 */
173
+	public function _construct_finalize($parent_form_section, $name)
174
+	{
175
+		parent::_construct_finalize($parent_form_section, $name);
176
+		$this->_set_default_name_if_empty();
177
+		$this->_set_default_html_id_if_empty();
178
+		foreach ($this->_subsections as $subsection_name => $subsection) {
179
+			if ($subsection instanceof EE_Form_Section_Base) {
180
+				$subsection->_construct_finalize($this, $subsection_name);
181
+			} else {
182
+				throw new EE_Error(
183
+					sprintf(
184
+						esc_html__(
185
+							'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
186
+							'event_espresso'
187
+						),
188
+						$subsection_name,
189
+						get_class($this),
190
+						$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
191
+					)
192
+				);
193
+			}
194
+		}
195
+		/**
196
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
197
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
198
+		 * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
199
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
200
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
201
+		 * ensured it has a name, HTML IDs, etc
202
+		 *
203
+		 * @param EE_Form_Section_Proper      $this
204
+		 * @param EE_Form_Section_Proper|null $parent_form_section
205
+		 * @param string                      $name
206
+		 */
207
+		do_action(
208
+			'AHEE__EE_Form_Section_Proper___construct_finalize__end',
209
+			$this,
210
+			$parent_form_section,
211
+			$name
212
+		);
213
+	}
214
+
215
+
216
+	/**
217
+	 * Gets the layout strategy for this form section
218
+	 *
219
+	 * @return EE_Form_Section_Layout_Base
220
+	 */
221
+	public function get_layout_strategy()
222
+	{
223
+		return $this->_layout_strategy;
224
+	}
225
+
226
+
227
+	/**
228
+	 * Gets the HTML for a single input for this form section according
229
+	 * to the layout strategy
230
+	 *
231
+	 * @param EE_Form_Input_Base $input
232
+	 * @return string
233
+	 */
234
+	public function get_html_for_input($input)
235
+	{
236
+		return $this->_layout_strategy->layout_input($input);
237
+	}
238
+
239
+
240
+	/**
241
+	 * was_submitted - checks if form inputs are present in request data
242
+	 * Basically an alias for form_data_present_in() (which is used by both
243
+	 * proper form sections and form inputs)
244
+	 *
245
+	 * @param null $form_data
246
+	 * @return boolean
247
+	 * @throws EE_Error
248
+	 */
249
+	public function was_submitted($form_data = null)
250
+	{
251
+		return $this->form_data_present_in($form_data);
252
+	}
253
+
254
+	/**
255
+	 * Gets the cached request data; but if there is none, or $req_data was set with
256
+	 * something different, refresh the cache, and then return it
257
+	 * @param null $req_data
258
+	 * @return array
259
+	 */
260
+	protected function getCachedRequest($req_data = null)
261
+	{
262
+		if (
263
+			$this->cached_request_data === null
264
+			|| (
265
+				$req_data !== null
266
+				&& $req_data !== $this->cached_request_data
267
+			)
268
+		) {
269
+			$req_data = apply_filters(
270
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
271
+				$req_data,
272
+				$this
273
+			);
274
+			if ($req_data === null) {
275
+				/** @var RequestInterface $request */
276
+				$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
277
+				$req_data = $request->requestParams();
278
+			}
279
+			$req_data = apply_filters(
280
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
281
+				$req_data,
282
+				$this
283
+			);
284
+			$this->cached_request_data = (array) $req_data;
285
+		}
286
+		return $this->cached_request_data;
287
+	}
288
+
289
+
290
+	/**
291
+	 * After the form section is initially created, call this to sanitize the data in the submission
292
+	 * which relates to this form section, validate it, and set it as properties on the form.
293
+	 *
294
+	 * @param array|null $req_data should usually be post data (the default).
295
+	 *                             However, you CAN supply a different array.
296
+	 *                             Consider using set_defaults() instead however.
297
+	 *                             (If you rendered the form in the page using $form_x->get_html()
298
+	 *                             the inputs will have the correct name in the request data for this function
299
+	 *                             to find them and populate the form with them.
300
+	 *                             If you have a flat form (with only input subsections),
301
+	 *                             you can supply a flat array where keys
302
+	 *                             are the form input names and values are their values)
303
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
304
+	 *                             of course, to validate that data, and set errors on the invalid values.
305
+	 *                             But if the data has already been validated
306
+	 *                             (eg you validated the data then stored it in the DB)
307
+	 *                             you may want to skip this step.
308
+	 * @throws InvalidArgumentException
309
+	 * @throws InvalidInterfaceException
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws EE_Error
312
+	 */
313
+	public function receive_form_submission($req_data = null, $validate = true)
314
+	{
315
+		$req_data = $this->getCachedRequest($req_data);
316
+		$this->_normalize($req_data);
317
+		if ($validate) {
318
+			$this->_validate();
319
+			// if it's invalid, we're going to want to re-display so remember what they submitted
320
+			if (! $this->is_valid()) {
321
+				$this->store_submitted_form_data_in_session();
322
+			}
323
+		}
324
+		if ($this->submission_error_message() === '' && ! $this->is_valid()) {
325
+			$this->set_submission_error_message();
326
+		}
327
+		do_action(
328
+			'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
329
+			$req_data,
330
+			$this,
331
+			$validate
332
+		);
333
+	}
334
+
335
+
336
+	/**
337
+	 * caches the originally submitted input values in the session
338
+	 * so that they can be used to repopulate the form if it failed validation
339
+	 *
340
+	 * @return boolean whether or not the data was successfully stored in the session
341
+	 * @throws InvalidArgumentException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws InvalidDataTypeException
344
+	 * @throws EE_Error
345
+	 */
346
+	protected function store_submitted_form_data_in_session()
347
+	{
348
+		$session = EE_Registry::instance()->SSN;
349
+		if ($session instanceof EE_Session) {
350
+			return EE_Registry::instance()->SSN->set_session_data(
351
+				[
352
+					EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
353
+				]
354
+			);
355
+		}
356
+		return false;
357
+	}
358
+
359
+
360
+	/**
361
+	 * retrieves the originally submitted input values in the session
362
+	 * so that they can be used to repopulate the form if it failed validation
363
+	 *
364
+	 * @return array
365
+	 * @throws InvalidArgumentException
366
+	 * @throws InvalidInterfaceException
367
+	 * @throws InvalidDataTypeException
368
+	 */
369
+	protected function get_submitted_form_data_from_session()
370
+	{
371
+		$session = EE_Registry::instance()->SSN;
372
+		if ($session instanceof EE_Session) {
373
+			return $session->get_session_data(
374
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
375
+			);
376
+		}
377
+		return array();
378
+	}
379
+
380
+
381
+	/**
382
+	 * flushed the originally submitted input values from the session
383
+	 *
384
+	 * @return boolean whether or not the data was successfully removed from the session
385
+	 * @throws InvalidArgumentException
386
+	 * @throws InvalidInterfaceException
387
+	 * @throws InvalidDataTypeException
388
+	 */
389
+	public static function flush_submitted_form_data_from_session()
390
+	{
391
+		return EE_Registry::instance()->SSN->reset_data(
392
+			[EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY]
393
+		);
394
+	}
395
+
396
+
397
+	/**
398
+	 * Populates this form and its subsections with data from the session.
399
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
400
+	 * validation errors when displaying too)
401
+	 * Returns true if the form was populated from the session, false otherwise
402
+	 *
403
+	 * @return boolean
404
+	 * @throws InvalidArgumentException
405
+	 * @throws InvalidInterfaceException
406
+	 * @throws InvalidDataTypeException
407
+	 * @throws EE_Error
408
+	 */
409
+	public function populate_from_session()
410
+	{
411
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
412
+		if (empty($form_data_in_session)) {
413
+			return false;
414
+		}
415
+		$this->receive_form_submission($form_data_in_session);
416
+		add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
417
+		if ($this->form_data_present_in($form_data_in_session)) {
418
+			return true;
419
+		}
420
+		return false;
421
+	}
422
+
423
+
424
+	/**
425
+	 * Populates the default data for the form, given an array where keys are
426
+	 * the input names, and values are their values (preferably normalized to be their
427
+	 * proper PHP types, not all strings... although that should be ok too).
428
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
429
+	 * the value being an array formatted in teh same way
430
+	 *
431
+	 * @param array $default_data
432
+	 * @throws EE_Error
433
+	 */
434
+	public function populate_defaults($default_data)
435
+	{
436
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
437
+			if (isset($default_data[ $subsection_name ])) {
438
+				if ($subsection instanceof EE_Form_Input_Base) {
439
+					$subsection->set_default($default_data[ $subsection_name ]);
440
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
441
+					$subsection->populate_defaults($default_data[ $subsection_name ]);
442
+				}
443
+			}
444
+		}
445
+	}
446
+
447
+
448
+	/**
449
+	 * returns true if subsection exists
450
+	 *
451
+	 * @param string $name
452
+	 * @return boolean
453
+	 */
454
+	public function subsection_exists($name)
455
+	{
456
+		return isset($this->_subsections[ $name ]) ? true : false;
457
+	}
458
+
459
+
460
+	/**
461
+	 * Gets the subsection specified by its name
462
+	 *
463
+	 * @param string  $name
464
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
465
+	 *                                                      so that the inputs will be properly configured.
466
+	 *                                                      However, some client code may be ok
467
+	 *                                                      with construction finalize being called later
468
+	 *                                                      (realizing that the subsections' html names
469
+	 *                                                      might not be set yet, etc.)
470
+	 * @return EE_Form_Section_Base
471
+	 * @throws EE_Error
472
+	 */
473
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
474
+	{
475
+		if ($require_construction_to_be_finalized) {
476
+			$this->ensure_construct_finalized_called();
477
+		}
478
+		return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
479
+	}
480
+
481
+
482
+	/**
483
+	 * Gets all the validatable subsections of this form section
484
+	 *
485
+	 * @return EE_Form_Section_Validatable[]
486
+	 * @throws EE_Error
487
+	 */
488
+	public function get_validatable_subsections()
489
+	{
490
+		$validatable_subsections = array();
491
+		foreach ($this->subsections() as $name => $obj) {
492
+			if ($obj instanceof EE_Form_Section_Validatable) {
493
+				$validatable_subsections[ $name ] = $obj;
494
+			}
495
+		}
496
+		return $validatable_subsections;
497
+	}
498
+
499
+
500
+	/**
501
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
502
+	 * throw an EE_Error.
503
+	 *
504
+	 * @param string  $name
505
+	 * @param boolean $require_construction_to_be_finalized most client code should
506
+	 *                                                      leave this as TRUE so that the inputs will be properly
507
+	 *                                                      configured. However, some client code may be ok with
508
+	 *                                                      construction finalize being called later
509
+	 *                                                      (realizing that the subsections' html names might not be
510
+	 *                                                      set yet, etc.)
511
+	 * @return EE_Form_Input_Base
512
+	 * @throws EE_Error
513
+	 */
514
+	public function get_input($name, $require_construction_to_be_finalized = true)
515
+	{
516
+		$subsection = $this->get_subsection(
517
+			$name,
518
+			$require_construction_to_be_finalized
519
+		);
520
+		if (! $subsection instanceof EE_Form_Input_Base) {
521
+			throw new EE_Error(
522
+				sprintf(
523
+					esc_html__(
524
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
525
+						'event_espresso'
526
+					),
527
+					$name,
528
+					get_class($this),
529
+					$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
530
+				)
531
+			);
532
+		}
533
+		return $subsection;
534
+	}
535
+
536
+
537
+	/**
538
+	 * Like get_input(), gets the proper subsection of the form given the name,
539
+	 * otherwise throws an EE_Error
540
+	 *
541
+	 * @param string  $name
542
+	 * @param boolean $require_construction_to_be_finalized most client code should
543
+	 *                                                      leave this as TRUE so that the inputs will be properly
544
+	 *                                                      configured. However, some client code may be ok with
545
+	 *                                                      construction finalize being called later
546
+	 *                                                      (realizing that the subsections' html names might not be
547
+	 *                                                      set yet, etc.)
548
+	 * @return EE_Form_Section_Proper
549
+	 * @throws EE_Error
550
+	 */
551
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
552
+	{
553
+		$subsection = $this->get_subsection(
554
+			$name,
555
+			$require_construction_to_be_finalized
556
+		);
557
+		if (! $subsection instanceof EE_Form_Section_Proper) {
558
+			throw new EE_Error(
559
+				sprintf(
560
+					esc_html__(
561
+						"Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
562
+						'event_espresso'
563
+					),
564
+					$name,
565
+					get_class($this)
566
+				)
567
+			);
568
+		}
569
+		return $subsection;
570
+	}
571
+
572
+
573
+	/**
574
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
575
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
576
+	 *
577
+	 * @param string $name
578
+	 * @return mixed depending on the input's type and its normalization strategy
579
+	 * @throws EE_Error
580
+	 */
581
+	public function get_input_value($name)
582
+	{
583
+		$input = $this->get_input($name);
584
+		return $input->normalized_value();
585
+	}
586
+
587
+
588
+	/**
589
+	 * Checks if this form section itself is valid, and then checks its subsections
590
+	 *
591
+	 * @throws EE_Error
592
+	 * @return boolean
593
+	 */
594
+	public function is_valid()
595
+	{
596
+		if ($this->is_valid === null) {
597
+			if (! $this->has_received_submission()) {
598
+				throw new EE_Error(
599
+					sprintf(
600
+						esc_html__(
601
+							'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
602
+							'event_espresso'
603
+						)
604
+					)
605
+				);
606
+			}
607
+			if (! parent::is_valid()) {
608
+				$this->is_valid = false;
609
+			} else {
610
+				// ok so no general errors to this entire form section.
611
+				// so let's check the subsections, but only set errors if that hasn't been done yet
612
+				$this->is_valid = true;
613
+				foreach ($this->get_validatable_subsections() as $subsection) {
614
+					if (! $subsection->is_valid()) {
615
+						$this->is_valid = false;
616
+					}
617
+				}
618
+			}
619
+		}
620
+		return $this->is_valid;
621
+	}
622
+
623
+
624
+	/**
625
+	 * gets the default name of this form section if none is specified
626
+	 *
627
+	 * @return void
628
+	 */
629
+	protected function _set_default_name_if_empty()
630
+	{
631
+		if (! $this->_name) {
632
+			$classname    = get_class($this);
633
+			$default_name = str_replace('EE_', '', $classname);
634
+			$this->_name  = $default_name;
635
+		}
636
+	}
637
+
638
+
639
+	/**
640
+	 * Returns the HTML for the form, except for the form opening and closing tags
641
+	 * (as the form section doesn't know where you necessarily want to send the information to),
642
+	 * and except for a submit button. Enqueues JS and CSS; if called early enough we will
643
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
644
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
645
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
646
+	 * any CSS.
647
+	 *
648
+	 * @throws InvalidArgumentException
649
+	 * @throws InvalidInterfaceException
650
+	 * @throws InvalidDataTypeException
651
+	 * @throws EE_Error
652
+	 */
653
+	public function get_html_and_js()
654
+	{
655
+		$this->enqueue_js();
656
+		return $this->get_html();
657
+	}
658
+
659
+
660
+	/**
661
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
662
+	 *
663
+	 * @param bool $display_previously_submitted_data
664
+	 * @return string
665
+	 * @throws InvalidArgumentException
666
+	 * @throws InvalidInterfaceException
667
+	 * @throws InvalidDataTypeException
668
+	 * @throws EE_Error
669
+	 * @throws EE_Error
670
+	 * @throws EE_Error
671
+	 */
672
+	public function get_html($display_previously_submitted_data = true)
673
+	{
674
+		$this->ensure_construct_finalized_called();
675
+		if ($display_previously_submitted_data) {
676
+			$this->populate_from_session();
677
+		}
678
+		return $this->_form_html_filter
679
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
680
+			: $this->_layout_strategy->layout_form();
681
+	}
682
+
683
+
684
+	/**
685
+	 * enqueues JS and CSS for the form.
686
+	 * It is preferred to call this before wp_enqueue_scripts so the
687
+	 * scripts and styles can be put in the header, but if called later
688
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
689
+	 * only be in the header; but in HTML5 its ok in the body.
690
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
691
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
692
+	 *
693
+	 * @return void
694
+	 * @throws EE_Error
695
+	 */
696
+	public function enqueue_js()
697
+	{
698
+		$this->_enqueue_and_localize_form_js();
699
+		foreach ($this->subsections() as $subsection) {
700
+			$subsection->enqueue_js();
701
+		}
702
+	}
703
+
704
+
705
+	/**
706
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
707
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
708
+	 * the wp_enqueue_scripts hook.
709
+	 * However, registering the form js and localizing it can happen when we
710
+	 * actually output the form (which is preferred, seeing how teh form's fields
711
+	 * could change until it's actually outputted)
712
+	 *
713
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
714
+	 *                                                    to be triggered automatically or not
715
+	 * @return void
716
+	 */
717
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
718
+	{
719
+		wp_register_script(
720
+			'ee_form_section_validation',
721
+			EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
722
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
723
+			EVENT_ESPRESSO_VERSION,
724
+			true
725
+		);
726
+		wp_localize_script(
727
+			'ee_form_section_validation',
728
+			'ee_form_section_validation_init',
729
+			array('init' => $init_form_validation_automatically ? '1' : '0')
730
+		);
731
+	}
732
+
733
+
734
+	/**
735
+	 * gets the variables used by form_section_validation.js.
736
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
737
+	 * but before the wordpress hook wp_loaded
738
+	 *
739
+	 * @throws EE_Error
740
+	 */
741
+	public function _enqueue_and_localize_form_js()
742
+	{
743
+		$this->ensure_construct_finalized_called();
744
+		// actually, we don't want to localize just yet. There may be other forms on the page.
745
+		// so we need to add our form section data to a static variable accessible by all form sections
746
+		// and localize it just before the footer
747
+		$this->localize_validation_rules();
748
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
749
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
750
+	}
751
+
752
+
753
+	/**
754
+	 * add our form section data to a static variable accessible by all form sections
755
+	 *
756
+	 * @param bool $return_for_subsection
757
+	 * @return void
758
+	 * @throws EE_Error
759
+	 */
760
+	public function localize_validation_rules($return_for_subsection = false)
761
+	{
762
+		// we only want to localize vars ONCE for the entire form,
763
+		// so if the form section doesn't have a parent, then it must be the top dog
764
+		if ($return_for_subsection || ! $this->parent_section()) {
765
+			EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
766
+				'form_section_id'  => $this->html_id(true),
767
+				'validation_rules' => $this->get_jquery_validation_rules(),
768
+				'other_data'       => $this->get_other_js_data(),
769
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
770
+			);
771
+			EE_Form_Section_Proper::$_scripts_localized                                = true;
772
+		}
773
+	}
774
+
775
+
776
+	/**
777
+	 * Gets an array of extra data that will be useful for client-side javascript.
778
+	 * This is primarily data added by inputs and forms in addition to any
779
+	 * scripts they might enqueue
780
+	 *
781
+	 * @param array $form_other_js_data
782
+	 * @return array
783
+	 * @throws EE_Error
784
+	 */
785
+	public function get_other_js_data($form_other_js_data = array())
786
+	{
787
+		foreach ($this->subsections() as $subsection) {
788
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
789
+		}
790
+		return $form_other_js_data;
791
+	}
792
+
793
+
794
+	/**
795
+	 * Gets a flat array of inputs for this form section and its subsections.
796
+	 * Keys are their form names, and values are the inputs themselves
797
+	 *
798
+	 * @return EE_Form_Input_Base
799
+	 * @throws EE_Error
800
+	 */
801
+	public function inputs_in_subsections()
802
+	{
803
+		$inputs = array();
804
+		foreach ($this->subsections() as $subsection) {
805
+			if ($subsection instanceof EE_Form_Input_Base) {
806
+				$inputs[ $subsection->html_name() ] = $subsection;
807
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
808
+				$inputs += $subsection->inputs_in_subsections();
809
+			}
810
+		}
811
+		return $inputs;
812
+	}
813
+
814
+
815
+	/**
816
+	 * Gets a flat array of all the validation errors.
817
+	 * Keys are html names (because those should be unique)
818
+	 * and values are a string of all their validation errors
819
+	 *
820
+	 * @return string[]
821
+	 * @throws EE_Error
822
+	 */
823
+	public function subsection_validation_errors_by_html_name()
824
+	{
825
+		$inputs = $this->inputs();
826
+		$errors = array();
827
+		foreach ($inputs as $form_input) {
828
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
829
+				$errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
830
+			}
831
+		}
832
+		return $errors;
833
+	}
834
+
835
+
836
+	/**
837
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
838
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
839
+	 *
840
+	 * @throws InvalidArgumentException
841
+	 * @throws InvalidInterfaceException
842
+	 * @throws InvalidDataTypeException
843
+	 */
844
+	public static function localize_script_for_all_forms()
845
+	{
846
+		// allow inputs and stuff to hook in their JS and stuff here
847
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
848
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
849
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
850
+			? EE_Registry::instance()->CFG->registration->email_validation_level
851
+			: 'wp_default';
852
+		EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
853
+		wp_enqueue_script('ee_form_section_validation');
854
+		wp_localize_script(
855
+			'ee_form_section_validation',
856
+			'ee_form_section_vars',
857
+			EE_Form_Section_Proper::$_js_localization
858
+		);
859
+	}
860
+
861
+
862
+	/**
863
+	 * ensure_scripts_localized
864
+	 *
865
+	 * @throws EE_Error
866
+	 */
867
+	public function ensure_scripts_localized()
868
+	{
869
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
870
+			$this->_enqueue_and_localize_form_js();
871
+		}
872
+	}
873
+
874
+
875
+	/**
876
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
877
+	 * is that the key here should be the same as the custom validation rule put in the JS file
878
+	 *
879
+	 * @return array keys are custom validation rules, and values are internationalized strings
880
+	 */
881
+	private static function _get_localized_error_messages()
882
+	{
883
+		return array(
884
+			'validUrl' => wp_strip_all_tags(__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso')),
885
+			'regex'    => wp_strip_all_tags(__('Please check your input', 'event_espresso'))
886
+		);
887
+	}
888
+
889
+
890
+	/**
891
+	 * @return array
892
+	 */
893
+	public static function js_localization()
894
+	{
895
+		return self::$_js_localization;
896
+	}
897
+
898
+
899
+	/**
900
+	 * @return void
901
+	 */
902
+	public static function reset_js_localization()
903
+	{
904
+		self::$_js_localization = array();
905
+	}
906
+
907
+
908
+	/**
909
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
910
+	 * See parent function for more...
911
+	 *
912
+	 * @return array
913
+	 * @throws EE_Error
914
+	 */
915
+	public function get_jquery_validation_rules()
916
+	{
917
+		$jquery_validation_rules = array();
918
+		foreach ($this->get_validatable_subsections() as $subsection) {
919
+			$jquery_validation_rules = array_merge(
920
+				$jquery_validation_rules,
921
+				$subsection->get_jquery_validation_rules()
922
+			);
923
+		}
924
+		return $jquery_validation_rules;
925
+	}
926
+
927
+
928
+	/**
929
+	 * Sanitizes all the data and sets the sanitized value of each field
930
+	 *
931
+	 * @param array $req_data
932
+	 * @return void
933
+	 * @throws EE_Error
934
+	 */
935
+	protected function _normalize($req_data)
936
+	{
937
+		$this->_received_submission = true;
938
+		$this->_validation_errors   = array();
939
+		foreach ($this->get_validatable_subsections() as $subsection) {
940
+			try {
941
+				$subsection->_normalize($req_data);
942
+			} catch (EE_Validation_Error $e) {
943
+				$subsection->add_validation_error($e);
944
+			}
945
+		}
946
+	}
947
+
948
+
949
+	/**
950
+	 * Performs validation on this form section and its subsections.
951
+	 * For each subsection,
952
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
953
+	 * and passes it the subsection, then calls _validate on that subsection.
954
+	 * If you need to perform validation on the form as a whole (considering multiple)
955
+	 * you would be best to override this _validate method,
956
+	 * calling parent::_validate() first.
957
+	 *
958
+	 * @throws EE_Error
959
+	 */
960
+	protected function _validate()
961
+	{
962
+		// reset the cache of whether this form is valid or not- we're re-validating it now
963
+		$this->is_valid = null;
964
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
965
+			if (method_exists($this, '_validate_' . $subsection_name)) {
966
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
967
+			}
968
+			$subsection->_validate();
969
+		}
970
+	}
971
+
972
+
973
+	/**
974
+	 * Gets all the validated inputs for the form section
975
+	 *
976
+	 * @return array
977
+	 * @throws EE_Error
978
+	 */
979
+	public function valid_data()
980
+	{
981
+		$inputs = array();
982
+		foreach ($this->subsections() as $subsection_name => $subsection) {
983
+			if ($subsection instanceof EE_Form_Section_Proper) {
984
+				$inputs[ $subsection_name ] = $subsection->valid_data();
985
+			} elseif ($subsection instanceof EE_Form_Input_Base) {
986
+				$inputs[ $subsection_name ] = $subsection->normalized_value();
987
+			}
988
+		}
989
+		return $inputs;
990
+	}
991
+
992
+
993
+	/**
994
+	 * Gets all the inputs on this form section
995
+	 *
996
+	 * @return EE_Form_Input_Base[]
997
+	 * @throws EE_Error
998
+	 */
999
+	public function inputs()
1000
+	{
1001
+		$inputs = array();
1002
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1003
+			if ($subsection instanceof EE_Form_Input_Base) {
1004
+				$inputs[ $subsection_name ] = $subsection;
1005
+			}
1006
+		}
1007
+		return $inputs;
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * Gets all the subsections which are a proper form
1013
+	 *
1014
+	 * @return EE_Form_Section_Proper[]
1015
+	 * @throws EE_Error
1016
+	 */
1017
+	public function subforms()
1018
+	{
1019
+		$form_sections = array();
1020
+		foreach ($this->subsections() as $name => $obj) {
1021
+			if ($obj instanceof EE_Form_Section_Proper) {
1022
+				$form_sections[ $name ] = $obj;
1023
+			}
1024
+		}
1025
+		return $form_sections;
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
1031
+	 * Consider using inputs() or subforms()
1032
+	 * if you only want form inputs or proper form sections.
1033
+	 *
1034
+	 * @param boolean $require_construction_to_be_finalized most client code should
1035
+	 *                                                      leave this as TRUE so that the inputs will be properly
1036
+	 *                                                      configured. However, some client code may be ok with
1037
+	 *                                                      construction finalize being called later
1038
+	 *                                                      (realizing that the subsections' html names might not be
1039
+	 *                                                      set yet, etc.)
1040
+	 * @return EE_Form_Section_Proper[]
1041
+	 * @throws EE_Error
1042
+	 */
1043
+	public function subsections($require_construction_to_be_finalized = true)
1044
+	{
1045
+		if ($require_construction_to_be_finalized) {
1046
+			$this->ensure_construct_finalized_called();
1047
+		}
1048
+		return $this->_subsections;
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * Returns whether this form has any subforms or inputs
1054
+	 * @return bool
1055
+	 */
1056
+	public function hasSubsections()
1057
+	{
1058
+		return ! empty($this->_subsections);
1059
+	}
1060
+
1061
+
1062
+	/**
1063
+	 * Returns a simple array where keys are input names, and values are their normalized
1064
+	 * values. (Similar to calling get_input_value on inputs)
1065
+	 *
1066
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1067
+	 *                                        or just this forms' direct children inputs
1068
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1069
+	 *                                        or allow multidimensional array
1070
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1071
+	 *                                        with array keys being input names
1072
+	 *                                        (regardless of whether they are from a subsection or not),
1073
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1074
+	 *                                        where keys are always subsection names and values are either
1075
+	 *                                        the input's normalized value, or an array like the top-level array
1076
+	 * @throws EE_Error
1077
+	 */
1078
+	public function input_values($include_subform_inputs = false, $flatten = false)
1079
+	{
1080
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
1081
+	}
1082
+
1083
+
1084
+	/**
1085
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1086
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1087
+	 * is not necessarily the value we want to display to users. This creates an array
1088
+	 * where keys are the input names, and values are their display values
1089
+	 *
1090
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1091
+	 *                                        or just this forms' direct children inputs
1092
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1093
+	 *                                        or allow multidimensional array
1094
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1095
+	 *                                        with array keys being input names
1096
+	 *                                        (regardless of whether they are from a subsection or not),
1097
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1098
+	 *                                        where keys are always subsection names and values are either
1099
+	 *                                        the input's normalized value, or an array like the top-level array
1100
+	 * @throws EE_Error
1101
+	 */
1102
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1103
+	{
1104
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1105
+	}
1106
+
1107
+
1108
+	/**
1109
+	 * Gets the input values from the form
1110
+	 *
1111
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1112
+	 *                                        or just the normalized value
1113
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1114
+	 *                                        or just this forms' direct children inputs
1115
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1116
+	 *                                        or allow multidimensional array
1117
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1118
+	 *                                        input names (regardless of whether they are from a subsection or not),
1119
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1120
+	 *                                        where keys are always subsection names and values are either
1121
+	 *                                        the input's normalized value, or an array like the top-level array
1122
+	 * @throws EE_Error
1123
+	 */
1124
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1125
+	{
1126
+		$input_values = array();
1127
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1128
+			if ($subsection instanceof EE_Form_Input_Base) {
1129
+				$input_values[ $subsection_name ] = $pretty
1130
+					? $subsection->pretty_value()
1131
+					: $subsection->normalized_value();
1132
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1133
+				$subform_input_values = $subsection->_input_values(
1134
+					$pretty,
1135
+					$include_subform_inputs,
1136
+					$flatten
1137
+				);
1138
+				if ($flatten) {
1139
+					$input_values = array_merge($input_values, $subform_input_values);
1140
+				} else {
1141
+					$input_values[ $subsection_name ] = $subform_input_values;
1142
+				}
1143
+			}
1144
+		}
1145
+		return $input_values;
1146
+	}
1147
+
1148
+
1149
+	/**
1150
+	 * Gets the originally submitted input values from the form
1151
+	 *
1152
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1153
+	 *                                   or just this forms' direct children inputs
1154
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1155
+	 *                                   with array keys being input names
1156
+	 *                                   (regardless of whether they are from a subsection or not),
1157
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1158
+	 *                                   where keys are always subsection names and values are either
1159
+	 *                                   the input's normalized value, or an array like the top-level array
1160
+	 * @throws EE_Error
1161
+	 */
1162
+	public function submitted_values($include_subforms = false)
1163
+	{
1164
+		$submitted_values = array();
1165
+		foreach ($this->subsections() as $subsection) {
1166
+			if ($subsection instanceof EE_Form_Input_Base) {
1167
+				// is this input part of an array of inputs?
1168
+				if (strpos($subsection->html_name(), '[') !== false) {
1169
+					$full_input_name  = EEH_Array::convert_array_values_to_keys(
1170
+						explode(
1171
+							'[',
1172
+							str_replace(']', '', $subsection->html_name())
1173
+						),
1174
+						$subsection->raw_value()
1175
+					);
1176
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1177
+				} else {
1178
+					$submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1179
+				}
1180
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1181
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1182
+				$submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1183
+			}
1184
+		}
1185
+		return $submitted_values;
1186
+	}
1187
+
1188
+
1189
+	/**
1190
+	 * Indicates whether or not this form has received a submission yet
1191
+	 * (ie, had receive_form_submission called on it yet)
1192
+	 *
1193
+	 * @return boolean
1194
+	 * @throws EE_Error
1195
+	 */
1196
+	public function has_received_submission()
1197
+	{
1198
+		$this->ensure_construct_finalized_called();
1199
+		return $this->_received_submission;
1200
+	}
1201
+
1202
+
1203
+	/**
1204
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1205
+	 * Removes the listed inputs from the form
1206
+	 *
1207
+	 * @param array $inputs_to_exclude values are the input names
1208
+	 * @return void
1209
+	 */
1210
+	public function exclude(array $inputs_to_exclude = array())
1211
+	{
1212
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1213
+			unset($this->_subsections[ $input_to_exclude_name ]);
1214
+		}
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1220
+	 * @param array $inputs_to_hide
1221
+	 * @throws EE_Error
1222
+	 */
1223
+	public function hide(array $inputs_to_hide = array())
1224
+	{
1225
+		foreach ($inputs_to_hide as $input_to_hide) {
1226
+			$input = $this->get_input($input_to_hide);
1227
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1228
+		}
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * add_subsections
1234
+	 * Adds the listed subsections to the form section.
1235
+	 * If $subsection_name_to_target is provided,
1236
+	 * then new subsections are added before or after that subsection,
1237
+	 * otherwise to the start or end of the entire subsections array.
1238
+	 *
1239
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1240
+	 *                                                          where keys are their names
1241
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1242
+	 *                                                          should be added before or after
1243
+	 *                                                          IF $subsection_name_to_target is null,
1244
+	 *                                                          then $new_subsections will be added to
1245
+	 *                                                          the beginning or end of the entire subsections array
1246
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1247
+	 *                                                          $subsection_name_to_target,
1248
+	 *                                                          or if $subsection_name_to_target is null,
1249
+	 *                                                          before or after entire subsections array
1250
+	 * @return void
1251
+	 * @throws EE_Error
1252
+	 */
1253
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1254
+	{
1255
+		foreach ($new_subsections as $subsection_name => $subsection) {
1256
+			if (! $subsection instanceof EE_Form_Section_Base) {
1257
+				EE_Error::add_error(
1258
+					sprintf(
1259
+						esc_html__(
1260
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1261
+							'event_espresso'
1262
+						),
1263
+						get_class($subsection),
1264
+						$subsection_name,
1265
+						$this->name()
1266
+					),
1267
+					__FILE__,
1268
+					__FUNCTION__,
1269
+					__LINE__
1270
+				);
1271
+				unset($new_subsections[ $subsection_name ]);
1272
+			}
1273
+		}
1274
+		$this->_subsections = EEH_Array::insert_into_array(
1275
+			$this->_subsections,
1276
+			$new_subsections,
1277
+			$subsection_name_to_target,
1278
+			$add_before
1279
+		);
1280
+		if ($this->_construction_finalized) {
1281
+			foreach ($this->_subsections as $name => $subsection) {
1282
+				$subsection->_construct_finalize($this, $name);
1283
+			}
1284
+		}
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 * @param string $subsection_name
1290
+	 * @param bool   $recursive
1291
+	 * @return bool
1292
+	 */
1293
+	public function has_subsection($subsection_name, $recursive = false)
1294
+	{
1295
+		foreach ($this->_subsections as $name => $subsection) {
1296
+			if (
1297
+				$name === $subsection_name
1298
+				|| (
1299
+					$recursive
1300
+					&& $subsection instanceof EE_Form_Section_Proper
1301
+					&& $subsection->has_subsection($subsection_name, $recursive)
1302
+				)
1303
+			) {
1304
+				return true;
1305
+			}
1306
+		}
1307
+		return false;
1308
+	}
1309
+
1310
+
1311
+
1312
+	/**
1313
+	 * Just gets all validatable subsections to clean their sensitive data
1314
+	 *
1315
+	 * @throws EE_Error
1316
+	 */
1317
+	public function clean_sensitive_data()
1318
+	{
1319
+		foreach ($this->get_validatable_subsections() as $subsection) {
1320
+			$subsection->clean_sensitive_data();
1321
+		}
1322
+	}
1323
+
1324
+
1325
+	/**
1326
+	 * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1327
+	 * @param string                           $form_submission_error_message
1328
+	 * @param EE_Form_Section_Validatable $form_section unused
1329
+	 * @throws EE_Error
1330
+	 */
1331
+	public function set_submission_error_message(
1332
+		$form_submission_error_message = ''
1333
+	) {
1334
+		$this->_form_submission_error_message = ! empty($form_submission_error_message)
1335
+			? $form_submission_error_message
1336
+			: $this->getAllValidationErrorsString();
1337
+	}
1338
+
1339
+
1340
+	/**
1341
+	 * Returns the cached error message. A default value is set for this during _validate(),
1342
+	 * (called during receive_form_submission) but it can be explicitly set using
1343
+	 * set_submission_error_message
1344
+	 *
1345
+	 * @return string
1346
+	 */
1347
+	public function submission_error_message()
1348
+	{
1349
+		return $this->_form_submission_error_message;
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Sets a message to display if the data submitted to the form was valid.
1355
+	 * @param string $form_submission_success_message
1356
+	 */
1357
+	public function set_submission_success_message($form_submission_success_message = '')
1358
+	{
1359
+		$this->_form_submission_success_message = ! empty($form_submission_success_message)
1360
+			? $form_submission_success_message
1361
+			: esc_html__('Form submitted successfully', 'event_espresso');
1362
+	}
1363
+
1364
+
1365
+	/**
1366
+	 * Gets a message appropriate for display when the form is correctly submitted
1367
+	 * @return string
1368
+	 */
1369
+	public function submission_success_message()
1370
+	{
1371
+		return $this->_form_submission_success_message;
1372
+	}
1373
+
1374
+
1375
+	/**
1376
+	 * Returns the prefix that should be used on child of this form section for
1377
+	 * their html names. If this form section itself has a parent, prepends ITS
1378
+	 * prefix onto this form section's prefix. Used primarily by
1379
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1380
+	 *
1381
+	 * @return string
1382
+	 * @throws EE_Error
1383
+	 */
1384
+	public function html_name_prefix()
1385
+	{
1386
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1387
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1388
+		}
1389
+		return $this->name();
1390
+	}
1391
+
1392
+
1393
+	/**
1394
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1395
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1396
+	 * was set, which is probably nothing, or the classname)
1397
+	 *
1398
+	 * @return string
1399
+	 * @throws EE_Error
1400
+	 */
1401
+	public function name()
1402
+	{
1403
+		$this->ensure_construct_finalized_called();
1404
+		return parent::name();
1405
+	}
1406
+
1407
+
1408
+	/**
1409
+	 * @return EE_Form_Section_Proper
1410
+	 * @throws EE_Error
1411
+	 */
1412
+	public function parent_section()
1413
+	{
1414
+		$this->ensure_construct_finalized_called();
1415
+		return parent::parent_section();
1416
+	}
1417
+
1418
+
1419
+	/**
1420
+	 * make sure construction finalized was called, otherwise children might not be ready
1421
+	 *
1422
+	 * @return void
1423
+	 * @throws EE_Error
1424
+	 */
1425
+	public function ensure_construct_finalized_called()
1426
+	{
1427
+		if (! $this->_construction_finalized) {
1428
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1429
+		}
1430
+	}
1431
+
1432
+
1433
+	/**
1434
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1435
+	 * are in teh form data. If any are found, returns true. Else false
1436
+	 *
1437
+	 * @param array $req_data
1438
+	 * @return boolean
1439
+	 * @throws EE_Error
1440
+	 */
1441
+	public function form_data_present_in($req_data = null)
1442
+	{
1443
+		$req_data = $this->getCachedRequest($req_data);
1444
+		foreach ($this->subsections() as $subsection) {
1445
+			if ($subsection instanceof EE_Form_Input_Base) {
1446
+				if ($subsection->form_data_present_in($req_data)) {
1447
+					return true;
1448
+				}
1449
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1450
+				if ($subsection->form_data_present_in($req_data)) {
1451
+					return true;
1452
+				}
1453
+			}
1454
+		}
1455
+		return false;
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * Gets validation errors for this form section and subsections
1461
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1462
+	 * gets the validation errors for ALL subsection
1463
+	 *
1464
+	 * @return EE_Validation_Error[]
1465
+	 * @throws EE_Error
1466
+	 */
1467
+	public function get_validation_errors_accumulated()
1468
+	{
1469
+		$validation_errors = $this->get_validation_errors();
1470
+		foreach ($this->get_validatable_subsections() as $subsection) {
1471
+			if ($subsection instanceof EE_Form_Section_Proper) {
1472
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1473
+			} else {
1474
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1475
+			}
1476
+			if ($validation_errors_on_this_subsection) {
1477
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1478
+			}
1479
+		}
1480
+		return $validation_errors;
1481
+	}
1482
+
1483
+	/**
1484
+	 * Fetch validation errors from children and grandchildren and puts them in a single string.
1485
+	 * This traverses the form section tree to generate this, but you probably want to instead use
1486
+	 * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1487
+	 *
1488
+	 * @return string
1489
+	 * @since 4.9.59.p
1490
+	 */
1491
+	protected function getAllValidationErrorsString()
1492
+	{
1493
+		$submission_error_messages = array();
1494
+		// bad, bad, bad registrant
1495
+		foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1496
+			if ($validation_error instanceof EE_Validation_Error) {
1497
+				$form_section = $validation_error->get_form_section();
1498
+				if ($form_section instanceof EE_Form_Input_Base) {
1499
+					$label = $validation_error->get_form_section()->html_label_text();
1500
+				} elseif ($form_section instanceof EE_Form_Section_Validatable) {
1501
+					$label = $validation_error->get_form_section()->name();
1502
+				} else {
1503
+					$label = esc_html__('Unknown', 'event_espresso');
1504
+				}
1505
+				$submission_error_messages[] = sprintf(
1506
+					esc_html__('%s : %s', 'event_espresso'),
1507
+					$label,
1508
+					$validation_error->getMessage()
1509
+				);
1510
+			}
1511
+		}
1512
+		return implode('<br>', $submission_error_messages);
1513
+	}
1514
+
1515
+
1516
+	/**
1517
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1518
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1519
+	 * dot-dot-slash (../) means to ascend into the parent section.
1520
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1521
+	 * which will be returned.
1522
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1523
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1524
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1525
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1526
+	 * Etc
1527
+	 *
1528
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1529
+	 * @return EE_Form_Section_Base
1530
+	 * @throws EE_Error
1531
+	 */
1532
+	public function find_section_from_path($form_section_path)
1533
+	{
1534
+		// check if we can find the input from purely going straight up the tree
1535
+		$input = parent::find_section_from_path($form_section_path);
1536
+		if ($input instanceof EE_Form_Section_Base) {
1537
+			return $input;
1538
+		}
1539
+		$next_slash_pos = strpos($form_section_path, '/');
1540
+		if ($next_slash_pos !== false) {
1541
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1542
+			$subpath            = substr($form_section_path, $next_slash_pos + 1);
1543
+		} else {
1544
+			$child_section_name = $form_section_path;
1545
+			$subpath            = '';
1546
+		}
1547
+		$child_section = $this->get_subsection($child_section_name);
1548
+		if ($child_section instanceof EE_Form_Section_Base) {
1549
+			return $child_section->find_section_from_path($subpath);
1550
+		}
1551
+		return null;
1552
+	}
1553 1553
 }
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -112,8 +112,8 @@  discard block
 block discarded – undo
112 112
             // AND we are going to make sure they're in that specified order
113 113
             $reordered_subsections = array();
114 114
             foreach ($options_array['include'] as $input_name) {
115
-                if (isset($this->_subsections[ $input_name ])) {
116
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
115
+                if (isset($this->_subsections[$input_name])) {
116
+                    $reordered_subsections[$input_name] = $this->_subsections[$input_name];
117 117
                 }
118 118
             }
119 119
             $this->_subsections = $reordered_subsections;
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
         if (isset($options_array['layout_strategy'])) {
126 126
             $this->_layout_strategy = $options_array['layout_strategy'];
127 127
         }
128
-        if (! $this->_layout_strategy) {
128
+        if ( ! $this->_layout_strategy) {
129 129
             $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
130 130
         }
131 131
         $this->_layout_strategy->_construct_finalize($this);
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
         if ($validate) {
318 318
             $this->_validate();
319 319
             // if it's invalid, we're going to want to re-display so remember what they submitted
320
-            if (! $this->is_valid()) {
320
+            if ( ! $this->is_valid()) {
321 321
                 $this->store_submitted_form_data_in_session();
322 322
             }
323 323
         }
@@ -434,11 +434,11 @@  discard block
 block discarded – undo
434 434
     public function populate_defaults($default_data)
435 435
     {
436 436
         foreach ($this->subsections(false) as $subsection_name => $subsection) {
437
-            if (isset($default_data[ $subsection_name ])) {
437
+            if (isset($default_data[$subsection_name])) {
438 438
                 if ($subsection instanceof EE_Form_Input_Base) {
439
-                    $subsection->set_default($default_data[ $subsection_name ]);
439
+                    $subsection->set_default($default_data[$subsection_name]);
440 440
                 } elseif ($subsection instanceof EE_Form_Section_Proper) {
441
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
441
+                    $subsection->populate_defaults($default_data[$subsection_name]);
442 442
                 }
443 443
             }
444 444
         }
@@ -453,7 +453,7 @@  discard block
 block discarded – undo
453 453
      */
454 454
     public function subsection_exists($name)
455 455
     {
456
-        return isset($this->_subsections[ $name ]) ? true : false;
456
+        return isset($this->_subsections[$name]) ? true : false;
457 457
     }
458 458
 
459 459
 
@@ -475,7 +475,7 @@  discard block
 block discarded – undo
475 475
         if ($require_construction_to_be_finalized) {
476 476
             $this->ensure_construct_finalized_called();
477 477
         }
478
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
478
+        return $this->subsection_exists($name) ? $this->_subsections[$name] : null;
479 479
     }
480 480
 
481 481
 
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
         $validatable_subsections = array();
491 491
         foreach ($this->subsections() as $name => $obj) {
492 492
             if ($obj instanceof EE_Form_Section_Validatable) {
493
-                $validatable_subsections[ $name ] = $obj;
493
+                $validatable_subsections[$name] = $obj;
494 494
             }
495 495
         }
496 496
         return $validatable_subsections;
@@ -517,7 +517,7 @@  discard block
 block discarded – undo
517 517
             $name,
518 518
             $require_construction_to_be_finalized
519 519
         );
520
-        if (! $subsection instanceof EE_Form_Input_Base) {
520
+        if ( ! $subsection instanceof EE_Form_Input_Base) {
521 521
             throw new EE_Error(
522 522
                 sprintf(
523 523
                     esc_html__(
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
             $name,
555 555
             $require_construction_to_be_finalized
556 556
         );
557
-        if (! $subsection instanceof EE_Form_Section_Proper) {
557
+        if ( ! $subsection instanceof EE_Form_Section_Proper) {
558 558
             throw new EE_Error(
559 559
                 sprintf(
560 560
                     esc_html__(
@@ -594,7 +594,7 @@  discard block
 block discarded – undo
594 594
     public function is_valid()
595 595
     {
596 596
         if ($this->is_valid === null) {
597
-            if (! $this->has_received_submission()) {
597
+            if ( ! $this->has_received_submission()) {
598 598
                 throw new EE_Error(
599 599
                     sprintf(
600 600
                         esc_html__(
@@ -604,14 +604,14 @@  discard block
 block discarded – undo
604 604
                     )
605 605
                 );
606 606
             }
607
-            if (! parent::is_valid()) {
607
+            if ( ! parent::is_valid()) {
608 608
                 $this->is_valid = false;
609 609
             } else {
610 610
                 // ok so no general errors to this entire form section.
611 611
                 // so let's check the subsections, but only set errors if that hasn't been done yet
612 612
                 $this->is_valid = true;
613 613
                 foreach ($this->get_validatable_subsections() as $subsection) {
614
-                    if (! $subsection->is_valid()) {
614
+                    if ( ! $subsection->is_valid()) {
615 615
                         $this->is_valid = false;
616 616
                     }
617 617
                 }
@@ -628,7 +628,7 @@  discard block
 block discarded – undo
628 628
      */
629 629
     protected function _set_default_name_if_empty()
630 630
     {
631
-        if (! $this->_name) {
631
+        if ( ! $this->_name) {
632 632
             $classname    = get_class($this);
633 633
             $default_name = str_replace('EE_', '', $classname);
634 634
             $this->_name  = $default_name;
@@ -718,7 +718,7 @@  discard block
 block discarded – undo
718 718
     {
719 719
         wp_register_script(
720 720
             'ee_form_section_validation',
721
-            EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
721
+            EE_GLOBAL_ASSETS_URL.'scripts'.'/form_section_validation.js',
722 722
             array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
723 723
             EVENT_ESPRESSO_VERSION,
724 724
             true
@@ -762,13 +762,13 @@  discard block
 block discarded – undo
762 762
         // we only want to localize vars ONCE for the entire form,
763 763
         // so if the form section doesn't have a parent, then it must be the top dog
764 764
         if ($return_for_subsection || ! $this->parent_section()) {
765
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
765
+            EE_Form_Section_Proper::$_js_localization['form_data'][$this->html_id()] = array(
766 766
                 'form_section_id'  => $this->html_id(true),
767 767
                 'validation_rules' => $this->get_jquery_validation_rules(),
768 768
                 'other_data'       => $this->get_other_js_data(),
769 769
                 'errors'           => $this->subsection_validation_errors_by_html_name(),
770 770
             );
771
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
771
+            EE_Form_Section_Proper::$_scripts_localized = true;
772 772
         }
773 773
     }
774 774
 
@@ -803,7 +803,7 @@  discard block
 block discarded – undo
803 803
         $inputs = array();
804 804
         foreach ($this->subsections() as $subsection) {
805 805
             if ($subsection instanceof EE_Form_Input_Base) {
806
-                $inputs[ $subsection->html_name() ] = $subsection;
806
+                $inputs[$subsection->html_name()] = $subsection;
807 807
             } elseif ($subsection instanceof EE_Form_Section_Proper) {
808 808
                 $inputs += $subsection->inputs_in_subsections();
809 809
             }
@@ -826,7 +826,7 @@  discard block
 block discarded – undo
826 826
         $errors = array();
827 827
         foreach ($inputs as $form_input) {
828 828
             if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
829
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
829
+                $errors[$form_input->html_name()] = $form_input->get_validation_error_string();
830 830
             }
831 831
         }
832 832
         return $errors;
@@ -849,7 +849,7 @@  discard block
 block discarded – undo
849 849
         $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
850 850
             ? EE_Registry::instance()->CFG->registration->email_validation_level
851 851
             : 'wp_default';
852
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
852
+        EE_Form_Section_Proper::$_js_localization['email_validation_level'] = $email_validation_level;
853 853
         wp_enqueue_script('ee_form_section_validation');
854 854
         wp_localize_script(
855 855
             'ee_form_section_validation',
@@ -866,7 +866,7 @@  discard block
 block discarded – undo
866 866
      */
867 867
     public function ensure_scripts_localized()
868 868
     {
869
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
869
+        if ( ! EE_Form_Section_Proper::$_scripts_localized) {
870 870
             $this->_enqueue_and_localize_form_js();
871 871
         }
872 872
     }
@@ -962,8 +962,8 @@  discard block
 block discarded – undo
962 962
         // reset the cache of whether this form is valid or not- we're re-validating it now
963 963
         $this->is_valid = null;
964 964
         foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
965
-            if (method_exists($this, '_validate_' . $subsection_name)) {
966
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
965
+            if (method_exists($this, '_validate_'.$subsection_name)) {
966
+                call_user_func_array(array($this, '_validate_'.$subsection_name), array($subsection));
967 967
             }
968 968
             $subsection->_validate();
969 969
         }
@@ -981,9 +981,9 @@  discard block
 block discarded – undo
981 981
         $inputs = array();
982 982
         foreach ($this->subsections() as $subsection_name => $subsection) {
983 983
             if ($subsection instanceof EE_Form_Section_Proper) {
984
-                $inputs[ $subsection_name ] = $subsection->valid_data();
984
+                $inputs[$subsection_name] = $subsection->valid_data();
985 985
             } elseif ($subsection instanceof EE_Form_Input_Base) {
986
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
986
+                $inputs[$subsection_name] = $subsection->normalized_value();
987 987
             }
988 988
         }
989 989
         return $inputs;
@@ -1001,7 +1001,7 @@  discard block
 block discarded – undo
1001 1001
         $inputs = array();
1002 1002
         foreach ($this->subsections() as $subsection_name => $subsection) {
1003 1003
             if ($subsection instanceof EE_Form_Input_Base) {
1004
-                $inputs[ $subsection_name ] = $subsection;
1004
+                $inputs[$subsection_name] = $subsection;
1005 1005
             }
1006 1006
         }
1007 1007
         return $inputs;
@@ -1019,7 +1019,7 @@  discard block
 block discarded – undo
1019 1019
         $form_sections = array();
1020 1020
         foreach ($this->subsections() as $name => $obj) {
1021 1021
             if ($obj instanceof EE_Form_Section_Proper) {
1022
-                $form_sections[ $name ] = $obj;
1022
+                $form_sections[$name] = $obj;
1023 1023
             }
1024 1024
         }
1025 1025
         return $form_sections;
@@ -1126,7 +1126,7 @@  discard block
 block discarded – undo
1126 1126
         $input_values = array();
1127 1127
         foreach ($this->subsections() as $subsection_name => $subsection) {
1128 1128
             if ($subsection instanceof EE_Form_Input_Base) {
1129
-                $input_values[ $subsection_name ] = $pretty
1129
+                $input_values[$subsection_name] = $pretty
1130 1130
                     ? $subsection->pretty_value()
1131 1131
                     : $subsection->normalized_value();
1132 1132
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
                 if ($flatten) {
1139 1139
                     $input_values = array_merge($input_values, $subform_input_values);
1140 1140
                 } else {
1141
-                    $input_values[ $subsection_name ] = $subform_input_values;
1141
+                    $input_values[$subsection_name] = $subform_input_values;
1142 1142
                 }
1143 1143
             }
1144 1144
         }
@@ -1166,7 +1166,7 @@  discard block
 block discarded – undo
1166 1166
             if ($subsection instanceof EE_Form_Input_Base) {
1167 1167
                 // is this input part of an array of inputs?
1168 1168
                 if (strpos($subsection->html_name(), '[') !== false) {
1169
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1169
+                    $full_input_name = EEH_Array::convert_array_values_to_keys(
1170 1170
                         explode(
1171 1171
                             '[',
1172 1172
                             str_replace(']', '', $subsection->html_name())
@@ -1175,7 +1175,7 @@  discard block
 block discarded – undo
1175 1175
                     );
1176 1176
                     $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1177 1177
                 } else {
1178
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1178
+                    $submitted_values[$subsection->html_name()] = $subsection->raw_value();
1179 1179
                 }
1180 1180
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1181 1181
                 $subform_input_values = $subsection->submitted_values($include_subforms);
@@ -1210,7 +1210,7 @@  discard block
 block discarded – undo
1210 1210
     public function exclude(array $inputs_to_exclude = array())
1211 1211
     {
1212 1212
         foreach ($inputs_to_exclude as $input_to_exclude_name) {
1213
-            unset($this->_subsections[ $input_to_exclude_name ]);
1213
+            unset($this->_subsections[$input_to_exclude_name]);
1214 1214
         }
1215 1215
     }
1216 1216
 
@@ -1253,7 +1253,7 @@  discard block
 block discarded – undo
1253 1253
     public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1254 1254
     {
1255 1255
         foreach ($new_subsections as $subsection_name => $subsection) {
1256
-            if (! $subsection instanceof EE_Form_Section_Base) {
1256
+            if ( ! $subsection instanceof EE_Form_Section_Base) {
1257 1257
                 EE_Error::add_error(
1258 1258
                     sprintf(
1259 1259
                         esc_html__(
@@ -1268,7 +1268,7 @@  discard block
 block discarded – undo
1268 1268
                     __FUNCTION__,
1269 1269
                     __LINE__
1270 1270
                 );
1271
-                unset($new_subsections[ $subsection_name ]);
1271
+                unset($new_subsections[$subsection_name]);
1272 1272
             }
1273 1273
         }
1274 1274
         $this->_subsections = EEH_Array::insert_into_array(
@@ -1384,7 +1384,7 @@  discard block
 block discarded – undo
1384 1384
     public function html_name_prefix()
1385 1385
     {
1386 1386
         if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1387
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1387
+            return $this->parent_section()->html_name_prefix().'['.$this->name().']';
1388 1388
         }
1389 1389
         return $this->name();
1390 1390
     }
@@ -1424,7 +1424,7 @@  discard block
 block discarded – undo
1424 1424
      */
1425 1425
     public function ensure_construct_finalized_called()
1426 1426
     {
1427
-        if (! $this->_construction_finalized) {
1427
+        if ( ! $this->_construction_finalized) {
1428 1428
             $this->_construct_finalize($this->_parent_section, $this->_name);
1429 1429
         }
1430 1430
     }
Please login to merge, or discard this patch.