Completed
Branch master (8de7dd)
by
unknown
06:29
created
modules/ticket_selector/TicketSelectorRowStandard.php 1 patch
Indentation   +382 added lines, -382 removed lines patch added patch discarded remove patch
@@ -19,390 +19,390 @@
 block discarded – undo
19 19
  */
20 20
 class TicketSelectorRowStandard extends TicketSelectorRow
21 21
 {
22
-    /**
23
-     * @var TicketDetails
24
-     */
25
-    protected $ticket_details;
26
-
27
-    /**
28
-     * @var EE_Ticket_Selector_Config
29
-     */
30
-    protected $template_settings;
31
-
32
-    /**
33
-     * @var EE_Tax_Config
34
-     */
35
-    protected $tax_settings;
36
-
37
-    /**
38
-     * @var boolean
39
-     */
40
-    protected $prices_displayed_including_taxes;
41
-
42
-    /**
43
-     * @var int
44
-     */
45
-    protected $row;
46
-
47
-    /**
48
-     * @var int
49
-     */
50
-    protected $cols;
51
-
52
-    /**
53
-     * @var boolean
54
-     */
55
-    protected $hidden_input_qty = false;
56
-
57
-    /**
58
-     * @var string
59
-     */
60
-    protected $ticket_datetime_classes;
61
-
62
-    private bool $use_new_checkbox_selector;
63
-
64
-
65
-    /**
66
-     * TicketDetails constructor.
67
-     *
68
-     * @param TicketDetails $ticket_details
69
-     * @param EE_Tax_Config $tax_settings
70
-     * @param int           $total_tickets
71
-     * @param int           $max_attendees
72
-     * @param int           $row
73
-     * @param int           $cols
74
-     * @param boolean       $required_ticket_sold_out
75
-     * @param string        $event_status
76
-     * @param string        $ticket_datetime_classes
77
-     * @param bool          $use_new_checkbox_selector
78
-     * @throws EE_Error
79
-     * @throws UnexpectedEntityException
80
-     */
81
-    public function __construct(
82
-        TicketDetails $ticket_details,
83
-        EE_Tax_Config $tax_settings,
84
-        $total_tickets,
85
-        $max_attendees,
86
-        $row,
87
-        $cols,
88
-        $required_ticket_sold_out,
89
-        $event_status,
90
-        $ticket_datetime_classes,
91
-        bool $use_new_checkbox_selector = false
92
-    ) {
93
-        $this->ticket_details = $ticket_details;
94
-        $this->template_settings = $ticket_details->getTemplateSettings();
95
-        $this->tax_settings = $tax_settings;
96
-        $this->row = $row;
97
-        $this->cols = $cols;
98
-        $this->ticket_datetime_classes = $ticket_datetime_classes;
99
-        $this->use_new_checkbox_selector = $use_new_checkbox_selector;
100
-        parent::__construct(
101
-            $ticket_details->getTicket(),
102
-            $max_attendees,
103
-            $ticket_details->getDateFormat(),
104
-            $event_status,
105
-            $required_ticket_sold_out,
106
-            $total_tickets
107
-        );
108
-    }
109
-
110
-
111
-    /**
112
-     * other ticket rows will need to know if a required ticket is sold out,
113
-     * so that they are not offered for sale
114
-     *
115
-     * @return boolean
116
-     */
117
-    public function getRequiredTicketSoldOut()
118
-    {
119
-        return $this->required_ticket_sold_out;
120
-    }
121
-
122
-
123
-    /**
124
-     * @return int
125
-     */
126
-    public function getCols()
127
-    {
128
-        return $this->cols;
129
-    }
130
-
131
-
132
-    /**
133
-     * getHtml
134
-     *
135
-     * @return string
136
-     * @throws EE_Error
137
-     * @throws ReflectionException
138
-     */
139
-    public function getHtml()
140
-    {
141
-        $this->min = 0;
142
-        $this->max = $this->ticket->max();
143
-        $remaining = $this->ticket->remaining();
144
-        $this->setTicketMinAndMax($remaining);
145
-        // set flag if ticket is required (flag is set to start date so that future tickets are not blocked)
146
-        $this->required_ticket_sold_out = $this->ticket->required() && ! $remaining
147
-            ? $this->ticket->start_date()
148
-            : $this->required_ticket_sold_out;
149
-        $this->setTicketPriceDetails();
150
-        $this->setTicketStatusClasses($remaining);
151
-        $filtered_row_html = $this->getFilteredRowHtml();
152
-        if ($filtered_row_html !== false) {
153
-            return $filtered_row_html;
154
-        }
155
-        $ticket_selector_row_html = EEH_HTML::tr(
156
-            '',
157
-            '',
158
-            "tckt-slctr-tbl-tr {$this->status_class}{$this->ticket_datetime_classes} "
159
-            . espresso_get_object_css_class($this->ticket)
160
-        );
161
-        $filtered_row_content = $this->getFilteredRowContents();
162
-        if ($filtered_row_content !== false) {
163
-            if ($this->max_attendees === 1) {
164
-                return $ticket_selector_row_html
165
-                       . $filtered_row_content
166
-                       . $this->ticketQtyAndIdHiddenInputs()
167
-                       . EEH_HTML::trx();
168
-            }
169
-            return $ticket_selector_row_html
170
-                   . $filtered_row_content
171
-                   . EEH_HTML::trx();
172
-        }
173
-        $this->hidden_input_qty = $this->max_attendees > 1;
174
-
175
-        $ticket_selector_row_html .= $this->ticketNameTableCell();
176
-        $ticket_selector_row_html .= $this->ticketPriceTableCell();
177
-        $ticket_selector_row_html .= EEH_HTML::td(
178
-            '',
179
-            '',
180
-            'tckt-slctr-tbl-td-qty cntr',
181
-            '',
182
-            'headers="quantity-' . $this->EVT_ID . '"'
183
-        );
184
-        $this->setTicketStatusDisplay($remaining);
185
-        if (empty($this->ticket_status_display)) {
186
-            $this->hidden_input_qty = false;
187
-            // display submit button since we have tickets available
188
-            add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
189
-            if ($this->max_attendees === 1) {
190
-                // only ONE attendee is allowed to register at a time
191
-                $ticket_selector_row_html .= $this->onlyOneAttendeeCanRegister();
192
-            } else {
193
-                $ticket_selector_row_html .= $this->max === 1 && $this->use_new_checkbox_selector
194
-                    ? $this->ticketCheckboxSelector()
195
-                    : $this->ticketQuantitySelector();
196
-            }
197
-        }
198
-        $ticket_selector_row_html .= $this->ticket_status_display;
199
-        $ticket_selector_row_html .= $this->ticketQtyAndIdHiddenInputs();
200
-        $ticket_selector_row_html .= $this->ticket_details->display(
201
-            $this->ticket_price,
202
-            $remaining,
203
-            $this->cols
204
-        );
205
-        $ticket_selector_row_html .= EEH_HTML::tdx();
206
-        $ticket_selector_row_html .= EEH_HTML::trx();
207
-
208
-
209
-        $this->row++;
210
-        return $ticket_selector_row_html;
211
-    }
212
-
213
-
214
-    /**
215
-     * getTicketPriceDetails
216
-     *
217
-     * @return void
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    protected function setTicketPriceDetails()
222
-    {
223
-        $this->ticket_price = $this->tax_settings->prices_displayed_including_taxes
224
-            ? $this->ticket->get_ticket_total_with_taxes()
225
-            : $this->ticket->get_ticket_subtotal();
226
-        $this->ticket_bundle = false;
227
-        $ticket_min = $this->ticket->min();
228
-        // for ticket bundles, set min and max qty the same
229
-        if ($ticket_min !== 0 && $ticket_min === $this->ticket->max()) {
230
-            $this->ticket_price *= $ticket_min;
231
-            $this->ticket_bundle = true;
232
-        }
233
-        $this->ticket_price = apply_filters(
234
-            'FHEE__ticket_selector_chart_template__ticket_price',
235
-            $this->ticket_price,
236
-            $this->ticket
237
-        );
238
-    }
239
-
240
-
241
-    /**
242
-     * ticketNameTableCell
243
-     *
244
-     * @return string
245
-     * @throws EE_Error
246
-     * @throws ReflectionException
247
-     */
248
-    protected function ticketNameTableCell()
249
-    {
250
-        $html = EEH_HTML::td(
251
-            '',
252
-            '',
253
-            'tckt-slctr-tbl-td-name',
254
-            '',
255
-            'headers="details-' . $this->EVT_ID . '"'
256
-        );
257
-        $html .= EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
258
-        $html .= $this->ticket_details->getShowHideLinks();
259
-        if ($this->ticket->required()) {
260
-            $html .= EEH_HTML::p(
261
-                apply_filters(
262
-                    'FHEE__ticket_selector_chart_template__ticket_required_message',
263
-                    esc_html__('This ticket is required and must be purchased.', 'event_espresso')
264
-                ),
265
-                '',
266
-                'ticket-required-pg'
267
-            );
268
-        }
269
-        $html .= EEH_HTML::tdx();
270
-        return $html;
271
-    }
272
-
273
-
274
-    /**
275
-     * ticketPriceTableCell
276
-     *
277
-     * @return string
278
-     * @throws EE_Error
279
-     * @throws ReflectionException
280
-     */
281
-    protected function ticketPriceTableCell()
282
-    {
283
-        $html = '';
284
-        if (apply_filters('FHEE__ticket_selector_chart_template__display_ticket_price_details', true)) {
285
-            $html .= EEH_HTML::td(
286
-                '',
287
-                '',
288
-                'tckt-slctr-tbl-td-price jst-rght',
289
-                '',
290
-                'headers="price-' . $this->EVT_ID . '"'
291
-            );
292
-            $html .= EEH_HTML::span(
293
-                EEH_Template::format_currency($this->ticket_price),
294
-                '',
295
-                'tckt-price--nowrap'
296
-            );
297
-            $html .= $this->ticket->taxable()
298
-                ? EEH_HTML::span('*', '', 'taxable-tickets-asterisk grey-text')
299
-                : '';
300
-            $html .= ' ';
301
-            // phpcs:disable WordPress.WP.I18n.NoEmptyStrings
302
-            $html .= EEH_HTML::span(
303
-                $this->ticket_bundle
304
-                    ? apply_filters(
305
-                        'FHEE__ticket_selector_chart_template__per_ticket_bundle_text',
306
-                        esc_html__(' / bundle', 'event_espresso')
307
-                    )
308
-                    : apply_filters(
309
-                        'FHEE__ticket_selector_chart_template__per_ticket_text',
310
-                        esc_html__('', 'event_espresso')
311
-                    ),
312
-                '',
313
-                'smaller-text no-bold'
314
-            );
315
-            $html .= ' ';
316
-            $html .= EEH_HTML::tdx();
317
-            $this->cols++;
318
-        }
319
-        return $html;
320
-    }
321
-
322
-
323
-    /**
324
-     * @return string
325
-     * @throws EE_Error
326
-     * @throws ReflectionException
327
-     */
328
-    protected function onlyOneAttendeeCanRegister(): string
329
-    {
330
-        $TKT   = $this->ticket->ID();
331
-        $label = esc_html__('Select this ticket', 'event_espresso');
332
-        $name  = "tkt-slctr-qty-$this->EVT_ID";
333
-        $class = "ticket-selector-tbl-qty-slct";
334
-        $id    = "$class-$this->EVT_ID-$this->row";
335
-        $checked = $this->total_tickets === 1 ? ' checked' : '';
336
-
337
-        return "
22
+	/**
23
+	 * @var TicketDetails
24
+	 */
25
+	protected $ticket_details;
26
+
27
+	/**
28
+	 * @var EE_Ticket_Selector_Config
29
+	 */
30
+	protected $template_settings;
31
+
32
+	/**
33
+	 * @var EE_Tax_Config
34
+	 */
35
+	protected $tax_settings;
36
+
37
+	/**
38
+	 * @var boolean
39
+	 */
40
+	protected $prices_displayed_including_taxes;
41
+
42
+	/**
43
+	 * @var int
44
+	 */
45
+	protected $row;
46
+
47
+	/**
48
+	 * @var int
49
+	 */
50
+	protected $cols;
51
+
52
+	/**
53
+	 * @var boolean
54
+	 */
55
+	protected $hidden_input_qty = false;
56
+
57
+	/**
58
+	 * @var string
59
+	 */
60
+	protected $ticket_datetime_classes;
61
+
62
+	private bool $use_new_checkbox_selector;
63
+
64
+
65
+	/**
66
+	 * TicketDetails constructor.
67
+	 *
68
+	 * @param TicketDetails $ticket_details
69
+	 * @param EE_Tax_Config $tax_settings
70
+	 * @param int           $total_tickets
71
+	 * @param int           $max_attendees
72
+	 * @param int           $row
73
+	 * @param int           $cols
74
+	 * @param boolean       $required_ticket_sold_out
75
+	 * @param string        $event_status
76
+	 * @param string        $ticket_datetime_classes
77
+	 * @param bool          $use_new_checkbox_selector
78
+	 * @throws EE_Error
79
+	 * @throws UnexpectedEntityException
80
+	 */
81
+	public function __construct(
82
+		TicketDetails $ticket_details,
83
+		EE_Tax_Config $tax_settings,
84
+		$total_tickets,
85
+		$max_attendees,
86
+		$row,
87
+		$cols,
88
+		$required_ticket_sold_out,
89
+		$event_status,
90
+		$ticket_datetime_classes,
91
+		bool $use_new_checkbox_selector = false
92
+	) {
93
+		$this->ticket_details = $ticket_details;
94
+		$this->template_settings = $ticket_details->getTemplateSettings();
95
+		$this->tax_settings = $tax_settings;
96
+		$this->row = $row;
97
+		$this->cols = $cols;
98
+		$this->ticket_datetime_classes = $ticket_datetime_classes;
99
+		$this->use_new_checkbox_selector = $use_new_checkbox_selector;
100
+		parent::__construct(
101
+			$ticket_details->getTicket(),
102
+			$max_attendees,
103
+			$ticket_details->getDateFormat(),
104
+			$event_status,
105
+			$required_ticket_sold_out,
106
+			$total_tickets
107
+		);
108
+	}
109
+
110
+
111
+	/**
112
+	 * other ticket rows will need to know if a required ticket is sold out,
113
+	 * so that they are not offered for sale
114
+	 *
115
+	 * @return boolean
116
+	 */
117
+	public function getRequiredTicketSoldOut()
118
+	{
119
+		return $this->required_ticket_sold_out;
120
+	}
121
+
122
+
123
+	/**
124
+	 * @return int
125
+	 */
126
+	public function getCols()
127
+	{
128
+		return $this->cols;
129
+	}
130
+
131
+
132
+	/**
133
+	 * getHtml
134
+	 *
135
+	 * @return string
136
+	 * @throws EE_Error
137
+	 * @throws ReflectionException
138
+	 */
139
+	public function getHtml()
140
+	{
141
+		$this->min = 0;
142
+		$this->max = $this->ticket->max();
143
+		$remaining = $this->ticket->remaining();
144
+		$this->setTicketMinAndMax($remaining);
145
+		// set flag if ticket is required (flag is set to start date so that future tickets are not blocked)
146
+		$this->required_ticket_sold_out = $this->ticket->required() && ! $remaining
147
+			? $this->ticket->start_date()
148
+			: $this->required_ticket_sold_out;
149
+		$this->setTicketPriceDetails();
150
+		$this->setTicketStatusClasses($remaining);
151
+		$filtered_row_html = $this->getFilteredRowHtml();
152
+		if ($filtered_row_html !== false) {
153
+			return $filtered_row_html;
154
+		}
155
+		$ticket_selector_row_html = EEH_HTML::tr(
156
+			'',
157
+			'',
158
+			"tckt-slctr-tbl-tr {$this->status_class}{$this->ticket_datetime_classes} "
159
+			. espresso_get_object_css_class($this->ticket)
160
+		);
161
+		$filtered_row_content = $this->getFilteredRowContents();
162
+		if ($filtered_row_content !== false) {
163
+			if ($this->max_attendees === 1) {
164
+				return $ticket_selector_row_html
165
+					   . $filtered_row_content
166
+					   . $this->ticketQtyAndIdHiddenInputs()
167
+					   . EEH_HTML::trx();
168
+			}
169
+			return $ticket_selector_row_html
170
+				   . $filtered_row_content
171
+				   . EEH_HTML::trx();
172
+		}
173
+		$this->hidden_input_qty = $this->max_attendees > 1;
174
+
175
+		$ticket_selector_row_html .= $this->ticketNameTableCell();
176
+		$ticket_selector_row_html .= $this->ticketPriceTableCell();
177
+		$ticket_selector_row_html .= EEH_HTML::td(
178
+			'',
179
+			'',
180
+			'tckt-slctr-tbl-td-qty cntr',
181
+			'',
182
+			'headers="quantity-' . $this->EVT_ID . '"'
183
+		);
184
+		$this->setTicketStatusDisplay($remaining);
185
+		if (empty($this->ticket_status_display)) {
186
+			$this->hidden_input_qty = false;
187
+			// display submit button since we have tickets available
188
+			add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
189
+			if ($this->max_attendees === 1) {
190
+				// only ONE attendee is allowed to register at a time
191
+				$ticket_selector_row_html .= $this->onlyOneAttendeeCanRegister();
192
+			} else {
193
+				$ticket_selector_row_html .= $this->max === 1 && $this->use_new_checkbox_selector
194
+					? $this->ticketCheckboxSelector()
195
+					: $this->ticketQuantitySelector();
196
+			}
197
+		}
198
+		$ticket_selector_row_html .= $this->ticket_status_display;
199
+		$ticket_selector_row_html .= $this->ticketQtyAndIdHiddenInputs();
200
+		$ticket_selector_row_html .= $this->ticket_details->display(
201
+			$this->ticket_price,
202
+			$remaining,
203
+			$this->cols
204
+		);
205
+		$ticket_selector_row_html .= EEH_HTML::tdx();
206
+		$ticket_selector_row_html .= EEH_HTML::trx();
207
+
208
+
209
+		$this->row++;
210
+		return $ticket_selector_row_html;
211
+	}
212
+
213
+
214
+	/**
215
+	 * getTicketPriceDetails
216
+	 *
217
+	 * @return void
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	protected function setTicketPriceDetails()
222
+	{
223
+		$this->ticket_price = $this->tax_settings->prices_displayed_including_taxes
224
+			? $this->ticket->get_ticket_total_with_taxes()
225
+			: $this->ticket->get_ticket_subtotal();
226
+		$this->ticket_bundle = false;
227
+		$ticket_min = $this->ticket->min();
228
+		// for ticket bundles, set min and max qty the same
229
+		if ($ticket_min !== 0 && $ticket_min === $this->ticket->max()) {
230
+			$this->ticket_price *= $ticket_min;
231
+			$this->ticket_bundle = true;
232
+		}
233
+		$this->ticket_price = apply_filters(
234
+			'FHEE__ticket_selector_chart_template__ticket_price',
235
+			$this->ticket_price,
236
+			$this->ticket
237
+		);
238
+	}
239
+
240
+
241
+	/**
242
+	 * ticketNameTableCell
243
+	 *
244
+	 * @return string
245
+	 * @throws EE_Error
246
+	 * @throws ReflectionException
247
+	 */
248
+	protected function ticketNameTableCell()
249
+	{
250
+		$html = EEH_HTML::td(
251
+			'',
252
+			'',
253
+			'tckt-slctr-tbl-td-name',
254
+			'',
255
+			'headers="details-' . $this->EVT_ID . '"'
256
+		);
257
+		$html .= EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
258
+		$html .= $this->ticket_details->getShowHideLinks();
259
+		if ($this->ticket->required()) {
260
+			$html .= EEH_HTML::p(
261
+				apply_filters(
262
+					'FHEE__ticket_selector_chart_template__ticket_required_message',
263
+					esc_html__('This ticket is required and must be purchased.', 'event_espresso')
264
+				),
265
+				'',
266
+				'ticket-required-pg'
267
+			);
268
+		}
269
+		$html .= EEH_HTML::tdx();
270
+		return $html;
271
+	}
272
+
273
+
274
+	/**
275
+	 * ticketPriceTableCell
276
+	 *
277
+	 * @return string
278
+	 * @throws EE_Error
279
+	 * @throws ReflectionException
280
+	 */
281
+	protected function ticketPriceTableCell()
282
+	{
283
+		$html = '';
284
+		if (apply_filters('FHEE__ticket_selector_chart_template__display_ticket_price_details', true)) {
285
+			$html .= EEH_HTML::td(
286
+				'',
287
+				'',
288
+				'tckt-slctr-tbl-td-price jst-rght',
289
+				'',
290
+				'headers="price-' . $this->EVT_ID . '"'
291
+			);
292
+			$html .= EEH_HTML::span(
293
+				EEH_Template::format_currency($this->ticket_price),
294
+				'',
295
+				'tckt-price--nowrap'
296
+			);
297
+			$html .= $this->ticket->taxable()
298
+				? EEH_HTML::span('*', '', 'taxable-tickets-asterisk grey-text')
299
+				: '';
300
+			$html .= ' ';
301
+			// phpcs:disable WordPress.WP.I18n.NoEmptyStrings
302
+			$html .= EEH_HTML::span(
303
+				$this->ticket_bundle
304
+					? apply_filters(
305
+						'FHEE__ticket_selector_chart_template__per_ticket_bundle_text',
306
+						esc_html__(' / bundle', 'event_espresso')
307
+					)
308
+					: apply_filters(
309
+						'FHEE__ticket_selector_chart_template__per_ticket_text',
310
+						esc_html__('', 'event_espresso')
311
+					),
312
+				'',
313
+				'smaller-text no-bold'
314
+			);
315
+			$html .= ' ';
316
+			$html .= EEH_HTML::tdx();
317
+			$this->cols++;
318
+		}
319
+		return $html;
320
+	}
321
+
322
+
323
+	/**
324
+	 * @return string
325
+	 * @throws EE_Error
326
+	 * @throws ReflectionException
327
+	 */
328
+	protected function onlyOneAttendeeCanRegister(): string
329
+	{
330
+		$TKT   = $this->ticket->ID();
331
+		$label = esc_html__('Select this ticket', 'event_espresso');
332
+		$name  = "tkt-slctr-qty-$this->EVT_ID";
333
+		$class = "ticket-selector-tbl-qty-slct";
334
+		$id    = "$class-$this->EVT_ID-$this->row";
335
+		$checked = $this->total_tickets === 1 ? ' checked' : '';
336
+
337
+		return "
338 338
         <label class='ee-a11y-screen-reader-text' for='$id' >$label</label>
339 339
         <input type='radio'$checked name='$name' id='$id' class='$class' value='$TKT-1' />";
340
-    }
341
-
342
-
343
-    /**
344
-     * @return string
345
-     * @throws EE_Error
346
-     * @throws ReflectionException
347
-     */
348
-    protected function ticketCheckboxSelector(): string
349
-    {
350
-        $TKT = $this->ticket->ID();
351
-        $label = esc_html__('Select this ticket', 'event_espresso');
352
-        $name  = "tkt-slctr-qty-$this->EVT_ID[$TKT]";
353
-        $class = 'ticket-selector-tbl-qty-slct';
354
-        $id    = "$class-$this->EVT_ID-$this->row";
355
-        $title = esc_html__('only one of this ticket can be purchased at a time', 'event_espresso');
356
-
357
-        return "
340
+	}
341
+
342
+
343
+	/**
344
+	 * @return string
345
+	 * @throws EE_Error
346
+	 * @throws ReflectionException
347
+	 */
348
+	protected function ticketCheckboxSelector(): string
349
+	{
350
+		$TKT = $this->ticket->ID();
351
+		$label = esc_html__('Select this ticket', 'event_espresso');
352
+		$name  = "tkt-slctr-qty-$this->EVT_ID[$TKT]";
353
+		$class = 'ticket-selector-tbl-qty-slct';
354
+		$id    = "$class-$this->EVT_ID-$this->row";
355
+		$title = esc_html__('only one of this ticket can be purchased at a time', 'event_espresso');
356
+
357
+		return "
358 358
         <label class='ee-a11y-screen-reader-text' for='$id' >$label</label>
359 359
         <input type='checkbox' name='$name' id='$id' class='$class' value='1' title='$title'/>";
360
-    }
361
-
362
-
363
-    /**
364
-     * @return string
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    protected function ticketQuantitySelector(): string
369
-    {
370
-        $TKT = $this->ticket->ID();
371
-        $label = esc_html__('Quantity', 'event_espresso');
372
-        $name  = "tkt-slctr-qty-$this->EVT_ID[$TKT]";
373
-        $class = 'ticket-selector-tbl-qty-slct';
374
-        $id = "$class-{$this->EVT_ID}-{$this->row}";
375
-
376
-        $html = "<label class='ee-a11y-screen-reader-text' for='$id' >$label</label>";
377
-        $html .= "<select name='$name' id='$id' class='$class'>";
378
-        // this ensures that non-required tickets with non-zero MIN QTYs don't HAVE to be purchased
379
-        if ($this->min !== 0 && ! $this->ticket->required()) {
380
-            $html .= "<option value='0'>&nbsp;0&nbsp;</option>";
381
-        }
382
-        // offer ticket quantities from the min to the max
383
-        for ($i = $this->min; $i <= $this->max; $i++) {
384
-            $html .= "<option value='$i'>&nbsp;$i&nbsp;</option>";
385
-        }
386
-        $html .= "</select>";
387
-        return $html;
388
-    }
389
-
390
-
391
-    /**
392
-     * @return string
393
-     * @throws EE_Error
394
-     * @throws ReflectionException
395
-     */
396
-    protected function ticketQtyAndIdHiddenInputs(): string
397
-    {
398
-        $html = '';
399
-        $EVT = $this->EVT_ID;
400
-        $TKT = $this->ticket->ID();
401
-        // depending on group reg we need to change the format for qty
402
-        if ($this->hidden_input_qty) {
403
-            $html .= "<input type='hidden' name='tkt-slctr-qty-{$EVT}[]' value='0' />";
404
-        }
405
-        $html .= "<input type='hidden' name='tkt-slctr-ticket-id-{$EVT}[]' value='{$TKT}' />";
406
-        return $html;
407
-    }
360
+	}
361
+
362
+
363
+	/**
364
+	 * @return string
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	protected function ticketQuantitySelector(): string
369
+	{
370
+		$TKT = $this->ticket->ID();
371
+		$label = esc_html__('Quantity', 'event_espresso');
372
+		$name  = "tkt-slctr-qty-$this->EVT_ID[$TKT]";
373
+		$class = 'ticket-selector-tbl-qty-slct';
374
+		$id = "$class-{$this->EVT_ID}-{$this->row}";
375
+
376
+		$html = "<label class='ee-a11y-screen-reader-text' for='$id' >$label</label>";
377
+		$html .= "<select name='$name' id='$id' class='$class'>";
378
+		// this ensures that non-required tickets with non-zero MIN QTYs don't HAVE to be purchased
379
+		if ($this->min !== 0 && ! $this->ticket->required()) {
380
+			$html .= "<option value='0'>&nbsp;0&nbsp;</option>";
381
+		}
382
+		// offer ticket quantities from the min to the max
383
+		for ($i = $this->min; $i <= $this->max; $i++) {
384
+			$html .= "<option value='$i'>&nbsp;$i&nbsp;</option>";
385
+		}
386
+		$html .= "</select>";
387
+		return $html;
388
+	}
389
+
390
+
391
+	/**
392
+	 * @return string
393
+	 * @throws EE_Error
394
+	 * @throws ReflectionException
395
+	 */
396
+	protected function ticketQtyAndIdHiddenInputs(): string
397
+	{
398
+		$html = '';
399
+		$EVT = $this->EVT_ID;
400
+		$TKT = $this->ticket->ID();
401
+		// depending on group reg we need to change the format for qty
402
+		if ($this->hidden_input_qty) {
403
+			$html .= "<input type='hidden' name='tkt-slctr-qty-{$EVT}[]' value='0' />";
404
+		}
405
+		$html .= "<input type='hidden' name='tkt-slctr-ticket-id-{$EVT}[]' value='{$TKT}' />";
406
+		return $html;
407
+	}
408 408
 }
Please login to merge, or discard this patch.
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 2 patches
Indentation   +1074 added lines, -1074 removed lines patch added patch discarded remove patch
@@ -19,1080 +19,1080 @@
 block discarded – undo
19 19
  */
20 20
 class EED_Ticket_Sales_Monitor extends EED_Module
21 21
 {
22
-    const debug = false;    // true false
23
-
24
-    private static $nl = '';
25
-
26
-    /**
27
-     * an array for tracking names of tickets that have sold out
28
-     *
29
-     * @var array $sold_out_tickets
30
-     */
31
-    protected $sold_out_tickets = array();
32
-
33
-    /**
34
-     * an array for tracking names of tickets that have had their quantities reduced
35
-     *
36
-     * @var array $decremented_tickets
37
-     */
38
-    protected $decremented_tickets = array();
39
-
40
-
41
-    /**
42
-     * set_hooks - for hooking into EE Core, other modules, etc
43
-     *
44
-     * @return    void
45
-     */
46
-    public static function set_hooks()
47
-    {
48
-        self::$nl = defined('EE_TESTS_DIR') ? "\n" : '<br />';
49
-        // release tickets for expired carts
50
-        add_action(
51
-            'EED_Ticket_Selector__process_ticket_selections__before',
52
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
53
-            1
54
-        );
55
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
56
-        add_filter(
57
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
58
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
59
-            20,
60
-            3
61
-        );
62
-        // add notices for sold out tickets
63
-        add_action(
64
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
65
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
66
-            10
67
-        );
68
-
69
-        // handle tickets deleted from cart
70
-        add_action(
71
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
72
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
73
-            10,
74
-            2
75
-        );
76
-        // handle emptied carts
77
-        add_action(
78
-            'AHEE__EE_Session__reset_cart__before_reset',
79
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
80
-            10,
81
-            1
82
-        );
83
-        add_action(
84
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
85
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
86
-            10,
87
-            1
88
-        );
89
-        // handle cancelled registrations
90
-        add_action(
91
-            'AHEE__EE_Session__reset_checkout__before_reset',
92
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
93
-            10,
94
-            1
95
-        );
96
-        // cron tasks
97
-        add_action(
98
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
99
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
100
-            10,
101
-            1
102
-        );
103
-        add_action(
104
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
105
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
106
-            10,
107
-            1
108
-        );
109
-        add_action(
110
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
111
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
112
-            10,
113
-            1
114
-        );
115
-    }
116
-
117
-
118
-    /**
119
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
120
-     *
121
-     * @return void
122
-     */
123
-    public static function set_hooks_admin()
124
-    {
125
-        EED_Ticket_Sales_Monitor::set_hooks();
126
-    }
127
-
128
-
129
-    /**
130
-     * @return EED_Ticket_Sales_Monitor|EED_Module
131
-     * @throws EE_Error
132
-     * @throws ReflectionException
133
-     */
134
-    public static function instance()
135
-    {
136
-        return parent::get_instance(__CLASS__);
137
-    }
138
-
139
-
140
-    /**
141
-     * @param WP_Query $WP
142
-     * @return    void
143
-     */
144
-    public function run($WP)
145
-    {
146
-    }
147
-
148
-
149
-
150
-    /********************************** PRE_TICKET_SALES  **********************************/
151
-
152
-
153
-    /**
154
-     * Retrieves grand totals from the line items that have no TXN ID
155
-     * and timestamps less than the current time minus the session lifespan.
156
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
157
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
158
-     *
159
-     * @return void
160
-     * @throws DomainException
161
-     * @throws EE_Error
162
-     * @throws InvalidArgumentException
163
-     * @throws InvalidDataTypeException
164
-     * @throws InvalidInterfaceException
165
-     * @throws UnexpectedEntityException
166
-     * @throws ReflectionException
167
-     */
168
-    public static function release_tickets_for_expired_carts()
169
-    {
170
-        // self::debug hardcoded to false
171
-        if (self::debug) {
172
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
173
-        }
174
-        do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
175
-        $expired_ticket_IDs = array();
176
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
177
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
178
-            'EventEspresso\core\domain\values\session\SessionLifespan'
179
-        );
180
-        $timestamp = $session_lifespan->expiration();
181
-        $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
182
-        if (self::debug) {
183
-            echo self::$nl . ' . time(): ' . time();
184
-            echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
185
-            echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
186
-            echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
187
-            echo self::$nl . ' . timestamp: ' . $timestamp;
188
-            echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
189
-        }
190
-        if (! empty($expired_ticket_line_items)) {
191
-            foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
192
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
193
-                    continue;
194
-                }
195
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
196
-                if (self::debug) {
197
-                    echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
198
-                    echo self::$nl . ' . $expired_ticket_line_item->timestamp(): '
199
-                         . date(
200
-                             'Y-m-d h:i a',
201
-                             $expired_ticket_line_item->timestamp(true)
202
-                         );
203
-                }
204
-            }
205
-            if (! empty($expired_ticket_IDs)) {
206
-                EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
207
-                    EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
208
-                    array(),
209
-                    __FUNCTION__
210
-                );
211
-                // now  let's get rid of expired line items so that they can't interfere with tracking
212
-                EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
213
-            }
214
-        }
215
-        do_action(
216
-            'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
217
-            $expired_ticket_IDs,
218
-            $expired_ticket_line_items
219
-        );
220
-    }
221
-
222
-
223
-
224
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
225
-
226
-
227
-    /**
228
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
229
-     *
230
-     * @param int       $qty
231
-     * @param EE_Ticket $ticket
232
-     * @return int
233
-     * @throws UnexpectedEntityException
234
-     * @throws EE_Error
235
-     * @throws ReflectionException
236
-     */
237
-    public static function validate_ticket_sale(int $qty, EE_Ticket $ticket): int
238
-    {
239
-        $qty = absint($qty);
240
-        if ($qty > 0) {
241
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
242
-        }
243
-        // self::debug hardcoded to false
244
-        if (self::debug) {
245
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
246
-            echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
247
-        }
248
-        return $qty;
249
-    }
250
-
251
-
252
-    /**
253
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
254
-     *
255
-     * @param EE_Ticket|null $ticket
256
-     * @param int       $qty
257
-     * @return int
258
-     * @throws UnexpectedEntityException
259
-     * @throws EE_Error
260
-     * @throws ReflectionException
261
-     */
262
-    protected function _validate_ticket_sale(?EE_Ticket $ticket, int $qty = 1): int
263
-    {
264
-        // self::debug hardcoded to false
265
-        if (self::debug) {
266
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
267
-        }
268
-        if (! $ticket instanceof EE_Ticket) {
269
-            return 0;
270
-        }
271
-        if (self::debug) {
272
-            echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
273
-            echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
274
-        }
275
-        $ticket->refresh_from_db();
276
-        // first let's determine the ticket availability based on sales
277
-        $available = $ticket->qty('saleable');
278
-        if (self::debug) {
279
-            echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
280
-            echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
281
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
282
-            echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
283
-            echo self::$nl . ' . . . available: ' . $available;
284
-        }
285
-        if ($available < 1) {
286
-            $this->_ticket_sold_out($ticket);
287
-            return 0;
288
-        }
289
-        if (self::debug) {
290
-            echo self::$nl . ' . . . qty: ' . $qty;
291
-        }
292
-        if ($available < $qty) {
293
-            $qty = $available;
294
-            if (self::debug) {
295
-                echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
296
-            }
297
-            $this->_ticket_quantity_decremented($ticket);
298
-        }
299
-        if ($this->_reserve_ticket($ticket, $qty)) {
300
-            return $qty;
301
-        }
302
-        return 0;
303
-    }
304
-
305
-
306
-    /**
307
-     * increments ticket reserved based on quantity passed
308
-     *
309
-     * @param EE_Ticket $ticket
310
-     * @param int       $quantity
311
-     * @return bool indicating success or failure
312
-     * @throws EE_Error
313
-     * @throws ReflectionException
314
-     */
315
-    protected function _reserve_ticket(EE_Ticket $ticket, int $quantity = 1): bool
316
-    {
317
-        // self::debug hardcoded to false
318
-        if (self::debug) {
319
-            echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
320
-        }
321
-        return $ticket->increaseReserved($quantity, 'TicketSalesMonitor:' . __LINE__);
322
-    }
323
-
324
-
325
-    /**
326
-     * @param EE_Ticket $ticket
327
-     * @param int       $quantity
328
-     * @return bool
329
-     * @throws EE_Error
330
-     * @throws ReflectionException
331
-     */
332
-    protected function _release_reserved_ticket(EE_Ticket $ticket, int $quantity = 1): bool
333
-    {
334
-        // self::debug hardcoded to false
335
-        if (self::debug) {
336
-            echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
337
-            echo self::$nl . ' . . . ticket->reserved before: ' . $ticket->reserved();
338
-        }
339
-        $ticket->decreaseReserved($quantity, true, 'TicketSalesMonitor:' . __LINE__);
340
-        if (self::debug) {
341
-            echo self::$nl . ' . . . ticket->reserved after: ' . $ticket->reserved();
342
-        }
343
-        return (bool) $ticket->save();
344
-    }
345
-
346
-
347
-    /**
348
-     * removes quantities within the ticket selector based on zero ticket availability
349
-     *
350
-     * @param EE_Ticket $ticket
351
-     * @return    void
352
-     * @throws UnexpectedEntityException
353
-     * @throws EE_Error
354
-     * @throws ReflectionException
355
-     */
356
-    protected function _ticket_sold_out(EE_Ticket $ticket)
357
-    {
358
-        // self::debug hardcoded to false
359
-        if (self::debug) {
360
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
361
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
362
-        }
363
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
364
-    }
365
-
366
-
367
-    /**
368
-     * adjusts quantities within the ticket selector based on decreased ticket availability
369
-     *
370
-     * @param EE_Ticket $ticket
371
-     * @return void
372
-     * @throws UnexpectedEntityException
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     */
376
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
377
-    {
378
-        // self::debug hardcoded to false
379
-        if (self::debug) {
380
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
381
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
382
-        }
383
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
384
-    }
385
-
386
-
387
-    /**
388
-     * builds string out of ticket and event name
389
-     *
390
-     * @param EE_Ticket $ticket
391
-     * @return string
392
-     * @throws UnexpectedEntityException
393
-     * @throws EE_Error
394
-     * @throws ReflectionException
395
-     */
396
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket): string
397
-    {
398
-        $event = $ticket->get_related_event();
399
-        if ($event instanceof EE_Event) {
400
-            $ticket_name = sprintf(
401
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
402
-                $ticket->name(),
403
-                $event->name()
404
-            );
405
-        } else {
406
-            $ticket_name = $ticket->name();
407
-        }
408
-        return $ticket_name;
409
-    }
410
-
411
-
412
-
413
-    /********************************** EVENT CART  **********************************/
414
-
415
-
416
-    /**
417
-     * releases or reserves ticket(s) based on quantity passed
418
-     *
419
-     * @param EE_Line_Item $line_item
420
-     * @param int          $quantity
421
-     * @return void
422
-     * @throws EE_Error
423
-     * @throws InvalidArgumentException
424
-     * @throws InvalidDataTypeException
425
-     * @throws InvalidInterfaceException
426
-     * @throws ReflectionException
427
-     */
428
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, int $quantity = 1)
429
-    {
430
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
431
-        if ($ticket instanceof EE_Ticket) {
432
-            if (self::debug) {
433
-                $ticket->add_extra_meta(
434
-                    EE_Ticket::META_KEY_TICKET_RESERVATIONS,
435
-                    __LINE__ . ') ' . __METHOD__ . '()'
436
-                );
437
-            }
438
-            if ($quantity > 0) {
439
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
440
-            } else {
441
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
442
-            }
443
-        }
444
-    }
445
-
446
-
447
-    /**
448
-     * releases reserved ticket(s) based on quantity passed
449
-     *
450
-     * @param EE_Ticket $ticket
451
-     * @param int       $quantity
452
-     * @return void
453
-     * @throws EE_Error
454
-     * @throws ReflectionException
455
-     */
456
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, int $quantity = 1)
457
-    {
458
-        if (self::debug) {
459
-            $ticket->add_extra_meta(
460
-                EE_Ticket::META_KEY_TICKET_RESERVATIONS,
461
-                __LINE__ . ') ' . __METHOD__ . '()'
462
-            );
463
-        }
464
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
465
-    }
466
-
467
-
468
-
469
-    /********************************** POST_NOTICES  **********************************/
470
-
471
-
472
-    /**
473
-     * @return void
474
-     * @throws EE_Error
475
-     * @throws ReflectionException
476
-     */
477
-    public static function post_notices()
478
-    {
479
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
480
-    }
481
-
482
-
483
-    /**
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws ReflectionException
488
-     * @throws InvalidDataTypeException
489
-     * @throws InvalidInterfaceException
490
-     */
491
-    protected function _post_notices()
492
-    {
493
-        // self::debug hardcoded to false
494
-        if (self::debug) {
495
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
496
-        }
497
-        $refresh_msg = '';
498
-        $none_added_msg = '';
499
-        if (defined('DOING_AJAX') && DOING_AJAX) {
500
-            $refresh_msg = esc_html__(
501
-                'Please refresh the page to view updated ticket quantities.',
502
-                'event_espresso'
503
-            );
504
-            $none_added_msg = esc_html__('No tickets were added for the event.', 'event_espresso');
505
-        }
506
-        if (! empty($this->sold_out_tickets)) {
507
-            EE_Error::add_attention(
508
-                sprintf(
509
-                    apply_filters(
510
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
511
-                        esc_html__(
512
-                            'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
513
-                            'event_espresso'
514
-                        )
515
-                    ),
516
-                    '<br />',
517
-                    implode('<br />', $this->sold_out_tickets),
518
-                    $none_added_msg,
519
-                    $refresh_msg
520
-                )
521
-            );
522
-            // alter code flow in the Ticket Selector for better UX
523
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
524
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
525
-            $this->sold_out_tickets = array();
526
-            // and reset the cart
527
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
528
-        }
529
-        if (! empty($this->decremented_tickets)) {
530
-            EE_Error::add_attention(
531
-                sprintf(
532
-                    apply_filters(
533
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
534
-                        esc_html__(
535
-                            'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
536
-                            'event_espresso'
537
-                        )
538
-                    ),
539
-                    '<br />',
540
-                    implode('<br />', $this->decremented_tickets),
541
-                    $none_added_msg,
542
-                    $refresh_msg
543
-                )
544
-            );
545
-            $this->decremented_tickets = array();
546
-        }
547
-    }
548
-
549
-
550
-
551
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
552
-
553
-
554
-    /**
555
-     * releases reserved tickets for all registrations of an EE_Transaction
556
-     * by default, will NOT release tickets for finalized transactions
557
-     *
558
-     * @param EE_Transaction $transaction
559
-     * @return int
560
-     * @throws EE_Error
561
-     * @throws ReflectionException
562
-     */
563
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction): int
564
-    {
565
-        // self::debug hardcoded to false
566
-        if (self::debug) {
567
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
568
-            echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
569
-            echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
570
-        }
571
-        // check if 'finalize_registration' step has been completed...
572
-        $finalized = $transaction->reg_step_completed('finalize_registration');
573
-        if (self::debug) {
574
-            // DEBUG LOG
575
-            EEH_Debug_Tools::log(
576
-                __CLASS__,
577
-                __FUNCTION__,
578
-                __LINE__,
579
-                array('finalized' => $finalized),
580
-                false,
581
-                'EE_Transaction: ' . $transaction->ID()
582
-            );
583
-        }
584
-        // how many tickets were released
585
-        $count = 0;
586
-        if (self::debug) {
587
-            echo self::$nl . ' . . . TXN finalized: ' . $finalized;
588
-        }
589
-        $release_tickets_with_TXN_status = array(
590
-            EEM_Transaction::failed_status_code,
591
-            EEM_Transaction::abandoned_status_code,
592
-            EEM_Transaction::incomplete_status_code,
593
-        );
594
-        $events = array();
595
-        // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
596
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
597
-            // cancel any reserved tickets for registrations that were not approved
598
-            $registrations = $transaction->registrations();
599
-            if (self::debug) {
600
-                echo self::$nl . ' . . . # registrations: ' . count($registrations);
601
-                $reg = reset($registrations);
602
-                $ticket = $reg->ticket();
603
-                if ($ticket instanceof EE_Ticket) {
604
-                    $ticket->add_extra_meta(
605
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
606
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
607
-                    );
608
-                }
609
-            }
610
-            if (! empty($registrations)) {
611
-                foreach ($registrations as $registration) {
612
-                    if (
613
-                        $registration instanceof EE_Registration
614
-                        && $this->_release_reserved_ticket_for_registration($registration, $transaction)
615
-                    ) {
616
-                        $count++;
617
-                        $events[ $registration->event_ID() ] = $registration->event();
618
-                    }
619
-                }
620
-            }
621
-        }
622
-        if ($events !== array()) {
623
-            foreach ($events as $event) {
624
-                /** @var EE_Event $event */
625
-                $event->perform_sold_out_status_check();
626
-            }
627
-        }
628
-        return $count;
629
-    }
630
-
631
-
632
-    /**
633
-     * releases reserved tickets for an EE_Registration
634
-     * by default, will NOT release tickets for APPROVED registrations
635
-     *
636
-     * @param EE_Registration $registration
637
-     * @param EE_Transaction  $transaction
638
-     * @return int
639
-     * @throws EE_Error
640
-     * @throws ReflectionException
641
-     */
642
-    protected function _release_reserved_ticket_for_registration(
643
-        EE_Registration $registration,
644
-        EE_Transaction $transaction
645
-    ): int {
646
-        $STS_ID = $transaction->status_ID();
647
-        // self::debug hardcoded to false
648
-        if (self::debug) {
649
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
650
-            echo self::$nl . ' . . registration->ID: ' . $registration->ID();
651
-            echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
652
-            echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
653
-        }
654
-        if (
22
+	const debug = false;    // true false
23
+
24
+	private static $nl = '';
25
+
26
+	/**
27
+	 * an array for tracking names of tickets that have sold out
28
+	 *
29
+	 * @var array $sold_out_tickets
30
+	 */
31
+	protected $sold_out_tickets = array();
32
+
33
+	/**
34
+	 * an array for tracking names of tickets that have had their quantities reduced
35
+	 *
36
+	 * @var array $decremented_tickets
37
+	 */
38
+	protected $decremented_tickets = array();
39
+
40
+
41
+	/**
42
+	 * set_hooks - for hooking into EE Core, other modules, etc
43
+	 *
44
+	 * @return    void
45
+	 */
46
+	public static function set_hooks()
47
+	{
48
+		self::$nl = defined('EE_TESTS_DIR') ? "\n" : '<br />';
49
+		// release tickets for expired carts
50
+		add_action(
51
+			'EED_Ticket_Selector__process_ticket_selections__before',
52
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
53
+			1
54
+		);
55
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
56
+		add_filter(
57
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
58
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
59
+			20,
60
+			3
61
+		);
62
+		// add notices for sold out tickets
63
+		add_action(
64
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
65
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
66
+			10
67
+		);
68
+
69
+		// handle tickets deleted from cart
70
+		add_action(
71
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
72
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
73
+			10,
74
+			2
75
+		);
76
+		// handle emptied carts
77
+		add_action(
78
+			'AHEE__EE_Session__reset_cart__before_reset',
79
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
80
+			10,
81
+			1
82
+		);
83
+		add_action(
84
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
85
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
86
+			10,
87
+			1
88
+		);
89
+		// handle cancelled registrations
90
+		add_action(
91
+			'AHEE__EE_Session__reset_checkout__before_reset',
92
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
93
+			10,
94
+			1
95
+		);
96
+		// cron tasks
97
+		add_action(
98
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
99
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
100
+			10,
101
+			1
102
+		);
103
+		add_action(
104
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
105
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
106
+			10,
107
+			1
108
+		);
109
+		add_action(
110
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
111
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
112
+			10,
113
+			1
114
+		);
115
+	}
116
+
117
+
118
+	/**
119
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
120
+	 *
121
+	 * @return void
122
+	 */
123
+	public static function set_hooks_admin()
124
+	{
125
+		EED_Ticket_Sales_Monitor::set_hooks();
126
+	}
127
+
128
+
129
+	/**
130
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
131
+	 * @throws EE_Error
132
+	 * @throws ReflectionException
133
+	 */
134
+	public static function instance()
135
+	{
136
+		return parent::get_instance(__CLASS__);
137
+	}
138
+
139
+
140
+	/**
141
+	 * @param WP_Query $WP
142
+	 * @return    void
143
+	 */
144
+	public function run($WP)
145
+	{
146
+	}
147
+
148
+
149
+
150
+	/********************************** PRE_TICKET_SALES  **********************************/
151
+
152
+
153
+	/**
154
+	 * Retrieves grand totals from the line items that have no TXN ID
155
+	 * and timestamps less than the current time minus the session lifespan.
156
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
157
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
158
+	 *
159
+	 * @return void
160
+	 * @throws DomainException
161
+	 * @throws EE_Error
162
+	 * @throws InvalidArgumentException
163
+	 * @throws InvalidDataTypeException
164
+	 * @throws InvalidInterfaceException
165
+	 * @throws UnexpectedEntityException
166
+	 * @throws ReflectionException
167
+	 */
168
+	public static function release_tickets_for_expired_carts()
169
+	{
170
+		// self::debug hardcoded to false
171
+		if (self::debug) {
172
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
173
+		}
174
+		do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
175
+		$expired_ticket_IDs = array();
176
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
177
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
178
+			'EventEspresso\core\domain\values\session\SessionLifespan'
179
+		);
180
+		$timestamp = $session_lifespan->expiration();
181
+		$expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
182
+		if (self::debug) {
183
+			echo self::$nl . ' . time(): ' . time();
184
+			echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
185
+			echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
186
+			echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
187
+			echo self::$nl . ' . timestamp: ' . $timestamp;
188
+			echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
189
+		}
190
+		if (! empty($expired_ticket_line_items)) {
191
+			foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
192
+				if (! $expired_ticket_line_item instanceof EE_Line_Item) {
193
+					continue;
194
+				}
195
+				$expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
196
+				if (self::debug) {
197
+					echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
198
+					echo self::$nl . ' . $expired_ticket_line_item->timestamp(): '
199
+						 . date(
200
+							 'Y-m-d h:i a',
201
+							 $expired_ticket_line_item->timestamp(true)
202
+						 );
203
+				}
204
+			}
205
+			if (! empty($expired_ticket_IDs)) {
206
+				EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
207
+					EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
208
+					array(),
209
+					__FUNCTION__
210
+				);
211
+				// now  let's get rid of expired line items so that they can't interfere with tracking
212
+				EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
213
+			}
214
+		}
215
+		do_action(
216
+			'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
217
+			$expired_ticket_IDs,
218
+			$expired_ticket_line_items
219
+		);
220
+	}
221
+
222
+
223
+
224
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
225
+
226
+
227
+	/**
228
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
229
+	 *
230
+	 * @param int       $qty
231
+	 * @param EE_Ticket $ticket
232
+	 * @return int
233
+	 * @throws UnexpectedEntityException
234
+	 * @throws EE_Error
235
+	 * @throws ReflectionException
236
+	 */
237
+	public static function validate_ticket_sale(int $qty, EE_Ticket $ticket): int
238
+	{
239
+		$qty = absint($qty);
240
+		if ($qty > 0) {
241
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
242
+		}
243
+		// self::debug hardcoded to false
244
+		if (self::debug) {
245
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
246
+			echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
247
+		}
248
+		return $qty;
249
+	}
250
+
251
+
252
+	/**
253
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
254
+	 *
255
+	 * @param EE_Ticket|null $ticket
256
+	 * @param int       $qty
257
+	 * @return int
258
+	 * @throws UnexpectedEntityException
259
+	 * @throws EE_Error
260
+	 * @throws ReflectionException
261
+	 */
262
+	protected function _validate_ticket_sale(?EE_Ticket $ticket, int $qty = 1): int
263
+	{
264
+		// self::debug hardcoded to false
265
+		if (self::debug) {
266
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
267
+		}
268
+		if (! $ticket instanceof EE_Ticket) {
269
+			return 0;
270
+		}
271
+		if (self::debug) {
272
+			echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
273
+			echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
274
+		}
275
+		$ticket->refresh_from_db();
276
+		// first let's determine the ticket availability based on sales
277
+		$available = $ticket->qty('saleable');
278
+		if (self::debug) {
279
+			echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
280
+			echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
281
+			echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
282
+			echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
283
+			echo self::$nl . ' . . . available: ' . $available;
284
+		}
285
+		if ($available < 1) {
286
+			$this->_ticket_sold_out($ticket);
287
+			return 0;
288
+		}
289
+		if (self::debug) {
290
+			echo self::$nl . ' . . . qty: ' . $qty;
291
+		}
292
+		if ($available < $qty) {
293
+			$qty = $available;
294
+			if (self::debug) {
295
+				echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
296
+			}
297
+			$this->_ticket_quantity_decremented($ticket);
298
+		}
299
+		if ($this->_reserve_ticket($ticket, $qty)) {
300
+			return $qty;
301
+		}
302
+		return 0;
303
+	}
304
+
305
+
306
+	/**
307
+	 * increments ticket reserved based on quantity passed
308
+	 *
309
+	 * @param EE_Ticket $ticket
310
+	 * @param int       $quantity
311
+	 * @return bool indicating success or failure
312
+	 * @throws EE_Error
313
+	 * @throws ReflectionException
314
+	 */
315
+	protected function _reserve_ticket(EE_Ticket $ticket, int $quantity = 1): bool
316
+	{
317
+		// self::debug hardcoded to false
318
+		if (self::debug) {
319
+			echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
320
+		}
321
+		return $ticket->increaseReserved($quantity, 'TicketSalesMonitor:' . __LINE__);
322
+	}
323
+
324
+
325
+	/**
326
+	 * @param EE_Ticket $ticket
327
+	 * @param int       $quantity
328
+	 * @return bool
329
+	 * @throws EE_Error
330
+	 * @throws ReflectionException
331
+	 */
332
+	protected function _release_reserved_ticket(EE_Ticket $ticket, int $quantity = 1): bool
333
+	{
334
+		// self::debug hardcoded to false
335
+		if (self::debug) {
336
+			echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
337
+			echo self::$nl . ' . . . ticket->reserved before: ' . $ticket->reserved();
338
+		}
339
+		$ticket->decreaseReserved($quantity, true, 'TicketSalesMonitor:' . __LINE__);
340
+		if (self::debug) {
341
+			echo self::$nl . ' . . . ticket->reserved after: ' . $ticket->reserved();
342
+		}
343
+		return (bool) $ticket->save();
344
+	}
345
+
346
+
347
+	/**
348
+	 * removes quantities within the ticket selector based on zero ticket availability
349
+	 *
350
+	 * @param EE_Ticket $ticket
351
+	 * @return    void
352
+	 * @throws UnexpectedEntityException
353
+	 * @throws EE_Error
354
+	 * @throws ReflectionException
355
+	 */
356
+	protected function _ticket_sold_out(EE_Ticket $ticket)
357
+	{
358
+		// self::debug hardcoded to false
359
+		if (self::debug) {
360
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
361
+			echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
362
+		}
363
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
364
+	}
365
+
366
+
367
+	/**
368
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
369
+	 *
370
+	 * @param EE_Ticket $ticket
371
+	 * @return void
372
+	 * @throws UnexpectedEntityException
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 */
376
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
377
+	{
378
+		// self::debug hardcoded to false
379
+		if (self::debug) {
380
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
381
+			echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
382
+		}
383
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
384
+	}
385
+
386
+
387
+	/**
388
+	 * builds string out of ticket and event name
389
+	 *
390
+	 * @param EE_Ticket $ticket
391
+	 * @return string
392
+	 * @throws UnexpectedEntityException
393
+	 * @throws EE_Error
394
+	 * @throws ReflectionException
395
+	 */
396
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket): string
397
+	{
398
+		$event = $ticket->get_related_event();
399
+		if ($event instanceof EE_Event) {
400
+			$ticket_name = sprintf(
401
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
402
+				$ticket->name(),
403
+				$event->name()
404
+			);
405
+		} else {
406
+			$ticket_name = $ticket->name();
407
+		}
408
+		return $ticket_name;
409
+	}
410
+
411
+
412
+
413
+	/********************************** EVENT CART  **********************************/
414
+
415
+
416
+	/**
417
+	 * releases or reserves ticket(s) based on quantity passed
418
+	 *
419
+	 * @param EE_Line_Item $line_item
420
+	 * @param int          $quantity
421
+	 * @return void
422
+	 * @throws EE_Error
423
+	 * @throws InvalidArgumentException
424
+	 * @throws InvalidDataTypeException
425
+	 * @throws InvalidInterfaceException
426
+	 * @throws ReflectionException
427
+	 */
428
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, int $quantity = 1)
429
+	{
430
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
431
+		if ($ticket instanceof EE_Ticket) {
432
+			if (self::debug) {
433
+				$ticket->add_extra_meta(
434
+					EE_Ticket::META_KEY_TICKET_RESERVATIONS,
435
+					__LINE__ . ') ' . __METHOD__ . '()'
436
+				);
437
+			}
438
+			if ($quantity > 0) {
439
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
440
+			} else {
441
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
442
+			}
443
+		}
444
+	}
445
+
446
+
447
+	/**
448
+	 * releases reserved ticket(s) based on quantity passed
449
+	 *
450
+	 * @param EE_Ticket $ticket
451
+	 * @param int       $quantity
452
+	 * @return void
453
+	 * @throws EE_Error
454
+	 * @throws ReflectionException
455
+	 */
456
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, int $quantity = 1)
457
+	{
458
+		if (self::debug) {
459
+			$ticket->add_extra_meta(
460
+				EE_Ticket::META_KEY_TICKET_RESERVATIONS,
461
+				__LINE__ . ') ' . __METHOD__ . '()'
462
+			);
463
+		}
464
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
465
+	}
466
+
467
+
468
+
469
+	/********************************** POST_NOTICES  **********************************/
470
+
471
+
472
+	/**
473
+	 * @return void
474
+	 * @throws EE_Error
475
+	 * @throws ReflectionException
476
+	 */
477
+	public static function post_notices()
478
+	{
479
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
480
+	}
481
+
482
+
483
+	/**
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws ReflectionException
488
+	 * @throws InvalidDataTypeException
489
+	 * @throws InvalidInterfaceException
490
+	 */
491
+	protected function _post_notices()
492
+	{
493
+		// self::debug hardcoded to false
494
+		if (self::debug) {
495
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
496
+		}
497
+		$refresh_msg = '';
498
+		$none_added_msg = '';
499
+		if (defined('DOING_AJAX') && DOING_AJAX) {
500
+			$refresh_msg = esc_html__(
501
+				'Please refresh the page to view updated ticket quantities.',
502
+				'event_espresso'
503
+			);
504
+			$none_added_msg = esc_html__('No tickets were added for the event.', 'event_espresso');
505
+		}
506
+		if (! empty($this->sold_out_tickets)) {
507
+			EE_Error::add_attention(
508
+				sprintf(
509
+					apply_filters(
510
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
511
+						esc_html__(
512
+							'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
513
+							'event_espresso'
514
+						)
515
+					),
516
+					'<br />',
517
+					implode('<br />', $this->sold_out_tickets),
518
+					$none_added_msg,
519
+					$refresh_msg
520
+				)
521
+			);
522
+			// alter code flow in the Ticket Selector for better UX
523
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
524
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
525
+			$this->sold_out_tickets = array();
526
+			// and reset the cart
527
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
528
+		}
529
+		if (! empty($this->decremented_tickets)) {
530
+			EE_Error::add_attention(
531
+				sprintf(
532
+					apply_filters(
533
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
534
+						esc_html__(
535
+							'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
536
+							'event_espresso'
537
+						)
538
+					),
539
+					'<br />',
540
+					implode('<br />', $this->decremented_tickets),
541
+					$none_added_msg,
542
+					$refresh_msg
543
+				)
544
+			);
545
+			$this->decremented_tickets = array();
546
+		}
547
+	}
548
+
549
+
550
+
551
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
552
+
553
+
554
+	/**
555
+	 * releases reserved tickets for all registrations of an EE_Transaction
556
+	 * by default, will NOT release tickets for finalized transactions
557
+	 *
558
+	 * @param EE_Transaction $transaction
559
+	 * @return int
560
+	 * @throws EE_Error
561
+	 * @throws ReflectionException
562
+	 */
563
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction): int
564
+	{
565
+		// self::debug hardcoded to false
566
+		if (self::debug) {
567
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
568
+			echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
569
+			echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
570
+		}
571
+		// check if 'finalize_registration' step has been completed...
572
+		$finalized = $transaction->reg_step_completed('finalize_registration');
573
+		if (self::debug) {
574
+			// DEBUG LOG
575
+			EEH_Debug_Tools::log(
576
+				__CLASS__,
577
+				__FUNCTION__,
578
+				__LINE__,
579
+				array('finalized' => $finalized),
580
+				false,
581
+				'EE_Transaction: ' . $transaction->ID()
582
+			);
583
+		}
584
+		// how many tickets were released
585
+		$count = 0;
586
+		if (self::debug) {
587
+			echo self::$nl . ' . . . TXN finalized: ' . $finalized;
588
+		}
589
+		$release_tickets_with_TXN_status = array(
590
+			EEM_Transaction::failed_status_code,
591
+			EEM_Transaction::abandoned_status_code,
592
+			EEM_Transaction::incomplete_status_code,
593
+		);
594
+		$events = array();
595
+		// if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
596
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
597
+			// cancel any reserved tickets for registrations that were not approved
598
+			$registrations = $transaction->registrations();
599
+			if (self::debug) {
600
+				echo self::$nl . ' . . . # registrations: ' . count($registrations);
601
+				$reg = reset($registrations);
602
+				$ticket = $reg->ticket();
603
+				if ($ticket instanceof EE_Ticket) {
604
+					$ticket->add_extra_meta(
605
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
606
+						__LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
607
+					);
608
+				}
609
+			}
610
+			if (! empty($registrations)) {
611
+				foreach ($registrations as $registration) {
612
+					if (
613
+						$registration instanceof EE_Registration
614
+						&& $this->_release_reserved_ticket_for_registration($registration, $transaction)
615
+					) {
616
+						$count++;
617
+						$events[ $registration->event_ID() ] = $registration->event();
618
+					}
619
+				}
620
+			}
621
+		}
622
+		if ($events !== array()) {
623
+			foreach ($events as $event) {
624
+				/** @var EE_Event $event */
625
+				$event->perform_sold_out_status_check();
626
+			}
627
+		}
628
+		return $count;
629
+	}
630
+
631
+
632
+	/**
633
+	 * releases reserved tickets for an EE_Registration
634
+	 * by default, will NOT release tickets for APPROVED registrations
635
+	 *
636
+	 * @param EE_Registration $registration
637
+	 * @param EE_Transaction  $transaction
638
+	 * @return int
639
+	 * @throws EE_Error
640
+	 * @throws ReflectionException
641
+	 */
642
+	protected function _release_reserved_ticket_for_registration(
643
+		EE_Registration $registration,
644
+		EE_Transaction $transaction
645
+	): int {
646
+		$STS_ID = $transaction->status_ID();
647
+		// self::debug hardcoded to false
648
+		if (self::debug) {
649
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
650
+			echo self::$nl . ' . . registration->ID: ' . $registration->ID();
651
+			echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
652
+			echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
653
+		}
654
+		if (
655 655
 // release Tickets for Failed Transactions and Abandoned Transactions
656
-            $STS_ID === EEM_Transaction::failed_status_code
657
-            || $STS_ID === EEM_Transaction::abandoned_status_code
658
-            || (
659
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
660
-                $STS_ID === EEM_Transaction::incomplete_status_code
661
-                && $registration->status_ID() !== RegStatus::APPROVED
662
-            )
663
-        ) {
664
-            if (self::debug) {
665
-                echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
666
-                $reserved = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
667
-                echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
668
-                var_dump($reserved);
669
-            }
670
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:' . __LINE__);
671
-            return 1;
672
-        }
673
-        return 0;
674
-    }
675
-
676
-
677
-
678
-    /********************************** SESSION_CART_RESET  **********************************/
679
-
680
-
681
-    /**
682
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
683
-     *
684
-     * @param EE_Session $session
685
-     * @return void
686
-     * @throws EE_Error
687
-     * @throws InvalidArgumentException
688
-     * @throws ReflectionException
689
-     * @throws InvalidDataTypeException
690
-     * @throws InvalidInterfaceException
691
-     */
692
-    public static function session_cart_reset(EE_Session $session)
693
-    {
694
-        // don't release tickets if checkout was already reset
695
-        if (did_action('AHEE__EE_Session__reset_checkout__before_reset')) {
696
-            return;
697
-        }
698
-        // self::debug hardcoded to false
699
-        if (self::debug) {
700
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
701
-        }
702
-        // first check of the session has a valid Checkout object
703
-        $checkout = $session->checkout();
704
-        if ($checkout instanceof EE_Checkout) {
705
-            // and use that to clear ticket reservations because it will update the associated registration meta data
706
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
707
-            return;
708
-        }
709
-        $cart = $session->cart();
710
-        if ($cart instanceof EE_Cart) {
711
-            if (self::debug) {
712
-                echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
713
-            }
714
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
715
-        } else {
716
-            if (self::debug) {
717
-                echo self::$nl . self::$nl . ' invalid EE_Cart: ';
718
-                echo var_export($cart, true);
719
-            }
720
-        }
721
-    }
722
-
723
-
724
-    /**
725
-     * releases reserved tickets in the EE_Cart
726
-     *
727
-     * @param EE_Cart $cart
728
-     * @param EE_Session $session
729
-     * @return void
730
-     * @throws EE_Error
731
-     * @throws InvalidArgumentException
732
-     * @throws ReflectionException
733
-     * @throws InvalidDataTypeException
734
-     * @throws InvalidInterfaceException
735
-     */
736
-    protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
737
-    {
738
-        // self::debug hardcoded to false
739
-        if (self::debug) {
740
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
741
-        }
742
-        $ticket_line_items = $cart->get_tickets();
743
-        if (empty($ticket_line_items)) {
744
-            return;
745
-        }
746
-        if (self::debug) {
747
-            echo '<br /> . ticket_line_item count: ' . count($ticket_line_items);
748
-        }
749
-        foreach ($ticket_line_items as $ticket_line_item) {
750
-            if (self::debug) {
751
-                echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
752
-            }
753
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
754
-                if (self::debug) {
755
-                    echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
756
-                }
757
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
758
-                if ($ticket instanceof EE_Ticket) {
759
-                    if (self::debug) {
760
-                        echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
761
-                        echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
762
-                        $ticket->add_extra_meta(
763
-                            EE_Ticket::META_KEY_TICKET_RESERVATIONS,
764
-                            __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
765
-                        );
766
-                    }
767
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
768
-                }
769
-            }
770
-        }
771
-        if (self::debug) {
772
-            echo self::$nl . self::$nl . ' RESET COMPLETED ';
773
-        }
774
-    }
775
-
776
-
777
-
778
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
779
-
780
-
781
-    /**
782
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
783
-     *
784
-     * @param EE_Session $session
785
-     * @return void
786
-     * @throws EE_Error
787
-     * @throws ReflectionException
788
-     */
789
-    public static function session_checkout_reset(EE_Session $session)
790
-    {
791
-        // don't release tickets if cart was already reset
792
-        if (did_action('AHEE__EE_Session__reset_cart__before_reset')) {
793
-            return;
794
-        }
795
-        $checkout = $session->checkout();
796
-        if ($checkout instanceof EE_Checkout) {
797
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
798
-        }
799
-    }
800
-
801
-
802
-    /**
803
-     * releases reserved tickets for the EE_Checkout->transaction
804
-     *
805
-     * @param EE_Checkout $checkout
806
-     * @return void
807
-     * @throws EE_Error
808
-     * @throws ReflectionException
809
-     */
810
-    protected function _session_checkout_reset(EE_Checkout $checkout)
811
-    {
812
-        // self::debug hardcoded to false
813
-        if (self::debug) {
814
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
815
-        }
816
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
817
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
818
-            return;
819
-        }
820
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
821
-    }
822
-
823
-
824
-
825
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
826
-
827
-
828
-    /**
829
-     * @param    EE_Session $session
830
-     * @return    void
831
-     */
832
-    public static function session_expired_reset(EE_Session $session)
833
-    {
834
-    }
835
-
836
-
837
-
838
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
839
-
840
-
841
-    /**
842
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
843
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
844
-     *
845
-     * @param EE_Transaction $transaction
846
-     * @return void
847
-     * @throws EE_Error
848
-     * @throws ReflectionException
849
-     */
850
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
851
-    {
852
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
853
-        if ($transaction->is_free() || $transaction->paid() > 0) {
854
-            // self::debug hardcoded to false
855
-            if (self::debug) {
856
-                // DEBUG LOG
857
-                EEH_Debug_Tools::log(
858
-                    __CLASS__,
859
-                    __FUNCTION__,
860
-                    __LINE__,
861
-                    array($transaction),
862
-                    false,
863
-                    'EE_Transaction: ' . $transaction->ID()
864
-                );
865
-            }
866
-            return;
867
-        }
868
-        // have their been any successful payments made ?
869
-        $payments = $transaction->payments();
870
-        foreach ($payments as $payment) {
871
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
872
-                if (self::debug) {
873
-                    // DEBUG LOG
874
-                    EEH_Debug_Tools::log(
875
-                        __CLASS__,
876
-                        __FUNCTION__,
877
-                        __LINE__,
878
-                        array($payment),
879
-                        false,
880
-                        'EE_Transaction: ' . $transaction->ID()
881
-                    );
882
-                }
883
-                return;
884
-            }
885
-        }
886
-        // since you haven't even attempted to pay for your ticket...
887
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
888
-    }
889
-
890
-
891
-
892
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
893
-
894
-
895
-    /**
896
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
897
-     *
898
-     * @param EE_Transaction $transaction
899
-     * @return void
900
-     * @throws EE_Error
901
-     * @throws ReflectionException
902
-     */
903
-    public static function process_failed_transactions(EE_Transaction $transaction)
904
-    {
905
-        // since you haven't even attempted to pay for your ticket...
906
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
907
-    }
908
-
909
-
910
-
911
-    /********************************** RESET RESERVATION COUNTS  *********************************/
912
-
913
-
914
-    /**
915
-     * Resets the ticket and datetime reserved counts.
916
-     *
917
-     * For all the tickets with reservations, recalculates what their actual reserved counts should be based
918
-     * on the valid transactions.
919
-     *
920
-     * @return int number of tickets whose reservations were released.
921
-     * @throws EE_Error
922
-     * @throws DomainException
923
-     * @throws InvalidDataTypeException
924
-     * @throws InvalidInterfaceException
925
-     * @throws InvalidArgumentException
926
-     * @throws UnexpectedEntityException
927
-     * @throws ReflectionException
928
-     */
929
-    public static function reset_reservation_counts(): int
930
-    {
931
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
932
-        $valid_reserved_tickets = array();
933
-        /** @var EE_Transaction[] $transactions_in_progress */
934
-        $transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
935
-        foreach ($transactions_in_progress as $transaction) {
936
-            // if this TXN has been fully completed, then skip it
937
-            if ($transaction->reg_step_completed('finalize_registration')) {
938
-                continue;
939
-            }
940
-            $total_line_item = $transaction->total_line_item();
941
-            // $transaction_in_progress->line
942
-            if (! $total_line_item instanceof EE_Line_Item) {
943
-                throw new DomainException(
944
-                    esc_html__(
945
-                        'Transaction does not have a valid Total Line Item associated with it.',
946
-                        'event_espresso'
947
-                    )
948
-                );
949
-            }
950
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
951
-                $total_line_item
952
-            );
953
-        }
954
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
955
-        foreach ($total_line_items as $total_line_item) {
956
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
957
-                $total_line_item
958
-            );
959
-        }
960
-        $tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
961
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
962
-            $tickets_with_reservations,
963
-            $valid_reserved_tickets,
964
-            __FUNCTION__
965
-        );
966
-    }
967
-
968
-
969
-    /**
970
-     * @param EE_Line_Item $total_line_item
971
-     * @return EE_Line_Item[]
972
-     * @throws EE_Error
973
-     * @throws ReflectionException
974
-     */
975
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item): array
976
-    {
977
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
978
-        $valid_reserved_tickets = array();
979
-        $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
980
-        foreach ($ticket_line_items as $ticket_line_item) {
981
-            if ($ticket_line_item instanceof EE_Line_Item) {
982
-                $valid_reserved_tickets[ $ticket_line_item->ID() ] = $ticket_line_item;
983
-            }
984
-        }
985
-        return $valid_reserved_tickets;
986
-    }
987
-
988
-
989
-    /**
990
-     * Releases ticket and datetime reservations (ie, reduces the number of reserved spots on them).
991
-     *
992
-     * Given the list of tickets which have reserved spots on them, uses the complete list of line items for tickets
993
-     * whose transactions aren't complete and also aren't yet expired (ie, they're incomplete and younger than the
994
-     * session's expiry time) to update the ticket (and their datetimes') reserved counts.
995
-     *
996
-     * @param EE_Ticket[]    $tickets_with_reservations        all tickets with TKT_reserved > 0
997
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items all line items for tickets and incomplete transactions
998
-     *                                                         whose session has NOT expired. We will use these to
999
-     *                                                         determine the number of ticket reservations are now
1000
-     *                                                         invalid. We don't use the list of invalid ticket line
1001
-     *                                                         items because we don't know which of those have already
1002
-     *                                                         been taken into account when reducing ticket reservation
1003
-     *                                                         counts, and which haven't.
1004
-     * @param string $source
1005
-     * @return int
1006
-     * @throws UnexpectedEntityException
1007
-     * @throws DomainException
1008
-     * @throws EE_Error
1009
-     * @throws ReflectionException
1010
-     */
1011
-    protected static function release_reservations_for_tickets(
1012
-        array $tickets_with_reservations,
1013
-        array $valid_reserved_ticket_line_items = [],
1014
-        string $source = ''
1015
-    ): int {
1016
-        $total_tickets_released = 0;
1017
-        $sold_out_events = array();
1018
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
1019
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1020
-                continue;
1021
-            }
1022
-            // The $valid_reserved_ticket_line_items tells us what the reserved count on their tickets (and datetimes)
1023
-            // SHOULD be. Instead of just directly updating the list, we're going to use EE_Ticket::decreaseReserved()
1024
-            // to try to avoid race conditions, so instead of just finding the number to update TO, we're going to find
1025
-            // the number to RELEASE. It's the same end result, just different path.
1026
-            // Begin by assuming we're going to release all the reservations on this ticket.
1027
-            $expired_reservations_count = $ticket_with_reservations->reserved();
1028
-            // Now reduce that number using the list of current valid reservations.
1029
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1030
-                if (
1031
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
1032
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1033
-                ) {
1034
-                    $expired_reservations_count -= $valid_reserved_ticket_line_item->quantity();
1035
-                }
1036
-            }
1037
-            // Only bother saving the tickets and datetimes if we're actually going to release some spots.
1038
-            if ($expired_reservations_count > 0) {
1039
-                if (self::debug) {
1040
-                    $ticket_with_reservations->add_extra_meta(
1041
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1042
-                        __LINE__ . ') ' . $source . '()'
1043
-                    );
1044
-                }
1045
-                $ticket_with_reservations->decreaseReserved($expired_reservations_count, true, 'TicketSalesMonitor:' . __LINE__);
1046
-                $total_tickets_released += $expired_reservations_count;
1047
-                $event = $ticket_with_reservations->get_related_event();
1048
-                // track sold out events
1049
-                if ($event instanceof EE_Event && $event->is_sold_out()) {
1050
-                    $sold_out_events[] = $event;
1051
-                }
1052
-            }
1053
-        }
1054
-        // Double check whether sold out events should remain sold out after releasing tickets
1055
-        if ($sold_out_events !== array()) {
1056
-            foreach ($sold_out_events as $sold_out_event) {
1057
-                /** @var EE_Event $sold_out_event */
1058
-                $sold_out_event->perform_sold_out_status_check();
1059
-            }
1060
-        }
1061
-        return $total_tickets_released;
1062
-    }
1063
-
1064
-
1065
-
1066
-    /********************************** SHUTDOWN  **********************************/
1067
-
1068
-
1069
-    /**
1070
-     * @param int $timestamp
1071
-     * @return false|int
1072
-     * @throws EE_Error
1073
-     * @throws InvalidArgumentException
1074
-     * @throws InvalidDataTypeException
1075
-     * @throws InvalidInterfaceException
1076
-     * @throws ReflectionException
1077
-     */
1078
-    public static function clear_expired_line_items_with_no_transaction(int $timestamp = 0)
1079
-    {
1080
-        /** @type WPDB $wpdb */
1081
-        global $wpdb;
1082
-        if (! absint($timestamp)) {
1083
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1084
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
1085
-                'EventEspresso\core\domain\values\session\SessionLifespan'
1086
-            );
1087
-            $timestamp = $session_lifespan->expiration();
1088
-        }
1089
-        return $wpdb->query(
1090
-            $wpdb->prepare(
1091
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
656
+			$STS_ID === EEM_Transaction::failed_status_code
657
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
658
+			|| (
659
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
660
+				$STS_ID === EEM_Transaction::incomplete_status_code
661
+				&& $registration->status_ID() !== RegStatus::APPROVED
662
+			)
663
+		) {
664
+			if (self::debug) {
665
+				echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
666
+				$reserved = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
667
+				echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
668
+				var_dump($reserved);
669
+			}
670
+			$registration->release_reserved_ticket(true, 'TicketSalesMonitor:' . __LINE__);
671
+			return 1;
672
+		}
673
+		return 0;
674
+	}
675
+
676
+
677
+
678
+	/********************************** SESSION_CART_RESET  **********************************/
679
+
680
+
681
+	/**
682
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
683
+	 *
684
+	 * @param EE_Session $session
685
+	 * @return void
686
+	 * @throws EE_Error
687
+	 * @throws InvalidArgumentException
688
+	 * @throws ReflectionException
689
+	 * @throws InvalidDataTypeException
690
+	 * @throws InvalidInterfaceException
691
+	 */
692
+	public static function session_cart_reset(EE_Session $session)
693
+	{
694
+		// don't release tickets if checkout was already reset
695
+		if (did_action('AHEE__EE_Session__reset_checkout__before_reset')) {
696
+			return;
697
+		}
698
+		// self::debug hardcoded to false
699
+		if (self::debug) {
700
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
701
+		}
702
+		// first check of the session has a valid Checkout object
703
+		$checkout = $session->checkout();
704
+		if ($checkout instanceof EE_Checkout) {
705
+			// and use that to clear ticket reservations because it will update the associated registration meta data
706
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
707
+			return;
708
+		}
709
+		$cart = $session->cart();
710
+		if ($cart instanceof EE_Cart) {
711
+			if (self::debug) {
712
+				echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
713
+			}
714
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
715
+		} else {
716
+			if (self::debug) {
717
+				echo self::$nl . self::$nl . ' invalid EE_Cart: ';
718
+				echo var_export($cart, true);
719
+			}
720
+		}
721
+	}
722
+
723
+
724
+	/**
725
+	 * releases reserved tickets in the EE_Cart
726
+	 *
727
+	 * @param EE_Cart $cart
728
+	 * @param EE_Session $session
729
+	 * @return void
730
+	 * @throws EE_Error
731
+	 * @throws InvalidArgumentException
732
+	 * @throws ReflectionException
733
+	 * @throws InvalidDataTypeException
734
+	 * @throws InvalidInterfaceException
735
+	 */
736
+	protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
737
+	{
738
+		// self::debug hardcoded to false
739
+		if (self::debug) {
740
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
741
+		}
742
+		$ticket_line_items = $cart->get_tickets();
743
+		if (empty($ticket_line_items)) {
744
+			return;
745
+		}
746
+		if (self::debug) {
747
+			echo '<br /> . ticket_line_item count: ' . count($ticket_line_items);
748
+		}
749
+		foreach ($ticket_line_items as $ticket_line_item) {
750
+			if (self::debug) {
751
+				echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
752
+			}
753
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
754
+				if (self::debug) {
755
+					echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
756
+				}
757
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
758
+				if ($ticket instanceof EE_Ticket) {
759
+					if (self::debug) {
760
+						echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
761
+						echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
762
+						$ticket->add_extra_meta(
763
+							EE_Ticket::META_KEY_TICKET_RESERVATIONS,
764
+							__LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
765
+						);
766
+					}
767
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
768
+				}
769
+			}
770
+		}
771
+		if (self::debug) {
772
+			echo self::$nl . self::$nl . ' RESET COMPLETED ';
773
+		}
774
+	}
775
+
776
+
777
+
778
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
779
+
780
+
781
+	/**
782
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
783
+	 *
784
+	 * @param EE_Session $session
785
+	 * @return void
786
+	 * @throws EE_Error
787
+	 * @throws ReflectionException
788
+	 */
789
+	public static function session_checkout_reset(EE_Session $session)
790
+	{
791
+		// don't release tickets if cart was already reset
792
+		if (did_action('AHEE__EE_Session__reset_cart__before_reset')) {
793
+			return;
794
+		}
795
+		$checkout = $session->checkout();
796
+		if ($checkout instanceof EE_Checkout) {
797
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
798
+		}
799
+	}
800
+
801
+
802
+	/**
803
+	 * releases reserved tickets for the EE_Checkout->transaction
804
+	 *
805
+	 * @param EE_Checkout $checkout
806
+	 * @return void
807
+	 * @throws EE_Error
808
+	 * @throws ReflectionException
809
+	 */
810
+	protected function _session_checkout_reset(EE_Checkout $checkout)
811
+	{
812
+		// self::debug hardcoded to false
813
+		if (self::debug) {
814
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
815
+		}
816
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
817
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
818
+			return;
819
+		}
820
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
821
+	}
822
+
823
+
824
+
825
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
826
+
827
+
828
+	/**
829
+	 * @param    EE_Session $session
830
+	 * @return    void
831
+	 */
832
+	public static function session_expired_reset(EE_Session $session)
833
+	{
834
+	}
835
+
836
+
837
+
838
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
839
+
840
+
841
+	/**
842
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
843
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
844
+	 *
845
+	 * @param EE_Transaction $transaction
846
+	 * @return void
847
+	 * @throws EE_Error
848
+	 * @throws ReflectionException
849
+	 */
850
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
851
+	{
852
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
853
+		if ($transaction->is_free() || $transaction->paid() > 0) {
854
+			// self::debug hardcoded to false
855
+			if (self::debug) {
856
+				// DEBUG LOG
857
+				EEH_Debug_Tools::log(
858
+					__CLASS__,
859
+					__FUNCTION__,
860
+					__LINE__,
861
+					array($transaction),
862
+					false,
863
+					'EE_Transaction: ' . $transaction->ID()
864
+				);
865
+			}
866
+			return;
867
+		}
868
+		// have their been any successful payments made ?
869
+		$payments = $transaction->payments();
870
+		foreach ($payments as $payment) {
871
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
872
+				if (self::debug) {
873
+					// DEBUG LOG
874
+					EEH_Debug_Tools::log(
875
+						__CLASS__,
876
+						__FUNCTION__,
877
+						__LINE__,
878
+						array($payment),
879
+						false,
880
+						'EE_Transaction: ' . $transaction->ID()
881
+					);
882
+				}
883
+				return;
884
+			}
885
+		}
886
+		// since you haven't even attempted to pay for your ticket...
887
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
888
+	}
889
+
890
+
891
+
892
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
893
+
894
+
895
+	/**
896
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
897
+	 *
898
+	 * @param EE_Transaction $transaction
899
+	 * @return void
900
+	 * @throws EE_Error
901
+	 * @throws ReflectionException
902
+	 */
903
+	public static function process_failed_transactions(EE_Transaction $transaction)
904
+	{
905
+		// since you haven't even attempted to pay for your ticket...
906
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
907
+	}
908
+
909
+
910
+
911
+	/********************************** RESET RESERVATION COUNTS  *********************************/
912
+
913
+
914
+	/**
915
+	 * Resets the ticket and datetime reserved counts.
916
+	 *
917
+	 * For all the tickets with reservations, recalculates what their actual reserved counts should be based
918
+	 * on the valid transactions.
919
+	 *
920
+	 * @return int number of tickets whose reservations were released.
921
+	 * @throws EE_Error
922
+	 * @throws DomainException
923
+	 * @throws InvalidDataTypeException
924
+	 * @throws InvalidInterfaceException
925
+	 * @throws InvalidArgumentException
926
+	 * @throws UnexpectedEntityException
927
+	 * @throws ReflectionException
928
+	 */
929
+	public static function reset_reservation_counts(): int
930
+	{
931
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
932
+		$valid_reserved_tickets = array();
933
+		/** @var EE_Transaction[] $transactions_in_progress */
934
+		$transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
935
+		foreach ($transactions_in_progress as $transaction) {
936
+			// if this TXN has been fully completed, then skip it
937
+			if ($transaction->reg_step_completed('finalize_registration')) {
938
+				continue;
939
+			}
940
+			$total_line_item = $transaction->total_line_item();
941
+			// $transaction_in_progress->line
942
+			if (! $total_line_item instanceof EE_Line_Item) {
943
+				throw new DomainException(
944
+					esc_html__(
945
+						'Transaction does not have a valid Total Line Item associated with it.',
946
+						'event_espresso'
947
+					)
948
+				);
949
+			}
950
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
951
+				$total_line_item
952
+			);
953
+		}
954
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
955
+		foreach ($total_line_items as $total_line_item) {
956
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
957
+				$total_line_item
958
+			);
959
+		}
960
+		$tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
961
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
962
+			$tickets_with_reservations,
963
+			$valid_reserved_tickets,
964
+			__FUNCTION__
965
+		);
966
+	}
967
+
968
+
969
+	/**
970
+	 * @param EE_Line_Item $total_line_item
971
+	 * @return EE_Line_Item[]
972
+	 * @throws EE_Error
973
+	 * @throws ReflectionException
974
+	 */
975
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item): array
976
+	{
977
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
978
+		$valid_reserved_tickets = array();
979
+		$ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
980
+		foreach ($ticket_line_items as $ticket_line_item) {
981
+			if ($ticket_line_item instanceof EE_Line_Item) {
982
+				$valid_reserved_tickets[ $ticket_line_item->ID() ] = $ticket_line_item;
983
+			}
984
+		}
985
+		return $valid_reserved_tickets;
986
+	}
987
+
988
+
989
+	/**
990
+	 * Releases ticket and datetime reservations (ie, reduces the number of reserved spots on them).
991
+	 *
992
+	 * Given the list of tickets which have reserved spots on them, uses the complete list of line items for tickets
993
+	 * whose transactions aren't complete and also aren't yet expired (ie, they're incomplete and younger than the
994
+	 * session's expiry time) to update the ticket (and their datetimes') reserved counts.
995
+	 *
996
+	 * @param EE_Ticket[]    $tickets_with_reservations        all tickets with TKT_reserved > 0
997
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items all line items for tickets and incomplete transactions
998
+	 *                                                         whose session has NOT expired. We will use these to
999
+	 *                                                         determine the number of ticket reservations are now
1000
+	 *                                                         invalid. We don't use the list of invalid ticket line
1001
+	 *                                                         items because we don't know which of those have already
1002
+	 *                                                         been taken into account when reducing ticket reservation
1003
+	 *                                                         counts, and which haven't.
1004
+	 * @param string $source
1005
+	 * @return int
1006
+	 * @throws UnexpectedEntityException
1007
+	 * @throws DomainException
1008
+	 * @throws EE_Error
1009
+	 * @throws ReflectionException
1010
+	 */
1011
+	protected static function release_reservations_for_tickets(
1012
+		array $tickets_with_reservations,
1013
+		array $valid_reserved_ticket_line_items = [],
1014
+		string $source = ''
1015
+	): int {
1016
+		$total_tickets_released = 0;
1017
+		$sold_out_events = array();
1018
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
1019
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
1020
+				continue;
1021
+			}
1022
+			// The $valid_reserved_ticket_line_items tells us what the reserved count on their tickets (and datetimes)
1023
+			// SHOULD be. Instead of just directly updating the list, we're going to use EE_Ticket::decreaseReserved()
1024
+			// to try to avoid race conditions, so instead of just finding the number to update TO, we're going to find
1025
+			// the number to RELEASE. It's the same end result, just different path.
1026
+			// Begin by assuming we're going to release all the reservations on this ticket.
1027
+			$expired_reservations_count = $ticket_with_reservations->reserved();
1028
+			// Now reduce that number using the list of current valid reservations.
1029
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1030
+				if (
1031
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
1032
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1033
+				) {
1034
+					$expired_reservations_count -= $valid_reserved_ticket_line_item->quantity();
1035
+				}
1036
+			}
1037
+			// Only bother saving the tickets and datetimes if we're actually going to release some spots.
1038
+			if ($expired_reservations_count > 0) {
1039
+				if (self::debug) {
1040
+					$ticket_with_reservations->add_extra_meta(
1041
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1042
+						__LINE__ . ') ' . $source . '()'
1043
+					);
1044
+				}
1045
+				$ticket_with_reservations->decreaseReserved($expired_reservations_count, true, 'TicketSalesMonitor:' . __LINE__);
1046
+				$total_tickets_released += $expired_reservations_count;
1047
+				$event = $ticket_with_reservations->get_related_event();
1048
+				// track sold out events
1049
+				if ($event instanceof EE_Event && $event->is_sold_out()) {
1050
+					$sold_out_events[] = $event;
1051
+				}
1052
+			}
1053
+		}
1054
+		// Double check whether sold out events should remain sold out after releasing tickets
1055
+		if ($sold_out_events !== array()) {
1056
+			foreach ($sold_out_events as $sold_out_event) {
1057
+				/** @var EE_Event $sold_out_event */
1058
+				$sold_out_event->perform_sold_out_status_check();
1059
+			}
1060
+		}
1061
+		return $total_tickets_released;
1062
+	}
1063
+
1064
+
1065
+
1066
+	/********************************** SHUTDOWN  **********************************/
1067
+
1068
+
1069
+	/**
1070
+	 * @param int $timestamp
1071
+	 * @return false|int
1072
+	 * @throws EE_Error
1073
+	 * @throws InvalidArgumentException
1074
+	 * @throws InvalidDataTypeException
1075
+	 * @throws InvalidInterfaceException
1076
+	 * @throws ReflectionException
1077
+	 */
1078
+	public static function clear_expired_line_items_with_no_transaction(int $timestamp = 0)
1079
+	{
1080
+		/** @type WPDB $wpdb */
1081
+		global $wpdb;
1082
+		if (! absint($timestamp)) {
1083
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1084
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
1085
+				'EventEspresso\core\domain\values\session\SessionLifespan'
1086
+			);
1087
+			$timestamp = $session_lifespan->expiration();
1088
+		}
1089
+		return $wpdb->query(
1090
+			$wpdb->prepare(
1091
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1092 1092
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1093
-                // use GMT time because that's what LIN_timestamps are in
1094
-                date('Y-m-d H:i:s', $timestamp)
1095
-            )
1096
-        );
1097
-    }
1093
+				// use GMT time because that's what LIN_timestamps are in
1094
+				date('Y-m-d H:i:s', $timestamp)
1095
+			)
1096
+		);
1097
+	}
1098 1098
 }
Please login to merge, or discard this patch.
Spacing   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -19,7 +19,7 @@  discard block
 block discarded – undo
19 19
  */
20 20
 class EED_Ticket_Sales_Monitor extends EED_Module
21 21
 {
22
-    const debug = false;    // true false
22
+    const debug = false; // true false
23 23
 
24 24
     private static $nl = '';
25 25
 
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
     {
170 170
         // self::debug hardcoded to false
171 171
         if (self::debug) {
172
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
172
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
173 173
         }
174 174
         do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
175 175
         $expired_ticket_IDs = array();
@@ -180,29 +180,29 @@  discard block
 block discarded – undo
180 180
         $timestamp = $session_lifespan->expiration();
181 181
         $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
182 182
         if (self::debug) {
183
-            echo self::$nl . ' . time(): ' . time();
184
-            echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
185
-            echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
186
-            echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
187
-            echo self::$nl . ' . timestamp: ' . $timestamp;
188
-            echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
183
+            echo self::$nl.' . time(): '.time();
184
+            echo self::$nl.' . time() as date: '.date('Y-m-d H:i a');
185
+            echo self::$nl.' . session expiration: '.$session_lifespan->expiration();
186
+            echo self::$nl.' . session expiration as date: '.date('Y-m-d H:i a', $session_lifespan->expiration());
187
+            echo self::$nl.' . timestamp: '.$timestamp;
188
+            echo self::$nl.' . $expired_ticket_line_items: '.count($expired_ticket_line_items);
189 189
         }
190
-        if (! empty($expired_ticket_line_items)) {
190
+        if ( ! empty($expired_ticket_line_items)) {
191 191
             foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
192
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
192
+                if ( ! $expired_ticket_line_item instanceof EE_Line_Item) {
193 193
                     continue;
194 194
                 }
195
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
195
+                $expired_ticket_IDs[$expired_ticket_line_item->OBJ_ID()] = $expired_ticket_line_item->OBJ_ID();
196 196
                 if (self::debug) {
197
-                    echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
198
-                    echo self::$nl . ' . $expired_ticket_line_item->timestamp(): '
197
+                    echo self::$nl.' . $expired_ticket_line_item->OBJ_ID(): '.$expired_ticket_line_item->OBJ_ID();
198
+                    echo self::$nl.' . $expired_ticket_line_item->timestamp(): '
199 199
                          . date(
200 200
                              'Y-m-d h:i a',
201 201
                              $expired_ticket_line_item->timestamp(true)
202 202
                          );
203 203
                 }
204 204
             }
205
-            if (! empty($expired_ticket_IDs)) {
205
+            if ( ! empty($expired_ticket_IDs)) {
206 206
                 EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
207 207
                     EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
208 208
                     array(),
@@ -242,8 +242,8 @@  discard block
 block discarded – undo
242 242
         }
243 243
         // self::debug hardcoded to false
244 244
         if (self::debug) {
245
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
246
-            echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
245
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
246
+            echo self::$nl.self::$nl.'<b> RETURNED QTY: '.$qty.'</b>';
247 247
         }
248 248
         return $qty;
249 249
     }
@@ -263,36 +263,36 @@  discard block
 block discarded – undo
263 263
     {
264 264
         // self::debug hardcoded to false
265 265
         if (self::debug) {
266
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
266
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
267 267
         }
268
-        if (! $ticket instanceof EE_Ticket) {
268
+        if ( ! $ticket instanceof EE_Ticket) {
269 269
             return 0;
270 270
         }
271 271
         if (self::debug) {
272
-            echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
273
-            echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
272
+            echo self::$nl.'<b> . ticket->ID: '.$ticket->ID().'</b>';
273
+            echo self::$nl.' . original ticket->reserved: '.$ticket->reserved();
274 274
         }
275 275
         $ticket->refresh_from_db();
276 276
         // first let's determine the ticket availability based on sales
277 277
         $available = $ticket->qty('saleable');
278 278
         if (self::debug) {
279
-            echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
280
-            echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
281
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
282
-            echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
283
-            echo self::$nl . ' . . . available: ' . $available;
279
+            echo self::$nl.' . . . ticket->qty: '.$ticket->qty();
280
+            echo self::$nl.' . . . ticket->sold: '.$ticket->sold();
281
+            echo self::$nl.' . . . ticket->reserved: '.$ticket->reserved();
282
+            echo self::$nl.' . . . ticket->qty(saleable): '.$ticket->qty('saleable');
283
+            echo self::$nl.' . . . available: '.$available;
284 284
         }
285 285
         if ($available < 1) {
286 286
             $this->_ticket_sold_out($ticket);
287 287
             return 0;
288 288
         }
289 289
         if (self::debug) {
290
-            echo self::$nl . ' . . . qty: ' . $qty;
290
+            echo self::$nl.' . . . qty: '.$qty;
291 291
         }
292 292
         if ($available < $qty) {
293 293
             $qty = $available;
294 294
             if (self::debug) {
295
-                echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
295
+                echo self::$nl.' . . . QTY ADJUSTED: '.$qty;
296 296
             }
297 297
             $this->_ticket_quantity_decremented($ticket);
298 298
         }
@@ -316,9 +316,9 @@  discard block
 block discarded – undo
316 316
     {
317 317
         // self::debug hardcoded to false
318 318
         if (self::debug) {
319
-            echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
319
+            echo self::$nl.self::$nl.' . . . INCREASE RESERVED: '.$quantity;
320 320
         }
321
-        return $ticket->increaseReserved($quantity, 'TicketSalesMonitor:' . __LINE__);
321
+        return $ticket->increaseReserved($quantity, 'TicketSalesMonitor:'.__LINE__);
322 322
     }
323 323
 
324 324
 
@@ -333,12 +333,12 @@  discard block
 block discarded – undo
333 333
     {
334 334
         // self::debug hardcoded to false
335 335
         if (self::debug) {
336
-            echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
337
-            echo self::$nl . ' . . . ticket->reserved before: ' . $ticket->reserved();
336
+            echo self::$nl.' . . . ticket->ID: '.$ticket->ID();
337
+            echo self::$nl.' . . . ticket->reserved before: '.$ticket->reserved();
338 338
         }
339
-        $ticket->decreaseReserved($quantity, true, 'TicketSalesMonitor:' . __LINE__);
339
+        $ticket->decreaseReserved($quantity, true, 'TicketSalesMonitor:'.__LINE__);
340 340
         if (self::debug) {
341
-            echo self::$nl . ' . . . ticket->reserved after: ' . $ticket->reserved();
341
+            echo self::$nl.' . . . ticket->reserved after: '.$ticket->reserved();
342 342
         }
343 343
         return (bool) $ticket->save();
344 344
     }
@@ -357,8 +357,8 @@  discard block
 block discarded – undo
357 357
     {
358 358
         // self::debug hardcoded to false
359 359
         if (self::debug) {
360
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
361
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
360
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
361
+            echo self::$nl.' . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
362 362
         }
363 363
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
364 364
     }
@@ -377,8 +377,8 @@  discard block
 block discarded – undo
377 377
     {
378 378
         // self::debug hardcoded to false
379 379
         if (self::debug) {
380
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
381
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
380
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
381
+            echo self::$nl.' . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
382 382
         }
383 383
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
384 384
     }
@@ -432,7 +432,7 @@  discard block
 block discarded – undo
432 432
             if (self::debug) {
433 433
                 $ticket->add_extra_meta(
434 434
                     EE_Ticket::META_KEY_TICKET_RESERVATIONS,
435
-                    __LINE__ . ') ' . __METHOD__ . '()'
435
+                    __LINE__.') '.__METHOD__.'()'
436 436
                 );
437 437
             }
438 438
             if ($quantity > 0) {
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
         if (self::debug) {
459 459
             $ticket->add_extra_meta(
460 460
                 EE_Ticket::META_KEY_TICKET_RESERVATIONS,
461
-                __LINE__ . ') ' . __METHOD__ . '()'
461
+                __LINE__.') '.__METHOD__.'()'
462 462
             );
463 463
         }
464 464
         EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
@@ -492,7 +492,7 @@  discard block
 block discarded – undo
492 492
     {
493 493
         // self::debug hardcoded to false
494 494
         if (self::debug) {
495
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
495
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
496 496
         }
497 497
         $refresh_msg = '';
498 498
         $none_added_msg = '';
@@ -503,7 +503,7 @@  discard block
 block discarded – undo
503 503
             );
504 504
             $none_added_msg = esc_html__('No tickets were added for the event.', 'event_espresso');
505 505
         }
506
-        if (! empty($this->sold_out_tickets)) {
506
+        if ( ! empty($this->sold_out_tickets)) {
507 507
             EE_Error::add_attention(
508 508
                 sprintf(
509 509
                     apply_filters(
@@ -526,7 +526,7 @@  discard block
 block discarded – undo
526 526
             // and reset the cart
527 527
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
528 528
         }
529
-        if (! empty($this->decremented_tickets)) {
529
+        if ( ! empty($this->decremented_tickets)) {
530 530
             EE_Error::add_attention(
531 531
                 sprintf(
532 532
                     apply_filters(
@@ -564,9 +564,9 @@  discard block
 block discarded – undo
564 564
     {
565 565
         // self::debug hardcoded to false
566 566
         if (self::debug) {
567
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
568
-            echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
569
-            echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
567
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
568
+            echo self::$nl.' . transaction->ID: '.$transaction->ID();
569
+            echo self::$nl.' . TXN status_ID: '.$transaction->status_ID();
570 570
         }
571 571
         // check if 'finalize_registration' step has been completed...
572 572
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -578,13 +578,13 @@  discard block
 block discarded – undo
578 578
                 __LINE__,
579 579
                 array('finalized' => $finalized),
580 580
                 false,
581
-                'EE_Transaction: ' . $transaction->ID()
581
+                'EE_Transaction: '.$transaction->ID()
582 582
             );
583 583
         }
584 584
         // how many tickets were released
585 585
         $count = 0;
586 586
         if (self::debug) {
587
-            echo self::$nl . ' . . . TXN finalized: ' . $finalized;
587
+            echo self::$nl.' . . . TXN finalized: '.$finalized;
588 588
         }
589 589
         $release_tickets_with_TXN_status = array(
590 590
             EEM_Transaction::failed_status_code,
@@ -593,28 +593,28 @@  discard block
 block discarded – undo
593 593
         );
594 594
         $events = array();
595 595
         // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
596
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
596
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
597 597
             // cancel any reserved tickets for registrations that were not approved
598 598
             $registrations = $transaction->registrations();
599 599
             if (self::debug) {
600
-                echo self::$nl . ' . . . # registrations: ' . count($registrations);
600
+                echo self::$nl.' . . . # registrations: '.count($registrations);
601 601
                 $reg = reset($registrations);
602 602
                 $ticket = $reg->ticket();
603 603
                 if ($ticket instanceof EE_Ticket) {
604 604
                     $ticket->add_extra_meta(
605 605
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
606
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
606
+                        __LINE__.') Release All Tickets TXN:'.$transaction->ID()
607 607
                     );
608 608
                 }
609 609
             }
610
-            if (! empty($registrations)) {
610
+            if ( ! empty($registrations)) {
611 611
                 foreach ($registrations as $registration) {
612 612
                     if (
613 613
                         $registration instanceof EE_Registration
614 614
                         && $this->_release_reserved_ticket_for_registration($registration, $transaction)
615 615
                     ) {
616 616
                         $count++;
617
-                        $events[ $registration->event_ID() ] = $registration->event();
617
+                        $events[$registration->event_ID()] = $registration->event();
618 618
                     }
619 619
                 }
620 620
             }
@@ -646,10 +646,10 @@  discard block
 block discarded – undo
646 646
         $STS_ID = $transaction->status_ID();
647 647
         // self::debug hardcoded to false
648 648
         if (self::debug) {
649
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
650
-            echo self::$nl . ' . . registration->ID: ' . $registration->ID();
651
-            echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
652
-            echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
649
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
650
+            echo self::$nl.' . . registration->ID: '.$registration->ID();
651
+            echo self::$nl.' . . registration->status_ID: '.$registration->status_ID();
652
+            echo self::$nl.' . . transaction->status_ID(): '.$STS_ID;
653 653
         }
654 654
         if (
655 655
 // release Tickets for Failed Transactions and Abandoned Transactions
@@ -662,12 +662,12 @@  discard block
 block discarded – undo
662 662
             )
663 663
         ) {
664 664
             if (self::debug) {
665
-                echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
665
+                echo self::$nl.self::$nl.' . . RELEASE RESERVED TICKET';
666 666
                 $reserved = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
667
-                echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
667
+                echo self::$nl.' . . . registration HAS_RESERVED_TICKET_KEY: ';
668 668
                 var_dump($reserved);
669 669
             }
670
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:' . __LINE__);
670
+            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'.__LINE__);
671 671
             return 1;
672 672
         }
673 673
         return 0;
@@ -697,7 +697,7 @@  discard block
 block discarded – undo
697 697
         }
698 698
         // self::debug hardcoded to false
699 699
         if (self::debug) {
700
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
700
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
701 701
         }
702 702
         // first check of the session has a valid Checkout object
703 703
         $checkout = $session->checkout();
@@ -709,12 +709,12 @@  discard block
 block discarded – undo
709 709
         $cart = $session->cart();
710 710
         if ($cart instanceof EE_Cart) {
711 711
             if (self::debug) {
712
-                echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
712
+                echo self::$nl.self::$nl.' cart instance of EE_Cart: ';
713 713
             }
714 714
             EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
715 715
         } else {
716 716
             if (self::debug) {
717
-                echo self::$nl . self::$nl . ' invalid EE_Cart: ';
717
+                echo self::$nl.self::$nl.' invalid EE_Cart: ';
718 718
                 echo var_export($cart, true);
719 719
             }
720 720
         }
@@ -737,31 +737,31 @@  discard block
 block discarded – undo
737 737
     {
738 738
         // self::debug hardcoded to false
739 739
         if (self::debug) {
740
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
740
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
741 741
         }
742 742
         $ticket_line_items = $cart->get_tickets();
743 743
         if (empty($ticket_line_items)) {
744 744
             return;
745 745
         }
746 746
         if (self::debug) {
747
-            echo '<br /> . ticket_line_item count: ' . count($ticket_line_items);
747
+            echo '<br /> . ticket_line_item count: '.count($ticket_line_items);
748 748
         }
749 749
         foreach ($ticket_line_items as $ticket_line_item) {
750 750
             if (self::debug) {
751
-                echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
751
+                echo self::$nl.' . ticket_line_item->ID(): '.$ticket_line_item->ID();
752 752
             }
753 753
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
754 754
                 if (self::debug) {
755
-                    echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
755
+                    echo self::$nl.' . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
756 756
                 }
757 757
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
758 758
                 if ($ticket instanceof EE_Ticket) {
759 759
                     if (self::debug) {
760
-                        echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
761
-                        echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
760
+                        echo self::$nl.' . . ticket->ID(): '.$ticket->ID();
761
+                        echo self::$nl.' . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
762 762
                         $ticket->add_extra_meta(
763 763
                             EE_Ticket::META_KEY_TICKET_RESERVATIONS,
764
-                            __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
764
+                            __LINE__.') '.__METHOD__.'() SID = '.$session->id()
765 765
                         );
766 766
                     }
767 767
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
@@ -769,7 +769,7 @@  discard block
 block discarded – undo
769 769
             }
770 770
         }
771 771
         if (self::debug) {
772
-            echo self::$nl . self::$nl . ' RESET COMPLETED ';
772
+            echo self::$nl.self::$nl.' RESET COMPLETED ';
773 773
         }
774 774
     }
775 775
 
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
     {
812 812
         // self::debug hardcoded to false
813 813
         if (self::debug) {
814
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
814
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
815 815
         }
816 816
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
817 817
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
                     __LINE__,
861 861
                     array($transaction),
862 862
                     false,
863
-                    'EE_Transaction: ' . $transaction->ID()
863
+                    'EE_Transaction: '.$transaction->ID()
864 864
                 );
865 865
             }
866 866
             return;
@@ -877,7 +877,7 @@  discard block
 block discarded – undo
877 877
                         __LINE__,
878 878
                         array($payment),
879 879
                         false,
880
-                        'EE_Transaction: ' . $transaction->ID()
880
+                        'EE_Transaction: '.$transaction->ID()
881 881
                     );
882 882
                 }
883 883
                 return;
@@ -939,7 +939,7 @@  discard block
 block discarded – undo
939 939
             }
940 940
             $total_line_item = $transaction->total_line_item();
941 941
             // $transaction_in_progress->line
942
-            if (! $total_line_item instanceof EE_Line_Item) {
942
+            if ( ! $total_line_item instanceof EE_Line_Item) {
943 943
                 throw new DomainException(
944 944
                     esc_html__(
945 945
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -979,7 +979,7 @@  discard block
 block discarded – undo
979 979
         $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item);
980 980
         foreach ($ticket_line_items as $ticket_line_item) {
981 981
             if ($ticket_line_item instanceof EE_Line_Item) {
982
-                $valid_reserved_tickets[ $ticket_line_item->ID() ] = $ticket_line_item;
982
+                $valid_reserved_tickets[$ticket_line_item->ID()] = $ticket_line_item;
983 983
             }
984 984
         }
985 985
         return $valid_reserved_tickets;
@@ -1016,7 +1016,7 @@  discard block
 block discarded – undo
1016 1016
         $total_tickets_released = 0;
1017 1017
         $sold_out_events = array();
1018 1018
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
1019
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1019
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
1020 1020
                 continue;
1021 1021
             }
1022 1022
             // The $valid_reserved_ticket_line_items tells us what the reserved count on their tickets (and datetimes)
@@ -1039,10 +1039,10 @@  discard block
 block discarded – undo
1039 1039
                 if (self::debug) {
1040 1040
                     $ticket_with_reservations->add_extra_meta(
1041 1041
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1042
-                        __LINE__ . ') ' . $source . '()'
1042
+                        __LINE__.') '.$source.'()'
1043 1043
                     );
1044 1044
                 }
1045
-                $ticket_with_reservations->decreaseReserved($expired_reservations_count, true, 'TicketSalesMonitor:' . __LINE__);
1045
+                $ticket_with_reservations->decreaseReserved($expired_reservations_count, true, 'TicketSalesMonitor:'.__LINE__);
1046 1046
                 $total_tickets_released += $expired_reservations_count;
1047 1047
                 $event = $ticket_with_reservations->get_related_event();
1048 1048
                 // track sold out events
@@ -1079,7 +1079,7 @@  discard block
 block discarded – undo
1079 1079
     {
1080 1080
         /** @type WPDB $wpdb */
1081 1081
         global $wpdb;
1082
-        if (! absint($timestamp)) {
1082
+        if ( ! absint($timestamp)) {
1083 1083
             /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1084 1084
             $session_lifespan = LoaderFactory::getLoader()->getShared(
1085 1085
                 'EventEspresso\core\domain\values\session\SessionLifespan'
@@ -1088,7 +1088,7 @@  discard block
 block discarded – undo
1088 1088
         }
1089 1089
         return $wpdb->query(
1090 1090
             $wpdb->prepare(
1091
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1091
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
1092 1092
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1093 1093
                 // use GMT time because that's what LIN_timestamps are in
1094 1094
                 date('Y-m-d H:i:s', $timestamp)
Please login to merge, or discard this patch.
modules/single_page_checkout/EED_Single_Page_Checkout.module.php 2 patches
Indentation   +1658 added lines, -1658 removed lines patch added patch discarded remove patch
@@ -24,1662 +24,1662 @@
 block discarded – undo
24 24
  */
25 25
 class EED_Single_Page_Checkout extends EED_Module
26 26
 {
27
-    /**
28
-     * $_initialized - has the SPCO controller already been initialized ?
29
-     */
30
-    private static bool $_initialized = false;
31
-
32
-
33
-    /**
34
-     * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
35
-     */
36
-    private static bool $_checkout_verified = true;
37
-
38
-    /**
39
-     * $_reg_steps_array - holds initial array of reg steps
40
-     *
41
-     * @var array $_reg_steps_array
42
-     */
43
-    private static array $_reg_steps_array = [];
44
-
45
-    /**
46
-     * $checkout - EE_Checkout object for handling the properties of the current checkout process
47
-     */
48
-    public ?EE_Checkout $checkout = null;
49
-
50
-    protected ?RequestInterface $request = null;
51
-
52
-    public ?EE_Session $session = null;
53
-
54
-    private bool $debug = false;    //  true    false
55
-
56
-
57
-    /**
58
-     * @return EED_Single_Page_Checkout|EED_Module
59
-     * @throws EE_Error
60
-     * @throws ReflectionException
61
-     */
62
-    public static function instance()
63
-    {
64
-        add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
65
-        return parent::get_instance(__CLASS__);
66
-    }
67
-
68
-
69
-    /**
70
-     * @return EE_CART
71
-     */
72
-    public function cart(): EE_CART
73
-    {
74
-        return $this->checkout->cart;
75
-    }
76
-
77
-
78
-    /**
79
-     * @return RequestInterface
80
-     * @since   4.10.14.p
81
-     */
82
-    public static function getRequest(): RequestInterface
83
-    {
84
-        return LoaderFactory::getLoader()->getShared(RequestInterface::class);
85
-    }
86
-
87
-
88
-    /**
89
-     * @return EE_Transaction
90
-     */
91
-    public function transaction(): EE_Transaction
92
-    {
93
-        return $this->checkout->transaction;
94
-    }
95
-
96
-
97
-    /**
98
-     *    set_hooks - for hooking into EE Core, other modules, etc
99
-     *
100
-     * @return    void
101
-     * @throws EE_Error
102
-     */
103
-    public static function set_hooks()
104
-    {
105
-        EED_Single_Page_Checkout::set_definitions();
106
-    }
107
-
108
-
109
-    /**
110
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
111
-     *
112
-     * @return    void
113
-     * @throws EE_Error
114
-     */
115
-    public static function set_hooks_admin()
116
-    {
117
-        EED_Single_Page_Checkout::set_definitions();
118
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
119
-            return;
120
-        }
121
-        // going to start an output buffer in case anything gets accidentally output
122
-        // that might disrupt our JSON response
123
-        ob_start();
124
-        EED_Single_Page_Checkout::load_reg_steps();
125
-        // set ajax hooks
126
-        add_action('wp_ajax_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
127
-        add_action('wp_ajax_nopriv_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
128
-        add_action('wp_ajax_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
129
-        add_action('wp_ajax_nopriv_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
130
-        add_action('wp_ajax_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
131
-        add_action('wp_ajax_nopriv_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
132
-    }
133
-
134
-
135
-    /**
136
-     *    process ajax request
137
-     *
138
-     * @param string $ajax_action
139
-     * @throws EE_Error
140
-     * @throws ReflectionException
141
-     */
142
-    public static function process_ajax_request(string $ajax_action)
143
-    {
144
-        $request = EED_Single_Page_Checkout::getRequest();
145
-        $request->setRequestParam('action', $ajax_action);
146
-        EED_Single_Page_Checkout::instance()->_initialize();
147
-    }
148
-
149
-
150
-    /**
151
-     * ajax display registration step
152
-     *
153
-     * @throws EE_Error
154
-     * @throws ReflectionException
155
-     */
156
-    public static function display_reg_step()
157
-    {
158
-        EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
159
-    }
160
-
161
-
162
-    /**
163
-     * ajax process registration step
164
-     *
165
-     * @throws EE_Error
166
-     * @throws ReflectionException
167
-     */
168
-    public static function process_reg_step()
169
-    {
170
-        EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
171
-    }
172
-
173
-
174
-    /**
175
-     * ajax process registration step
176
-     *
177
-     * @throws EE_Error
178
-     * @throws ReflectionException
179
-     */
180
-    public static function update_reg_step()
181
-    {
182
-        EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
183
-    }
184
-
185
-
186
-    /**
187
-     * update_checkout
188
-     *
189
-     * @return void
190
-     * @throws ReflectionException
191
-     * @throws EE_Error
192
-     */
193
-    public static function update_checkout()
194
-    {
195
-        EED_Single_Page_Checkout::process_ajax_request('update_checkout');
196
-    }
197
-
198
-
199
-    /**
200
-     *    set_definitions
201
-     *
202
-     * @return    void
203
-     * @throws EE_Error
204
-     */
205
-    public static function set_definitions()
206
-    {
207
-        if (defined('SPCO_BASE_PATH')) {
208
-            return;
209
-        }
210
-        define(
211
-            'SPCO_BASE_PATH',
212
-            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
213
-        );
214
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
215
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
216
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
217
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
218
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
219
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
220
-        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
221
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
222
-            EED_Single_Page_Checkout::getRegistrationExpirationNotice();
223
-    }
224
-
225
-
226
-    /**
227
-     * load_reg_steps
228
-     * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
229
-     *
230
-     * @throws EE_Error
231
-     */
232
-    public static function load_reg_steps()
233
-    {
234
-        static $reg_steps_loaded = false;
235
-        if ($reg_steps_loaded) {
236
-            return;
237
-        }
238
-        // filter list of reg_steps
239
-        $reg_steps_to_load = (array) apply_filters(
240
-            'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
241
-            EED_Single_Page_Checkout::get_reg_steps()
242
-        );
243
-        // sort by key (order)
244
-        ksort($reg_steps_to_load);
245
-        // loop through folders
246
-        foreach ($reg_steps_to_load as $order => $reg_step) {
247
-            // we need a
248
-            if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
249
-                // copy over to the reg_steps_array
250
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
251
-                // register custom key route for each reg step
252
-                // ie: step=>"slug" - this is the entire reason we load the reg steps array now
253
-                EED_Module::registerRoute(
254
-                    $reg_step['slug'],
255
-                    'EED_Single_Page_Checkout',
256
-                    'run',
257
-                    'step'
258
-                );
259
-                // add AJAX or other hooks
260
-                if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
261
-                    // setup autoloaders if necessary
262
-                    if (! class_exists($reg_step['class_name'])) {
263
-                        EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
264
-                            $reg_step['file_path'],
265
-                            true
266
-                        );
267
-                    }
268
-                    if (is_callable($reg_step['class_name'], 'set_hooks')) {
269
-                        call_user_func([$reg_step['class_name'], 'set_hooks']);
270
-                    }
271
-                }
272
-            }
273
-        }
274
-        $reg_steps_loaded = true;
275
-    }
276
-
277
-
278
-    /**
279
-     *    get_reg_steps
280
-     *
281
-     * @return    array
282
-     */
283
-    public static function get_reg_steps(): array
284
-    {
285
-        $reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
286
-        if (empty($reg_steps)) {
287
-            $reg_steps = [
288
-                10  => [
289
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
290
-                    'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
291
-                    'slug'       => 'attendee_information',
292
-                    'has_hooks'  => false,
293
-                ],
294
-                30  => [
295
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
296
-                    'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
297
-                    'slug'       => 'payment_options',
298
-                    'has_hooks'  => true,
299
-                ],
300
-                999 => [
301
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
302
-                    'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
303
-                    'slug'       => 'finalize_registration',
304
-                    'has_hooks'  => false,
305
-                ],
306
-            ];
307
-        }
308
-        return $reg_steps;
309
-    }
310
-
311
-
312
-    /**
313
-     * @return array|string
314
-     * @throws EE_Error
315
-     * @throws ReflectionException
316
-     */
317
-    public static function registration_checkout_for_admin()
318
-    {
319
-        $request = EED_Single_Page_Checkout::getRequest();
320
-        $request->setRequestParam('step', 'attendee_information');
321
-        $request->setRequestParam('action', 'display_spco_reg_step');
322
-        $request->setRequestParam('process_form_submission', false);
323
-        EED_Single_Page_Checkout::instance()->_initialize();
324
-        EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
325
-        return EED_Single_Page_Checkout::getResponse()->getOutput();
326
-    }
327
-
328
-
329
-    /**
330
-     * @return EE_Transaction|null
331
-     * @throws EE_Error
332
-     * @throws ReflectionException
333
-     */
334
-    public static function process_registration_from_admin(): ?EE_Transaction
335
-    {
336
-        $request = EED_Single_Page_Checkout::getRequest();
337
-        $request->setRequestParam('step', 'attendee_information');
338
-        $request->setRequestParam('action', 'process_reg_step');
339
-        $request->setRequestParam('process_form_submission', true);
340
-        EED_Single_Page_Checkout::instance()->_initialize();
341
-        if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
342
-            $final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
343
-            if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
344
-                EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
345
-                if ($final_reg_step->process_reg_step()) {
346
-                    $final_reg_step->set_completed();
347
-                    EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
348
-                    return EED_Single_Page_Checkout::instance()->checkout->transaction;
349
-                }
350
-            }
351
-        }
352
-        return null;
353
-    }
354
-
355
-
356
-    /**
357
-     *    run
358
-     *
359
-     * @param WP_Query|null $WP_Query
360
-     * @return    void
361
-     */
362
-    public function run($WP_Query)
363
-    {
364
-        if (
365
-            $WP_Query instanceof WP_Query
366
-            && $WP_Query->is_main_query()
367
-            && apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
368
-            && $this->_is_reg_checkout()
369
-        ) {
370
-            $this->_initialize();
371
-        }
372
-    }
373
-
374
-
375
-    /**
376
-     * determines whether current url matches reg page url
377
-     *
378
-     * @return bool
379
-     */
380
-    protected function _is_reg_checkout(): bool
381
-    {
382
-        // get current permalink for reg page without any extra query args
383
-        $reg_page_url = get_permalink(EE_Config::instance()->core->reg_page_id);
384
-        // get request URI for current request, but without the scheme or host
385
-        $current_request_uri = EEH_URL::filter_input_server_url();
386
-        $current_request_uri = html_entity_decode($current_request_uri);
387
-        // get array of query args from the current request URI
388
-        $query_args = EEH_URL::get_query_string($current_request_uri);
389
-        // grab page id if it is set
390
-        $page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
391
-        // and remove the page id from the query args (we will re-add it later)
392
-        unset($query_args['page_id']);
393
-        // now strip all query args from current request URI
394
-        $current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
395
-        // and re-add the page id if it was set
396
-        if ($page_id) {
397
-            $current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
398
-        }
399
-        // remove slashes and ?
400
-        $current_request_uri = trim($current_request_uri, '?/');
401
-        // is current request URI part of the known full reg page URL ?
402
-        return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
403
-    }
404
-
405
-
406
-    /**
407
-     * @param WP_Query $wp_query
408
-     * @return    void
409
-     * @throws EE_Error
410
-     * @throws ReflectionException
411
-     */
412
-    public static function init(WP_Query $wp_query)
413
-    {
414
-        EED_Single_Page_Checkout::instance()->run($wp_query);
415
-    }
416
-
417
-
418
-    /**
419
-     * @return void
420
-     */
421
-    private function _initialize()
422
-    {
423
-        // ensure SPCO doesn't run twice
424
-        if (EED_Single_Page_Checkout::$_initialized) {
425
-            return;
426
-        }
427
-        try {
428
-            $this->request = EED_Single_Page_Checkout::getRequest();
429
-            EED_Single_Page_Checkout::load_reg_steps();
430
-            $this->_verify_session();
431
-            // set up the EE_Checkout object
432
-            $this->checkout = $this->_initialize_checkout();
433
-            // filter checkout
434
-            $this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
435
-            // get the $_GET
436
-            $this->_get_request_vars();
437
-            if ($this->_block_bots()) {
438
-                return;
439
-            }
440
-            // filter continue_reg
441
-            $this->checkout->continue_reg = apply_filters(
442
-                'FHEE__EED_Single_Page_Checkout__init___continue_reg',
443
-                true,
444
-                $this->checkout
445
-            );
446
-            // load the reg steps array
447
-            if (! $this->_load_and_instantiate_reg_steps()) {
448
-                EED_Single_Page_Checkout::$_initialized = true;
449
-                return;
450
-            }
451
-            // set the current step
452
-            $this->checkout->set_current_step($this->checkout->step);
453
-            // and the next step
454
-            $this->checkout->set_next_step();
455
-            // verify that everything has been set up correctly
456
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
457
-                EED_Single_Page_Checkout::$_initialized = true;
458
-                return;
459
-            }
460
-            do_action('AHEE__Single_Page_Checkout___initialize__after_final_verifications', $this->checkout);
461
-            // lock the transaction
462
-            $this->checkout->transaction->lock();
463
-            // make sure all of our cached objects are added to their respective model entity mappers
464
-            $this->checkout->refresh_all_entities();
465
-            // set amount owing
466
-            $this->checkout->amount_owing = $this->checkout->transaction->remaining();
467
-            // initialize each reg step, which gives them the chance to potentially alter the process
468
-            $this->_initialize_reg_steps();
469
-            // DEBUG LOG
470
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
471
-            // get reg form
472
-            if (! $this->_check_form_submission()) {
473
-                EED_Single_Page_Checkout::$_initialized = true;
474
-                return;
475
-            }
476
-            // checkout the action!!!
477
-            $this->_process_form_action();
478
-            // add some style and make it dance
479
-            $this->add_styles_and_scripts($this);
480
-            // kk... SPCO has successfully run
481
-            EED_Single_Page_Checkout::$_initialized = true;
482
-            // set no cache headers and constants
483
-            EE_System::do_not_cache();
484
-            // add anchor
485
-            add_action('loop_start', [$this, 'set_checkout_anchor'], 1);
486
-            // remove transaction lock
487
-            add_action('shutdown', [$this, 'unlock_transaction'], 1);
488
-        } catch (Exception $e) {
489
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
490
-        }
491
-    }
492
-
493
-
494
-    /**
495
-     * checks that the session is valid and not expired
496
-     *
497
-     * @throws EE_Error
498
-     * @throws ReflectionException
499
-     */
500
-    private function _verify_session()
501
-    {
502
-        if (! $this->session instanceof EE_Session) {
503
-            $this->session = LoaderFactory::getShared(EE_Session::class);
504
-            if (! $this->session instanceof EE_Session) {
505
-                throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
506
-            }
507
-        }
508
-        $clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
509
-        // is session still valid ?
510
-        if (
511
-            $clear_session_requested
512
-            || (
513
-                $this->session->expired()
514
-                && $this->request->getRequestParam('e_reg_url_link') === ''
515
-            )
516
-        ) {
517
-            $this->checkout = new EE_Checkout();
518
-            $this->session->clear_session(__CLASS__, __FUNCTION__);
519
-            if (! $clear_session_requested) {
520
-                EE_Error::add_attention(
521
-                    EE_Registry::$i18n_js_strings['registration_expiration_notice'],
522
-                    __FILE__,
523
-                    __FUNCTION__,
524
-                    __LINE__
525
-                );
526
-            }
527
-        }
528
-    }
529
-
530
-
531
-    /**
532
-     * loads and instantiates EE_Checkout
533
-     *
534
-     * @return EE_Checkout
535
-     * @throws EE_Error
536
-     * @throws ReflectionException
537
-     */
538
-    private function _initialize_checkout(): EE_Checkout
539
-    {
540
-        // look in session for existing checkout
541
-        /** @type EE_Checkout $checkout */
542
-        $checkout = $this->session->checkout();
543
-        // verify
544
-        if (! $checkout instanceof EE_Checkout) {
545
-            // instantiate EE_Checkout object for handling the properties of the current checkout process
546
-            $checkout = EE_Registry::instance()->load_file(
547
-                SPCO_INC_PATH,
548
-                'EE_Checkout',
549
-                'class',
550
-                [],
551
-                false
552
-            );
553
-        } else {
554
-            if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
555
-                $this->unlock_transaction();
556
-                wp_safe_redirect($checkout->redirect_url);
557
-                exit();
558
-            }
559
-        }
560
-        $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
561
-        // verify again
562
-        if (! $checkout instanceof EE_Checkout) {
563
-            throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
564
-        }
565
-        // reset anything that needs a clean slate for each request
566
-        $checkout->reset_for_current_request();
567
-        return $checkout;
568
-    }
569
-
570
-
571
-    /**
572
-     * @return void
573
-     */
574
-    private function _get_request_vars()
575
-    {
576
-        // make sure this request is marked as belonging to EE
577
-        /** @var CurrentPage $current_page */
578
-        $current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class);
579
-        $current_page->setEspressoPage(true);
580
-        // which step is being requested ?
581
-        $this->checkout->step = $this->request->getRequestParam('step', $this->_get_first_step());
582
-        // which step is being edited ?
583
-        $this->checkout->edit_step = $this->request->getRequestParam('edit_step');
584
-        // and what we're doing on the current step
585
-        $this->checkout->action = $this->request->getRequestParam('action', 'display_spco_reg_step');
586
-        // timestamp
587
-        $this->checkout->uts = $this->request->getRequestParam('uts', 0, 'int');
588
-        // returning to edit ?
589
-        $this->checkout->reg_url_link = $this->request->getRequestParam('e_reg_url_link');
590
-        // add reg url link to registration query params
591
-        if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
592
-            $this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
593
-        }
594
-        // or some other kind of revisit ?
595
-        $this->checkout->revisit = $this->request->getRequestParam('revisit', false, 'bool');
596
-        // and whether to generate a reg form for this request
597
-        $this->checkout->generate_reg_form = $this->request->getRequestParam('generate_reg_form', true, 'bool');
598
-        // and whether to process a reg form submission for this request
599
-        $this->checkout->process_form_submission = $this->request->getRequestParam(
600
-            'process_form_submission',
601
-            $this->checkout->action === 'process_reg_step',
602
-            'bool'
603
-        );
604
-        $this->checkout->process_form_submission = filter_var(
605
-            $this->checkout->action !== 'display_spco_reg_step'
606
-                ? $this->checkout->process_form_submission
607
-                : false,
608
-            FILTER_VALIDATE_BOOLEAN
609
-        );
610
-        $this->_display_request_vars();
611
-    }
612
-
613
-
614
-    /**
615
-     * @return void
616
-     */
617
-    protected function _display_request_vars()
618
-    {
619
-        if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
620
-            return;
621
-        }
622
-        EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
623
-        EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
624
-        EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
625
-        EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
626
-        EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
627
-        EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
628
-        EEH_Debug_Tools::printr(
629
-            $this->checkout->generate_reg_form,
630
-            '$this->checkout->generate_reg_form',
631
-            __FILE__,
632
-            __LINE__
633
-        );
634
-        EEH_Debug_Tools::printr(
635
-            $this->checkout->process_form_submission,
636
-            '$this->checkout->process_form_submission',
637
-            __FILE__,
638
-            __LINE__
639
-        );
640
-    }
641
-
642
-
643
-    /**
644
-     * _block_bots
645
-     * checks that the incoming request has either of the following set:
646
-     *  a UTS (unix timestamp) which indicates that the request was redirected from the Ticket Selector
647
-     *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
648
-     * so if you're not coming from the Ticket Selector nor returning for a valid IP...
649
-     * then where you coming from man?
650
-     *
651
-     * @return boolean
652
-     */
653
-    private function _block_bots(): bool
654
-    {
655
-        return EED_Invalid_Checkout_Access::getInvalidCheckoutAccess()->checkoutAccessIsInvalid($this->checkout);
656
-    }
657
-
658
-
659
-    /**
660
-     *  gets slug for first step in $_reg_steps_array
661
-     *
662
-     * @return string
663
-     */
664
-    private function _get_first_step(): string
665
-    {
666
-        $first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
667
-        return $first_step['slug'] ?? 'attendee_information';
668
-    }
669
-
670
-
671
-    /**
672
-     * instantiates each reg step based on the loaded reg_steps array
673
-     *
674
-     * @return bool
675
-     * @throws EE_Error
676
-     * @throws InvalidArgumentException
677
-     * @throws InvalidDataTypeException
678
-     * @throws InvalidInterfaceException
679
-     * @throws ReflectionException
680
-     */
681
-    private function _load_and_instantiate_reg_steps(): bool
682
-    {
683
-        do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
684
-        // have reg_steps already been instantiated ?
685
-        if (
686
-            empty($this->checkout->reg_steps)
687
-            || apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
688
-        ) {
689
-            // if not, then loop through raw reg steps array
690
-            foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
691
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
692
-                    return false;
693
-                }
694
-            }
695
-            if (isset($this->checkout->reg_steps['registration_confirmation'])) {
696
-                // skip the registration_confirmation page ?
697
-                // just remove it from the reg steps array
698
-                $this->checkout->remove_reg_step('registration_confirmation', false);
699
-            }
700
-            // filter the array for good luck
701
-            $this->checkout->reg_steps = apply_filters(
702
-                'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
703
-                $this->checkout->reg_steps
704
-            );
705
-            // finally re-sort based on the reg step class order properties
706
-            $this->checkout->sort_reg_steps();
707
-        } else {
708
-            foreach ($this->checkout->reg_steps as $reg_step) {
709
-                // set all current step stati to FALSE
710
-                $reg_step->set_is_current_step(false);
711
-            }
712
-        }
713
-        if (empty($this->checkout->reg_steps)) {
714
-            EE_Error::add_error(
715
-                esc_html__('No Reg Steps were loaded..', 'event_espresso'),
716
-                __FILE__,
717
-                __FUNCTION__,
718
-                __LINE__
719
-            );
720
-            return false;
721
-        }
722
-        // make reg step details available to JS
723
-        $this->checkout->set_reg_step_JSON_info();
724
-        return true;
725
-    }
726
-
727
-
728
-    /**
729
-     * @param array $reg_step
730
-     * @param int   $order
731
-     * @return bool
732
-     * @throws EE_Error
733
-     * @throws ReflectionException
734
-     */
735
-    private function _load_and_instantiate_reg_step(array $reg_step = [], int $order = 0): bool
736
-    {
737
-        // we need a file_path, class_name, and slug to add a reg step
738
-        if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
739
-            // if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
740
-            if (
741
-                $this->checkout->reg_url_link
742
-                && $this->checkout->step !== $reg_step['slug']
743
-                && $reg_step['slug'] !== 'finalize_registration'
744
-                // normally at this point we would NOT load the reg step, but this filter can change that
745
-                && apply_filters(
746
-                    'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
747
-                    true,
748
-                    $reg_step,
749
-                    $this->checkout
750
-                )
751
-            ) {
752
-                return true;
753
-            }
754
-
755
-            // instantiate step class using file path and class name
756
-            $reg_step_obj = EE_Registry::instance()->load_file(
757
-                $reg_step['file_path'],
758
-                $reg_step['class_name'],
759
-                'class',
760
-                [$this->checkout],
761
-                false
762
-            );
763
-            // did we get the goods ?
764
-            if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
765
-                // set reg step order based on config
766
-                $reg_step_obj->set_order($order);
767
-                // add instantiated reg step object to the master reg steps array
768
-                $this->checkout->add_reg_step($reg_step_obj);
769
-            } else {
770
-                EE_Error::add_error(
771
-                    esc_html__('The current step could not be set.', 'event_espresso'),
772
-                    __FILE__,
773
-                    __FUNCTION__,
774
-                    __LINE__
775
-                );
776
-                return false;
777
-            }
778
-        } else {
779
-            if (WP_DEBUG) {
780
-                EE_Error::add_error(
781
-                    sprintf(
782
-                        esc_html__(
783
-                            'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
784
-                            'event_espresso'
785
-                        ),
786
-                        $reg_step['file_path'] ?? '',
787
-                        $reg_step['class_name'] ?? '',
788
-                        $reg_step['slug'] ?? '',
789
-                        '<ul>',
790
-                        '<li>',
791
-                        '</li>',
792
-                        '</ul>'
793
-                    ),
794
-                    __FILE__,
795
-                    __FUNCTION__,
796
-                    __LINE__
797
-                );
798
-            }
799
-            return false;
800
-        }
801
-        return true;
802
-    }
803
-
804
-
805
-    /**
806
-     * @return bool
807
-     * @throws EE_Error
808
-     * @throws ReflectionException
809
-     */
810
-    private function _verify_transaction_and_get_registrations(): bool
811
-    {
812
-        // was there already a valid transaction in the checkout from the session ?
813
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
814
-            // get transaction from db or session
815
-            $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
816
-                ? $this->_get_transaction_and_cart_for_previous_visit()
817
-                : $this->_get_cart_for_current_session_and_setup_new_transaction();
818
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
819
-                EE_Error::add_error(
820
-                    esc_html__(
821
-                        'Your Registration and Transaction information could not be retrieved from the db.',
822
-                        'event_espresso'
823
-                    ),
824
-                    __FILE__,
825
-                    __FUNCTION__,
826
-                    __LINE__
827
-                );
828
-                $this->checkout->transaction = EE_Transaction::new_instance();
829
-                // add some style and make it dance
830
-                $this->add_styles_and_scripts($this);
831
-                EED_Single_Page_Checkout::$_initialized = true;
832
-                return false;
833
-            }
834
-            // and the registrations for the transaction
835
-            $this->_get_registrations($this->checkout->transaction);
836
-        }
837
-        return true;
838
-    }
839
-
840
-
841
-    /**
842
-     * @return EE_Transaction|null
843
-     * @throws EE_Error
844
-     * @throws ReflectionException
845
-     */
846
-    private function _get_transaction_and_cart_for_previous_visit(): ?EE_Transaction
847
-    {
848
-        /** @var $TXN_model EEM_Transaction */
849
-        $TXN_model = EE_Registry::instance()->load_model('Transaction');
850
-        // because the reg_url_link is present in the request,
851
-        // this is a return visit to SPCO, so we'll get the transaction data from the db
852
-        $transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
853
-        // verify transaction
854
-        if ($transaction instanceof EE_Transaction) {
855
-            // and get the cart that was used for that transaction
856
-            $this->checkout->cart = $this->_get_cart_for_transaction($transaction);
857
-            return $transaction;
858
-        }
859
-        EE_Error::add_error(
860
-            esc_html__(
861
-                'Your Registration and Transaction information could not be retrieved from the db.',
862
-                'event_espresso'
863
-            ),
864
-            __FILE__,
865
-            __FUNCTION__,
866
-            __LINE__
867
-        );
868
-        return null;
869
-    }
870
-
871
-
872
-    /**
873
-     * @param EE_Transaction|null $transaction
874
-     * @return EE_Cart
875
-     * @throws EE_Error
876
-     * @throws ReflectionException
877
-     */
878
-    private function _get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
879
-    {
880
-        return $this->checkout->get_cart_for_transaction($transaction);
881
-    }
882
-
883
-
884
-    /**
885
-     * @param EE_Transaction|null $transaction
886
-     * @return EE_Cart
887
-     * @throws EE_Error
888
-     * @throws ReflectionException
889
-     */
890
-    public function get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
891
-    {
892
-        return $this->checkout->get_cart_for_transaction($transaction);
893
-    }
894
-
895
-
896
-    /**
897
-     * generates a new EE_Transaction object and adds it to the $_transaction property.
898
-     *
899
-     * @return EE_Transaction|null
900
-     * @throws EE_Error
901
-     * @throws ReflectionException
902
-     */
903
-    private function _get_cart_for_current_session_and_setup_new_transaction(): ?EE_Transaction
904
-    {
905
-        //  if there's no transaction, then this is the FIRST visit to SPCO
906
-        // so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
907
-        $this->checkout->cart = $this->_get_cart_for_transaction(null);
908
-        // and then create a new transaction
909
-        $transaction = $this->_initialize_transaction();
910
-        // verify transaction
911
-        if ($transaction instanceof EE_Transaction) {
912
-            // and save TXN data to the cart
913
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
914
-        } else {
915
-            EE_Error::add_error(
916
-                esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
917
-                __FILE__,
918
-                __FUNCTION__,
919
-                __LINE__
920
-            );
921
-        }
922
-        return $transaction;
923
-    }
924
-
925
-
926
-    /**
927
-     * generates a new EE_Transaction object and adds it to the $_transaction property.
928
-     *
929
-     * @return EE_Transaction|null
930
-     */
931
-    private function _initialize_transaction(): ?EE_Transaction
932
-    {
933
-        try {
934
-            // ensure cart totals have been calculated
935
-            $this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
936
-            // grab the cart grand total
937
-            $cart_total = $this->checkout->cart->get_cart_grand_total();
938
-            // create new TXN
939
-            $transaction = EE_Transaction::new_instance(
940
-                [
941
-                    'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
942
-                    'TXN_total'     => max($cart_total, 0),
943
-                    'TXN_paid'      => 0,
944
-                    'STS_ID'        => EEM_Transaction::failed_status_code,
945
-                ]
946
-            );
947
-            // save it so that we have an ID for other objects to use
948
-            $transaction->save();
949
-            // set cron job for following up on TXNs after their session has expired
950
-            EE_Cron_Tasks::schedule_expired_transaction_check(
951
-                $this->session->expiration() + 1,
952
-                $transaction->ID()
953
-            );
954
-            return $transaction;
955
-        } catch (Exception $e) {
956
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
957
-        }
958
-        return null;
959
-    }
960
-
961
-
962
-    /**
963
-     * _get_registrations
964
-     *
965
-     * @param EE_Transaction $transaction
966
-     * @return void
967
-     * @throws EE_Error
968
-     * @throws ReflectionException
969
-     */
970
-    private function _get_registrations(EE_Transaction $transaction)
971
-    {
972
-        // first step: grab the registrants  { : o
973
-        $registrations                      = $transaction->registrations($this->checkout->reg_cache_where_params);
974
-        $this->checkout->total_ticket_count = count($registrations);
975
-        // verify registrations have been set
976
-        if (empty($registrations)) {
977
-            // if no cached registrations, then check the db
978
-            $registrations = $transaction->registrations($this->checkout->reg_cache_where_params);
979
-            // still nothing ? well as long as this isn't a revisit
980
-            if (empty($registrations) && ! $this->checkout->revisit) {
981
-                // generate new registrations from scratch
982
-                $registrations = $this->_initialize_registrations($transaction);
983
-            }
984
-        }
985
-        // sort by their original registration order
986
-        usort($registrations, ['EED_Single_Page_Checkout', 'sort_registrations_by_REG_count']);
987
-        // then loop thru the array
988
-        foreach ($registrations as $registration) {
989
-            // verify each registration
990
-            if ($registration instanceof EE_Registration) {
991
-                // we display all attendee info for the primary registrant
992
-                if (
993
-                    $this->checkout->reg_url_link === $registration->reg_url_link()
994
-                    && $registration->is_primary_registrant()
995
-                ) {
996
-                    $this->checkout->primary_revisit = true;
997
-                    break;
998
-                }
999
-                if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1000
-                    // but hide info if it doesn't belong to you
1001
-                    $transaction->clear_cache('Registration', $registration->ID());
1002
-                    $this->checkout->total_ticket_count--;
1003
-                }
1004
-                $this->checkout->set_reg_status_updated($registration->ID(), false);
1005
-            }
1006
-        }
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1012
-     *
1013
-     * @param EE_Transaction $transaction
1014
-     * @return array
1015
-     * @throws EE_Error
1016
-     * @throws ReflectionException
1017
-     */
1018
-    private function _initialize_registrations(EE_Transaction $transaction): array
1019
-    {
1020
-        $att_nmbr      = 0;
1021
-        $registrations = [];
1022
-        /** @type EE_Registration_Processor $registration_processor */
1023
-        $registration_processor             = EE_Registry::instance()->load_class('Registration_Processor');
1024
-        $this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1025
-        // now let's add the cart items to the $transaction
1026
-        foreach ($this->checkout->cart->get_tickets() as $line_item) {
1027
-            // do the following for each ticket of this type they selected
1028
-            for ($x = 1; $x <= $line_item->quantity(); $x++) {
1029
-                $att_nmbr++;
1030
-                /** @var CreateRegistrationCommand $CreateRegistrationCommand */
1031
-                $CreateRegistrationCommand = EE_Registry::instance()->create(
1032
-                    CreateRegistrationCommand::class,
1033
-                    [
1034
-                        $transaction,
1035
-                        $line_item,
1036
-                        $att_nmbr,
1037
-                        $this->checkout->total_ticket_count,
1038
-                    ]
1039
-                );
1040
-                // override capabilities for frontend registrations
1041
-                if ($this->request->isFrontend()) {
1042
-                    $CreateRegistrationCommand->setCapCheck(
1043
-                        new PublicCapabilities('', 'create_new_registration')
1044
-                    );
1045
-                }
1046
-                $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1047
-                if (! $registration instanceof EE_Registration) {
1048
-                    throw new InvalidEntityException($registration, 'EE_Registration');
1049
-                }
1050
-                $registrations[ $registration->ID() ] = $registration;
1051
-            }
1052
-        }
1053
-        $registration_processor->fix_reg_final_price_rounding_issue($transaction);
1054
-        return $registrations;
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * @param EE_Registration $reg_A
1060
-     * @param EE_Registration $reg_B
1061
-     * @return int
1062
-     * @throws EE_Error
1063
-     * @throws ReflectionException
1064
-     */
1065
-    public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B): int
1066
-    {
1067
-        // this shouldn't ever happen within the same TXN, but oh well
1068
-        if ($reg_A->count() === $reg_B->count()) {
1069
-            return 0;
1070
-        }
1071
-        return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * just makes sure that everything is set up correctly before proceeding
1077
-     *
1078
-     * @return bool
1079
-     * @throws EE_Error
1080
-     * @throws ReflectionException
1081
-     */
1082
-    private function _final_verifications(): bool
1083
-    {
1084
-        // filter checkout
1085
-        $this->checkout = apply_filters(
1086
-            'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1087
-            $this->checkout
1088
-        );
1089
-        // verify that current step is still set correctly
1090
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1091
-            EE_Error::add_error(
1092
-                esc_html__(
1093
-                    'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1094
-                    'event_espresso'
1095
-                ),
1096
-                __FILE__,
1097
-                __FUNCTION__,
1098
-                __LINE__
1099
-            );
1100
-            return false;
1101
-        }
1102
-        // if returning to SPCO, then verify that primary registrant is set
1103
-        if (! empty($this->checkout->reg_url_link)) {
1104
-            $valid_registrant = $this->checkout->transaction->primary_registration();
1105
-            if (! $valid_registrant instanceof EE_Registration) {
1106
-                EE_Error::add_error(
1107
-                    esc_html__(
1108
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1109
-                        'event_espresso'
1110
-                    ),
1111
-                    __FILE__,
1112
-                    __FUNCTION__,
1113
-                    __LINE__
1114
-                );
1115
-                return false;
1116
-            }
1117
-            $valid_registrant = null;
1118
-            foreach (
1119
-                $this->checkout->transaction->registrations(
1120
-                    $this->checkout->reg_cache_where_params
1121
-                ) as $registration
1122
-            ) {
1123
-                if (
1124
-                    $registration instanceof EE_Registration
1125
-                    && $registration->reg_url_link() === $this->checkout->reg_url_link
1126
-                ) {
1127
-                    $valid_registrant = $registration;
1128
-                }
1129
-            }
1130
-            if (! $valid_registrant instanceof EE_Registration) {
1131
-                // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1132
-                if (EED_Single_Page_Checkout::$_checkout_verified) {
1133
-                    // clear the session, mark the checkout as unverified, and try again
1134
-                    $this->session->clear_session(__CLASS__, __FUNCTION__);
1135
-                    EED_Single_Page_Checkout::$_initialized       = false;
1136
-                    EED_Single_Page_Checkout::$_checkout_verified = false;
1137
-                    $this->_initialize();
1138
-                    EE_Error::reset_notices();
1139
-                    return false;
1140
-                }
1141
-                EE_Error::add_error(
1142
-                    esc_html__(
1143
-                        'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1144
-                        'event_espresso'
1145
-                    ),
1146
-                    __FILE__,
1147
-                    __FUNCTION__,
1148
-                    __LINE__
1149
-                );
1150
-                return false;
1151
-            }
1152
-        }
1153
-        // now that things have been kinda sufficiently verified,
1154
-        // let's add the checkout to the session so that it's available to other systems
1155
-        $this->session->set_checkout($this->checkout);
1156
-        return true;
1157
-    }
1158
-
1159
-
1160
-    /**
1161
-     * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1162
-     * then loops thru all the active reg steps and calls the initialize_reg_step() method
1163
-     *
1164
-     * @param bool $reinitializing
1165
-     * @throws EE_Error
1166
-     * @throws ReflectionException
1167
-     */
1168
-    private function _initialize_reg_steps(bool $reinitializing = false)
1169
-    {
1170
-        $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1171
-        // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1172
-        foreach ($this->checkout->reg_steps as $reg_step) {
1173
-            if (! $reg_step->initialize_reg_step()) {
1174
-                // if not initialized then maybe this step is being removed...
1175
-                if (! $reinitializing && $reg_step->is_current_step()) {
1176
-                    // if it was the current step, then we need to start over here
1177
-                    $this->_initialize_reg_steps(true);
1178
-                    return;
1179
-                }
1180
-                continue;
1181
-            }
1182
-            // add css and JS for current step
1183
-            $this->add_styles_and_scripts($reg_step);
1184
-            if ($reg_step->is_current_step()) {
1185
-                // the text that appears on the reg step form submit button
1186
-                $reg_step->set_submit_button_text();
1187
-            }
1188
-        }
1189
-        // dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1190
-        do_action(
1191
-            "AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1192
-            $this->checkout->current_step
1193
-        );
1194
-        $this->checkout->json_response->set_return_data(
1195
-            [
1196
-                'action'        => $this->checkout->action,
1197
-                'admin_request' => $this->checkout->admin_request,
1198
-                'current_step'  => $this->checkout->current_step->slug(),
1199
-                'revisit'       => $this->checkout->revisit,
1200
-            ]
1201
-        );
1202
-    }
1203
-
1204
-
1205
-    /**
1206
-     * @return boolean
1207
-     * @throws EE_Error
1208
-     * @throws ReflectionException
1209
-     */
1210
-    private function _check_form_submission(): bool
1211
-    {
1212
-        // does this request require the reg form to be generated ?
1213
-        if ($this->checkout->generate_reg_form) {
1214
-            // ever heard that song by Blue Rodeo ?
1215
-            try {
1216
-                $this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1217
-                // if not displaying a form, then check for form submission
1218
-                if (
1219
-                    $this->checkout->process_form_submission
1220
-                    && $this->checkout->current_step->reg_form->was_submitted()
1221
-                ) {
1222
-                    // clear out any old data in case this step is being run again
1223
-                    $this->checkout->current_step->set_valid_data([]);
1224
-                    // capture submitted form data
1225
-                    $request_data = $this->request->requestParams();
1226
-                    $this->checkout->current_step->reg_form->receive_form_submission(
1227
-                        (array) apply_filters(
1228
-                            'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1229
-                            $request_data,
1230
-                            $this->checkout
1231
-                        )
1232
-                    );
1233
-                    // validate submitted form data
1234
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1235
-                        // thou shall not pass !!!
1236
-                        $this->checkout->continue_reg = false;
1237
-                        // any form validation errors?
1238
-                        if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1239
-                            EE_Error::add_error(
1240
-                                $this->checkout->current_step->reg_form->submission_error_message(),
1241
-                                __FILE__,
1242
-                                __FUNCTION__,
1243
-                                __LINE__
1244
-                            );
1245
-                        }
1246
-                        // well not really... what will happen is
1247
-                        // we'll just get redirected back to redo the current step
1248
-                        $this->go_to_next_step();
1249
-                        return false;
1250
-                    }
1251
-                }
1252
-            } catch (EE_Error $e) {
1253
-                $e->get_error();
1254
-            }
1255
-        }
1256
-        return true;
1257
-    }
1258
-
1259
-
1260
-    /**
1261
-     * @return void
1262
-     * @throws EE_Error
1263
-     * @throws ReflectionException
1264
-     */
1265
-    private function _process_form_action()
1266
-    {
1267
-        // what cha wanna do?
1268
-        switch ($this->checkout->action) {
1269
-            // AJAX next step reg form
1270
-            case 'display_spco_reg_step':
1271
-                $this->checkout->redirect = false;
1272
-                if ($this->request->isAjax()) {
1273
-                    $this->checkout->json_response->set_reg_step_html(
1274
-                        $this->checkout->current_step->display_reg_form()
1275
-                    );
1276
-                }
1277
-                break;
1278
-            default:
1279
-                // meh... do one of those other steps first
1280
-                if (
1281
-                    ! empty($this->checkout->action)
1282
-                    && is_callable([$this->checkout->current_step, $this->checkout->action])
1283
-                ) {
1284
-                    // dynamically creates hook point like:
1285
-                    //   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1286
-                    do_action(
1287
-                        "AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1288
-                        $this->checkout->current_step
1289
-                    );
1290
-                    $process_reg_step = apply_filters(
1291
-                        "AHEE__Single_Page_Checkout__process_reg_step__{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1292
-                        true,
1293
-                        $this->checkout->current_step,
1294
-                        $this
1295
-                    );
1296
-                    // call action on current step
1297
-                    if ($process_reg_step && call_user_func([$this->checkout->current_step, $this->checkout->action])) {
1298
-                        // good registrant, you get to proceed
1299
-                        if (
1300
-                            $this->checkout->current_step->success_message() !== ''
1301
-                            && apply_filters(
1302
-                                'FHEE__Single_Page_Checkout___process_form_action__display_success',
1303
-                                false
1304
-                            )
1305
-                        ) {
1306
-                            EE_Error::add_success(
1307
-                                $this->checkout->current_step->success_message()
1308
-                                . '<br />' . $this->checkout->next_step->_instructions()
1309
-                            );
1310
-                        }
1311
-                        // pack it up, pack it in...
1312
-                        $this->_setup_redirect();
1313
-                    }
1314
-                    // dynamically creates hook point like:
1315
-                    //  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1316
-                    do_action(
1317
-                        "AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1318
-                        $this->checkout->current_step
1319
-                    );
1320
-                } else {
1321
-                    EE_Error::add_error(
1322
-                        sprintf(
1323
-                            esc_html__(
1324
-                                'The requested form action "%s" does not exist for the current "%s" registration step.',
1325
-                                'event_espresso'
1326
-                            ),
1327
-                            $this->checkout->action,
1328
-                            $this->checkout->current_step->name()
1329
-                        ),
1330
-                        __FILE__,
1331
-                        __FUNCTION__,
1332
-                        __LINE__
1333
-                    );
1334
-                }
1335
-            // end default
1336
-        }
1337
-        // store our progress so far
1338
-        $this->checkout->stash_transaction_and_checkout();
1339
-        // advance to the next step! If you pass GO, collect $200
1340
-        $this->go_to_next_step();
1341
-    }
1342
-
1343
-
1344
-    /**
1345
-     * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target an object with the method `translate_js_strings` and
1346
-     *                                                          `enqueue_styles_and_scripts`.
1347
-     * @return void
1348
-     */
1349
-    public function add_styles_and_scripts($target)
1350
-    {
1351
-        // i18n
1352
-        $target->translate_js_strings();
1353
-        if ($this->checkout->admin_request) {
1354
-            add_action('admin_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1355
-        } else {
1356
-            add_action('wp_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1357
-        }
1358
-    }
1359
-
1360
-
1361
-    /**
1362
-     * @return void
1363
-     */
1364
-    public function translate_js_strings()
1365
-    {
1366
-        EE_Registry::$i18n_js_strings['revisit']                        = $this->checkout->revisit;
1367
-        EE_Registry::$i18n_js_strings['e_reg_url_link']                 = $this->checkout->reg_url_link;
1368
-        EE_Registry::$i18n_js_strings['server_error']                   = esc_html__(
1369
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1370
-            'event_espresso'
1371
-        );
1372
-        EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1373
-            'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1374
-            'event_espresso'
1375
-        );
1376
-        EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1377
-            'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1378
-            'event_espresso'
1379
-        );
1380
-        EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1381
-            'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1382
-            'event_espresso'
1383
-        );
1384
-        EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1385
-            'This registration step could not be completed. Please refresh the page and try again.',
1386
-            'event_espresso'
1387
-        );
1388
-        EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1389
-            'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1390
-            'event_espresso'
1391
-        );
1392
-        EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1393
-            esc_html__(
1394
-                'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1395
-                'event_espresso'
1396
-            ),
1397
-            '<br/>',
1398
-            '<br/>'
1399
-        );
1400
-        EE_Registry::$i18n_js_strings['language']                       = get_bloginfo('language');
1401
-        EE_Registry::$i18n_js_strings['EESID']                          = $this->session->id();
1402
-        EE_Registry::$i18n_js_strings['currency']                       = EE_Registry::instance()->CFG->currency;
1403
-        EE_Registry::$i18n_js_strings['datepicker_yearRange']           = '-150:+20';
1404
-        EE_Registry::$i18n_js_strings['timer_years']                    = esc_html__('years', 'event_espresso');
1405
-        EE_Registry::$i18n_js_strings['timer_months']                   = esc_html__('months', 'event_espresso');
1406
-        EE_Registry::$i18n_js_strings['timer_weeks']                    = esc_html__('weeks', 'event_espresso');
1407
-        EE_Registry::$i18n_js_strings['timer_days']                     = esc_html__('days', 'event_espresso');
1408
-        EE_Registry::$i18n_js_strings['timer_hours']                    = esc_html__('hours', 'event_espresso');
1409
-        EE_Registry::$i18n_js_strings['timer_minutes']                  = esc_html__('minutes', 'event_espresso');
1410
-        EE_Registry::$i18n_js_strings['timer_seconds']                  = esc_html__('seconds', 'event_espresso');
1411
-        EE_Registry::$i18n_js_strings['timer_year']                     = esc_html__('year', 'event_espresso');
1412
-        EE_Registry::$i18n_js_strings['timer_month']                    = esc_html__('month', 'event_espresso');
1413
-        EE_Registry::$i18n_js_strings['timer_week']                     = esc_html__('week', 'event_espresso');
1414
-        EE_Registry::$i18n_js_strings['timer_day']                      = esc_html__('day', 'event_espresso');
1415
-        EE_Registry::$i18n_js_strings['timer_hour']                     = esc_html__('hour', 'event_espresso');
1416
-        EE_Registry::$i18n_js_strings['timer_minute']                   = esc_html__('minute', 'event_espresso');
1417
-        EE_Registry::$i18n_js_strings['timer_second']                   = esc_html__('second', 'event_espresso');
1418
-        EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
1419
-            EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1420
-        EE_Registry::$i18n_js_strings['ajax_submit']                    = apply_filters(
1421
-            'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1422
-            true
1423
-        );
1424
-        EE_Registry::$i18n_js_strings['session_extension']              = absint(
1425
-            apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1426
-        );
1427
-        EE_Registry::$i18n_js_strings['session_expiration']    = $this->session->expiration();
1428
-        EE_Registry::$i18n_js_strings['use_session_countdown'] = EE_Registry::instance()->CFG->registration->useSessionCountdown();
1429
-        EE_Registry::$i18n_js_strings['no_copy_paste_email_confirm'] = esc_html__("We're sorry but copy and paste is disabled for email confirmation inputs. Please enter the email address manually.", 'event_espresso');
1430
-    }
1431
-
1432
-
1433
-    /**
1434
-     * @return void
1435
-     * @throws EE_Error
1436
-     */
1437
-    public function enqueue_styles_and_scripts()
1438
-    {
1439
-        // load css
1440
-        wp_register_style(
1441
-            'single_page_checkout',
1442
-            SPCO_CSS_URL . 'single_page_checkout.css',
1443
-            ['espresso_default'],
1444
-            EVENT_ESPRESSO_VERSION
1445
-        );
1446
-        wp_enqueue_style('single_page_checkout');
1447
-        // load JS
1448
-        wp_register_script(
1449
-            'single_page_checkout',
1450
-            SPCO_JS_URL . 'single_page_checkout.js',
1451
-            ['espresso_core', 'underscore', 'ee_form_section_validation'],
1452
-            EVENT_ESPRESSO_VERSION,
1453
-            true
1454
-        );
1455
-        if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1456
-            $this->checkout->registration_form->enqueue_js();
1457
-        }
1458
-        if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1459
-            $this->checkout->current_step->reg_form->enqueue_js();
1460
-        }
1461
-        wp_enqueue_script('single_page_checkout');
1462
-        /**
1463
-         * global action hook for enqueueing styles and scripts with
1464
-         * spco calls.
1465
-         */
1466
-        do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1467
-        /**
1468
-         * dynamic action hook for enqueueing styles and scripts with spco calls.
1469
-         * The hook will end up being something like:
1470
-         *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1471
-         */
1472
-        do_action(
1473
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1474
-            $this
1475
-        );
1476
-    }
1477
-
1478
-
1479
-    /**
1480
-     * display the Registration Single Page Checkout Form
1481
-     *
1482
-     * @return void
1483
-     * @throws EE_Error
1484
-     * @throws ReflectionException
1485
-     */
1486
-    private function _display_spco_reg_form()
1487
-    {
1488
-        // if registering via the admin, just display the reg form for the current step
1489
-        if ($this->checkout->admin_request) {
1490
-            EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->current_step->display_reg_form());
1491
-            return;
1492
-        }
1493
-
1494
-        // add powered by EE msg
1495
-        add_action('AHEE__SPCO__reg_form_footer', ['EED_Single_Page_Checkout', 'display_registration_footer']);
1496
-        $empty_cart = count(
1497
-                $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1498
-            ) < 1;
1499
-        EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1500
-
1501
-        /** @var FeatureFlags $feature */
1502
-        $feature = LoaderFactory::getShared(FeatureFlags::class);
1503
-
1504
-        $this->checkout->registration_form = $feature->allowed(FeatureFlag::USE_SPCO_FORM_REFACTOR)
1505
-            ? new SinglePageCheckoutForm($this->checkout, $empty_cart)
1506
-            : new LegacySpcoForm($this->checkout, $empty_cart, $this->session->expiration());
1507
-
1508
-        // load template and add to output sent that gets filtered into the_content()
1509
-        EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->registration_form->get_html());
1510
-
1511
-    }
1512
-
1513
-
1514
-    /**
1515
-     * @param $next_step
1516
-     * @return void
1517
-     */
1518
-    public function add_extra_finalize_registration_inputs($next_step)
1519
-    {
1520
-        if ($next_step === 'finalize_registration') {
1521
-            echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1522
-        }
1523
-    }
1524
-
1525
-
1526
-    /**
1527
-     * @return void
1528
-     */
1529
-    public static function display_registration_footer()
1530
-    {
1531
-        if (
1532
-            apply_filters(
1533
-                'FHEE__EE_Front__Controller__show_reg_footer',
1534
-                EE_Registry::instance()->CFG->admin->show_reg_footer
1535
-            )
1536
-        ) {
1537
-            add_filter(
1538
-                'FHEE__EEH_Template__powered_by_event_espresso__url',
1539
-                function ($url) {
1540
-                    return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1541
-                }
1542
-            );
1543
-            echo apply_filters(
1544
-                'FHEE__EE_Front_Controller__display_registration_footer',
1545
-                EEH_Template::powered_by_event_espresso(
1546
-                    '',
1547
-                    'espresso-registration-footer-dv',
1548
-                    ['utm_content' => 'registration_checkout']
1549
-                )
1550
-            );
1551
-        }
1552
-    }
1553
-
1554
-
1555
-    /**
1556
-     * @return void
1557
-     * @throws EE_Error
1558
-     * @throws ReflectionException
1559
-     */
1560
-    public function unlock_transaction()
1561
-    {
1562
-        if ($this->checkout instanceof EE_Checkout && $this->checkout->transaction instanceof EE_Transaction) {
1563
-            $this->checkout->transaction->unlock();
1564
-        }
1565
-    }
1566
-
1567
-
1568
-    /**
1569
-     * @return void
1570
-     */
1571
-    private function _setup_redirect()
1572
-    {
1573
-        if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1574
-            $this->checkout->redirect = true;
1575
-            if (empty($this->checkout->redirect_url)) {
1576
-                $this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1577
-            }
1578
-            $this->checkout->redirect_url = apply_filters(
1579
-                'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1580
-                $this->checkout->redirect_url,
1581
-                $this->checkout
1582
-            );
1583
-        }
1584
-    }
1585
-
1586
-
1587
-    /**
1588
-     * handle ajax message responses and redirects
1589
-     *
1590
-     * @return void
1591
-     * @throws EE_Error
1592
-     * @throws ReflectionException
1593
-     */
1594
-    public function go_to_next_step()
1595
-    {
1596
-        if ($this->request->isAjax()) {
1597
-            // capture contents of output buffer we started earlier in the request, and insert into JSON response
1598
-            $this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1599
-        }
1600
-        $this->unlock_transaction();
1601
-        // just return for these conditions
1602
-        if (
1603
-            $this->checkout->admin_request
1604
-            || $this->checkout->action === 'redirect_form'
1605
-            || $this->checkout->action === 'update_checkout'
1606
-        ) {
1607
-            return;
1608
-        }
1609
-        // AJAX response
1610
-        $this->_handle_json_response();
1611
-        // redirect to next step or the Thank-You page
1612
-        $this->_handle_html_redirects();
1613
-        // hmmm... must be something wrong, so let's just display the form again !
1614
-        $this->_display_spco_reg_form();
1615
-    }
1616
-
1617
-
1618
-    /**
1619
-     * @return void
1620
-     */
1621
-    protected function _handle_json_response()
1622
-    {
1623
-        // if this is an ajax request
1624
-        if ($this->request->isAjax()) {
1625
-            $this->checkout->json_response->set_registration_time_limit(
1626
-                $this->checkout->get_registration_time_limit()
1627
-            );
1628
-            $this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1629
-            /** @var EE_SPCO_JSON_Response $json_response */
1630
-            $json_response = apply_filters(
1631
-                'FHEE__EE_Single_Page_Checkout__JSON_response',
1632
-                $this->checkout->json_response
1633
-            );
1634
-            // just send the ajax
1635
-            $json_response->sendResponse();
1636
-        }
1637
-    }
1638
-
1639
-
1640
-    /**
1641
-     * @return void
1642
-     */
1643
-    protected function _handle_html_redirects()
1644
-    {
1645
-        // going somewhere ?
1646
-        if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1647
-            // store notices in a transient
1648
-            EE_Error::get_notices(false, true);
1649
-            wp_safe_redirect($this->checkout->redirect_url);
1650
-            exit();
1651
-        }
1652
-    }
1653
-
1654
-
1655
-    /**
1656
-     * @return void
1657
-     */
1658
-    public function set_checkout_anchor()
1659
-    {
1660
-        echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1661
-    }
1662
-
1663
-
1664
-    /**
1665
-     * @return string
1666
-     * @since 4.9.59.p
1667
-     */
1668
-    public static function getRegistrationExpirationNotice(): string
1669
-    {
1670
-        return sprintf(
1671
-            esc_html__(
1672
-                '%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1673
-                'event_espresso'
1674
-            ),
1675
-            '<h4 class="important-notice">',
1676
-            '</h4>',
1677
-            '<br />',
1678
-            '<p>',
1679
-            '<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" title="',
1680
-            '">',
1681
-            '</a>',
1682
-            '</p>'
1683
-        );
1684
-    }
27
+	/**
28
+	 * $_initialized - has the SPCO controller already been initialized ?
29
+	 */
30
+	private static bool $_initialized = false;
31
+
32
+
33
+	/**
34
+	 * $_checkout_verified - is the EE_Checkout verified as correct for this request ?
35
+	 */
36
+	private static bool $_checkout_verified = true;
37
+
38
+	/**
39
+	 * $_reg_steps_array - holds initial array of reg steps
40
+	 *
41
+	 * @var array $_reg_steps_array
42
+	 */
43
+	private static array $_reg_steps_array = [];
44
+
45
+	/**
46
+	 * $checkout - EE_Checkout object for handling the properties of the current checkout process
47
+	 */
48
+	public ?EE_Checkout $checkout = null;
49
+
50
+	protected ?RequestInterface $request = null;
51
+
52
+	public ?EE_Session $session = null;
53
+
54
+	private bool $debug = false;    //  true    false
55
+
56
+
57
+	/**
58
+	 * @return EED_Single_Page_Checkout|EED_Module
59
+	 * @throws EE_Error
60
+	 * @throws ReflectionException
61
+	 */
62
+	public static function instance()
63
+	{
64
+		add_filter('EED_Single_Page_Checkout__SPCO_active', '__return_true');
65
+		return parent::get_instance(__CLASS__);
66
+	}
67
+
68
+
69
+	/**
70
+	 * @return EE_CART
71
+	 */
72
+	public function cart(): EE_CART
73
+	{
74
+		return $this->checkout->cart;
75
+	}
76
+
77
+
78
+	/**
79
+	 * @return RequestInterface
80
+	 * @since   4.10.14.p
81
+	 */
82
+	public static function getRequest(): RequestInterface
83
+	{
84
+		return LoaderFactory::getLoader()->getShared(RequestInterface::class);
85
+	}
86
+
87
+
88
+	/**
89
+	 * @return EE_Transaction
90
+	 */
91
+	public function transaction(): EE_Transaction
92
+	{
93
+		return $this->checkout->transaction;
94
+	}
95
+
96
+
97
+	/**
98
+	 *    set_hooks - for hooking into EE Core, other modules, etc
99
+	 *
100
+	 * @return    void
101
+	 * @throws EE_Error
102
+	 */
103
+	public static function set_hooks()
104
+	{
105
+		EED_Single_Page_Checkout::set_definitions();
106
+	}
107
+
108
+
109
+	/**
110
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
111
+	 *
112
+	 * @return    void
113
+	 * @throws EE_Error
114
+	 */
115
+	public static function set_hooks_admin()
116
+	{
117
+		EED_Single_Page_Checkout::set_definitions();
118
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
119
+			return;
120
+		}
121
+		// going to start an output buffer in case anything gets accidentally output
122
+		// that might disrupt our JSON response
123
+		ob_start();
124
+		EED_Single_Page_Checkout::load_reg_steps();
125
+		// set ajax hooks
126
+		add_action('wp_ajax_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
127
+		add_action('wp_ajax_nopriv_process_reg_step', ['EED_Single_Page_Checkout', 'process_reg_step']);
128
+		add_action('wp_ajax_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
129
+		add_action('wp_ajax_nopriv_display_spco_reg_step', ['EED_Single_Page_Checkout', 'display_reg_step']);
130
+		add_action('wp_ajax_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
131
+		add_action('wp_ajax_nopriv_update_reg_step', ['EED_Single_Page_Checkout', 'update_reg_step']);
132
+	}
133
+
134
+
135
+	/**
136
+	 *    process ajax request
137
+	 *
138
+	 * @param string $ajax_action
139
+	 * @throws EE_Error
140
+	 * @throws ReflectionException
141
+	 */
142
+	public static function process_ajax_request(string $ajax_action)
143
+	{
144
+		$request = EED_Single_Page_Checkout::getRequest();
145
+		$request->setRequestParam('action', $ajax_action);
146
+		EED_Single_Page_Checkout::instance()->_initialize();
147
+	}
148
+
149
+
150
+	/**
151
+	 * ajax display registration step
152
+	 *
153
+	 * @throws EE_Error
154
+	 * @throws ReflectionException
155
+	 */
156
+	public static function display_reg_step()
157
+	{
158
+		EED_Single_Page_Checkout::process_ajax_request('display_spco_reg_step');
159
+	}
160
+
161
+
162
+	/**
163
+	 * ajax process registration step
164
+	 *
165
+	 * @throws EE_Error
166
+	 * @throws ReflectionException
167
+	 */
168
+	public static function process_reg_step()
169
+	{
170
+		EED_Single_Page_Checkout::process_ajax_request('process_reg_step');
171
+	}
172
+
173
+
174
+	/**
175
+	 * ajax process registration step
176
+	 *
177
+	 * @throws EE_Error
178
+	 * @throws ReflectionException
179
+	 */
180
+	public static function update_reg_step()
181
+	{
182
+		EED_Single_Page_Checkout::process_ajax_request('update_reg_step');
183
+	}
184
+
185
+
186
+	/**
187
+	 * update_checkout
188
+	 *
189
+	 * @return void
190
+	 * @throws ReflectionException
191
+	 * @throws EE_Error
192
+	 */
193
+	public static function update_checkout()
194
+	{
195
+		EED_Single_Page_Checkout::process_ajax_request('update_checkout');
196
+	}
197
+
198
+
199
+	/**
200
+	 *    set_definitions
201
+	 *
202
+	 * @return    void
203
+	 * @throws EE_Error
204
+	 */
205
+	public static function set_definitions()
206
+	{
207
+		if (defined('SPCO_BASE_PATH')) {
208
+			return;
209
+		}
210
+		define(
211
+			'SPCO_BASE_PATH',
212
+			rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
213
+		);
214
+		define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
215
+		define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
216
+		define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
217
+		define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
218
+		define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
219
+		define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
220
+		EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
221
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
222
+			EED_Single_Page_Checkout::getRegistrationExpirationNotice();
223
+	}
224
+
225
+
226
+	/**
227
+	 * load_reg_steps
228
+	 * loads and instantiates each reg step based on the EE_Registry::instance()->CFG->registration->reg_steps array
229
+	 *
230
+	 * @throws EE_Error
231
+	 */
232
+	public static function load_reg_steps()
233
+	{
234
+		static $reg_steps_loaded = false;
235
+		if ($reg_steps_loaded) {
236
+			return;
237
+		}
238
+		// filter list of reg_steps
239
+		$reg_steps_to_load = (array) apply_filters(
240
+			'AHEE__SPCO__load_reg_steps__reg_steps_to_load',
241
+			EED_Single_Page_Checkout::get_reg_steps()
242
+		);
243
+		// sort by key (order)
244
+		ksort($reg_steps_to_load);
245
+		// loop through folders
246
+		foreach ($reg_steps_to_load as $order => $reg_step) {
247
+			// we need a
248
+			if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
249
+				// copy over to the reg_steps_array
250
+				EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
251
+				// register custom key route for each reg step
252
+				// ie: step=>"slug" - this is the entire reason we load the reg steps array now
253
+				EED_Module::registerRoute(
254
+					$reg_step['slug'],
255
+					'EED_Single_Page_Checkout',
256
+					'run',
257
+					'step'
258
+				);
259
+				// add AJAX or other hooks
260
+				if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
261
+					// setup autoloaders if necessary
262
+					if (! class_exists($reg_step['class_name'])) {
263
+						EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
264
+							$reg_step['file_path'],
265
+							true
266
+						);
267
+					}
268
+					if (is_callable($reg_step['class_name'], 'set_hooks')) {
269
+						call_user_func([$reg_step['class_name'], 'set_hooks']);
270
+					}
271
+				}
272
+			}
273
+		}
274
+		$reg_steps_loaded = true;
275
+	}
276
+
277
+
278
+	/**
279
+	 *    get_reg_steps
280
+	 *
281
+	 * @return    array
282
+	 */
283
+	public static function get_reg_steps(): array
284
+	{
285
+		$reg_steps = EE_Registry::instance()->CFG->registration->reg_steps;
286
+		if (empty($reg_steps)) {
287
+			$reg_steps = [
288
+				10  => [
289
+					'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
290
+					'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
291
+					'slug'       => 'attendee_information',
292
+					'has_hooks'  => false,
293
+				],
294
+				30  => [
295
+					'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
296
+					'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
297
+					'slug'       => 'payment_options',
298
+					'has_hooks'  => true,
299
+				],
300
+				999 => [
301
+					'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
302
+					'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
303
+					'slug'       => 'finalize_registration',
304
+					'has_hooks'  => false,
305
+				],
306
+			];
307
+		}
308
+		return $reg_steps;
309
+	}
310
+
311
+
312
+	/**
313
+	 * @return array|string
314
+	 * @throws EE_Error
315
+	 * @throws ReflectionException
316
+	 */
317
+	public static function registration_checkout_for_admin()
318
+	{
319
+		$request = EED_Single_Page_Checkout::getRequest();
320
+		$request->setRequestParam('step', 'attendee_information');
321
+		$request->setRequestParam('action', 'display_spco_reg_step');
322
+		$request->setRequestParam('process_form_submission', false);
323
+		EED_Single_Page_Checkout::instance()->_initialize();
324
+		EED_Single_Page_Checkout::instance()->_display_spco_reg_form();
325
+		return EED_Single_Page_Checkout::getResponse()->getOutput();
326
+	}
327
+
328
+
329
+	/**
330
+	 * @return EE_Transaction|null
331
+	 * @throws EE_Error
332
+	 * @throws ReflectionException
333
+	 */
334
+	public static function process_registration_from_admin(): ?EE_Transaction
335
+	{
336
+		$request = EED_Single_Page_Checkout::getRequest();
337
+		$request->setRequestParam('step', 'attendee_information');
338
+		$request->setRequestParam('action', 'process_reg_step');
339
+		$request->setRequestParam('process_form_submission', true);
340
+		EED_Single_Page_Checkout::instance()->_initialize();
341
+		if (EED_Single_Page_Checkout::instance()->checkout->current_step->completed()) {
342
+			$final_reg_step = end(EED_Single_Page_Checkout::instance()->checkout->reg_steps);
343
+			if ($final_reg_step instanceof EE_SPCO_Reg_Step_Finalize_Registration) {
344
+				EED_Single_Page_Checkout::instance()->checkout->set_reg_step_initiated($final_reg_step);
345
+				if ($final_reg_step->process_reg_step()) {
346
+					$final_reg_step->set_completed();
347
+					EED_Single_Page_Checkout::instance()->checkout->update_txn_reg_steps_array();
348
+					return EED_Single_Page_Checkout::instance()->checkout->transaction;
349
+				}
350
+			}
351
+		}
352
+		return null;
353
+	}
354
+
355
+
356
+	/**
357
+	 *    run
358
+	 *
359
+	 * @param WP_Query|null $WP_Query
360
+	 * @return    void
361
+	 */
362
+	public function run($WP_Query)
363
+	{
364
+		if (
365
+			$WP_Query instanceof WP_Query
366
+			&& $WP_Query->is_main_query()
367
+			&& apply_filters('FHEE__EED_Single_Page_Checkout__run', true)
368
+			&& $this->_is_reg_checkout()
369
+		) {
370
+			$this->_initialize();
371
+		}
372
+	}
373
+
374
+
375
+	/**
376
+	 * determines whether current url matches reg page url
377
+	 *
378
+	 * @return bool
379
+	 */
380
+	protected function _is_reg_checkout(): bool
381
+	{
382
+		// get current permalink for reg page without any extra query args
383
+		$reg_page_url = get_permalink(EE_Config::instance()->core->reg_page_id);
384
+		// get request URI for current request, but without the scheme or host
385
+		$current_request_uri = EEH_URL::filter_input_server_url();
386
+		$current_request_uri = html_entity_decode($current_request_uri);
387
+		// get array of query args from the current request URI
388
+		$query_args = EEH_URL::get_query_string($current_request_uri);
389
+		// grab page id if it is set
390
+		$page_id = isset($query_args['page_id']) ? absint($query_args['page_id']) : 0;
391
+		// and remove the page id from the query args (we will re-add it later)
392
+		unset($query_args['page_id']);
393
+		// now strip all query args from current request URI
394
+		$current_request_uri = remove_query_arg(array_keys($query_args), $current_request_uri);
395
+		// and re-add the page id if it was set
396
+		if ($page_id) {
397
+			$current_request_uri = add_query_arg('page_id', $page_id, $current_request_uri);
398
+		}
399
+		// remove slashes and ?
400
+		$current_request_uri = trim($current_request_uri, '?/');
401
+		// is current request URI part of the known full reg page URL ?
402
+		return ! empty($current_request_uri) && strpos($reg_page_url, $current_request_uri) !== false;
403
+	}
404
+
405
+
406
+	/**
407
+	 * @param WP_Query $wp_query
408
+	 * @return    void
409
+	 * @throws EE_Error
410
+	 * @throws ReflectionException
411
+	 */
412
+	public static function init(WP_Query $wp_query)
413
+	{
414
+		EED_Single_Page_Checkout::instance()->run($wp_query);
415
+	}
416
+
417
+
418
+	/**
419
+	 * @return void
420
+	 */
421
+	private function _initialize()
422
+	{
423
+		// ensure SPCO doesn't run twice
424
+		if (EED_Single_Page_Checkout::$_initialized) {
425
+			return;
426
+		}
427
+		try {
428
+			$this->request = EED_Single_Page_Checkout::getRequest();
429
+			EED_Single_Page_Checkout::load_reg_steps();
430
+			$this->_verify_session();
431
+			// set up the EE_Checkout object
432
+			$this->checkout = $this->_initialize_checkout();
433
+			// filter checkout
434
+			$this->checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize__checkout', $this->checkout);
435
+			// get the $_GET
436
+			$this->_get_request_vars();
437
+			if ($this->_block_bots()) {
438
+				return;
439
+			}
440
+			// filter continue_reg
441
+			$this->checkout->continue_reg = apply_filters(
442
+				'FHEE__EED_Single_Page_Checkout__init___continue_reg',
443
+				true,
444
+				$this->checkout
445
+			);
446
+			// load the reg steps array
447
+			if (! $this->_load_and_instantiate_reg_steps()) {
448
+				EED_Single_Page_Checkout::$_initialized = true;
449
+				return;
450
+			}
451
+			// set the current step
452
+			$this->checkout->set_current_step($this->checkout->step);
453
+			// and the next step
454
+			$this->checkout->set_next_step();
455
+			// verify that everything has been set up correctly
456
+			if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
457
+				EED_Single_Page_Checkout::$_initialized = true;
458
+				return;
459
+			}
460
+			do_action('AHEE__Single_Page_Checkout___initialize__after_final_verifications', $this->checkout);
461
+			// lock the transaction
462
+			$this->checkout->transaction->lock();
463
+			// make sure all of our cached objects are added to their respective model entity mappers
464
+			$this->checkout->refresh_all_entities();
465
+			// set amount owing
466
+			$this->checkout->amount_owing = $this->checkout->transaction->remaining();
467
+			// initialize each reg step, which gives them the chance to potentially alter the process
468
+			$this->_initialize_reg_steps();
469
+			// DEBUG LOG
470
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
471
+			// get reg form
472
+			if (! $this->_check_form_submission()) {
473
+				EED_Single_Page_Checkout::$_initialized = true;
474
+				return;
475
+			}
476
+			// checkout the action!!!
477
+			$this->_process_form_action();
478
+			// add some style and make it dance
479
+			$this->add_styles_and_scripts($this);
480
+			// kk... SPCO has successfully run
481
+			EED_Single_Page_Checkout::$_initialized = true;
482
+			// set no cache headers and constants
483
+			EE_System::do_not_cache();
484
+			// add anchor
485
+			add_action('loop_start', [$this, 'set_checkout_anchor'], 1);
486
+			// remove transaction lock
487
+			add_action('shutdown', [$this, 'unlock_transaction'], 1);
488
+		} catch (Exception $e) {
489
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
490
+		}
491
+	}
492
+
493
+
494
+	/**
495
+	 * checks that the session is valid and not expired
496
+	 *
497
+	 * @throws EE_Error
498
+	 * @throws ReflectionException
499
+	 */
500
+	private function _verify_session()
501
+	{
502
+		if (! $this->session instanceof EE_Session) {
503
+			$this->session = LoaderFactory::getShared(EE_Session::class);
504
+			if (! $this->session instanceof EE_Session) {
505
+				throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
506
+			}
507
+		}
508
+		$clear_session_requested = $this->request->getRequestParam('clear_session', false, 'bool');
509
+		// is session still valid ?
510
+		if (
511
+			$clear_session_requested
512
+			|| (
513
+				$this->session->expired()
514
+				&& $this->request->getRequestParam('e_reg_url_link') === ''
515
+			)
516
+		) {
517
+			$this->checkout = new EE_Checkout();
518
+			$this->session->clear_session(__CLASS__, __FUNCTION__);
519
+			if (! $clear_session_requested) {
520
+				EE_Error::add_attention(
521
+					EE_Registry::$i18n_js_strings['registration_expiration_notice'],
522
+					__FILE__,
523
+					__FUNCTION__,
524
+					__LINE__
525
+				);
526
+			}
527
+		}
528
+	}
529
+
530
+
531
+	/**
532
+	 * loads and instantiates EE_Checkout
533
+	 *
534
+	 * @return EE_Checkout
535
+	 * @throws EE_Error
536
+	 * @throws ReflectionException
537
+	 */
538
+	private function _initialize_checkout(): EE_Checkout
539
+	{
540
+		// look in session for existing checkout
541
+		/** @type EE_Checkout $checkout */
542
+		$checkout = $this->session->checkout();
543
+		// verify
544
+		if (! $checkout instanceof EE_Checkout) {
545
+			// instantiate EE_Checkout object for handling the properties of the current checkout process
546
+			$checkout = EE_Registry::instance()->load_file(
547
+				SPCO_INC_PATH,
548
+				'EE_Checkout',
549
+				'class',
550
+				[],
551
+				false
552
+			);
553
+		} else {
554
+			if ($checkout->current_step->is_final_step() && $checkout->exit_spco() === true) {
555
+				$this->unlock_transaction();
556
+				wp_safe_redirect($checkout->redirect_url);
557
+				exit();
558
+			}
559
+		}
560
+		$checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
561
+		// verify again
562
+		if (! $checkout instanceof EE_Checkout) {
563
+			throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
564
+		}
565
+		// reset anything that needs a clean slate for each request
566
+		$checkout->reset_for_current_request();
567
+		return $checkout;
568
+	}
569
+
570
+
571
+	/**
572
+	 * @return void
573
+	 */
574
+	private function _get_request_vars()
575
+	{
576
+		// make sure this request is marked as belonging to EE
577
+		/** @var CurrentPage $current_page */
578
+		$current_page = LoaderFactory::getLoader()->getShared(CurrentPage::class);
579
+		$current_page->setEspressoPage(true);
580
+		// which step is being requested ?
581
+		$this->checkout->step = $this->request->getRequestParam('step', $this->_get_first_step());
582
+		// which step is being edited ?
583
+		$this->checkout->edit_step = $this->request->getRequestParam('edit_step');
584
+		// and what we're doing on the current step
585
+		$this->checkout->action = $this->request->getRequestParam('action', 'display_spco_reg_step');
586
+		// timestamp
587
+		$this->checkout->uts = $this->request->getRequestParam('uts', 0, 'int');
588
+		// returning to edit ?
589
+		$this->checkout->reg_url_link = $this->request->getRequestParam('e_reg_url_link');
590
+		// add reg url link to registration query params
591
+		if ($this->checkout->reg_url_link && strpos($this->checkout->reg_url_link, '1-') !== 0) {
592
+			$this->checkout->reg_cache_where_params[0]['REG_url_link'] = $this->checkout->reg_url_link;
593
+		}
594
+		// or some other kind of revisit ?
595
+		$this->checkout->revisit = $this->request->getRequestParam('revisit', false, 'bool');
596
+		// and whether to generate a reg form for this request
597
+		$this->checkout->generate_reg_form = $this->request->getRequestParam('generate_reg_form', true, 'bool');
598
+		// and whether to process a reg form submission for this request
599
+		$this->checkout->process_form_submission = $this->request->getRequestParam(
600
+			'process_form_submission',
601
+			$this->checkout->action === 'process_reg_step',
602
+			'bool'
603
+		);
604
+		$this->checkout->process_form_submission = filter_var(
605
+			$this->checkout->action !== 'display_spco_reg_step'
606
+				? $this->checkout->process_form_submission
607
+				: false,
608
+			FILTER_VALIDATE_BOOLEAN
609
+		);
610
+		$this->_display_request_vars();
611
+	}
612
+
613
+
614
+	/**
615
+	 * @return void
616
+	 */
617
+	protected function _display_request_vars()
618
+	{
619
+		if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
620
+			return;
621
+		}
622
+		EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
623
+		EEH_Debug_Tools::printr($this->checkout->step, '$this->checkout->step', __FILE__, __LINE__);
624
+		EEH_Debug_Tools::printr($this->checkout->edit_step, '$this->checkout->edit_step', __FILE__, __LINE__);
625
+		EEH_Debug_Tools::printr($this->checkout->action, '$this->checkout->action', __FILE__, __LINE__);
626
+		EEH_Debug_Tools::printr($this->checkout->reg_url_link, '$this->checkout->reg_url_link', __FILE__, __LINE__);
627
+		EEH_Debug_Tools::printr($this->checkout->revisit, '$this->checkout->revisit', __FILE__, __LINE__);
628
+		EEH_Debug_Tools::printr(
629
+			$this->checkout->generate_reg_form,
630
+			'$this->checkout->generate_reg_form',
631
+			__FILE__,
632
+			__LINE__
633
+		);
634
+		EEH_Debug_Tools::printr(
635
+			$this->checkout->process_form_submission,
636
+			'$this->checkout->process_form_submission',
637
+			__FILE__,
638
+			__LINE__
639
+		);
640
+	}
641
+
642
+
643
+	/**
644
+	 * _block_bots
645
+	 * checks that the incoming request has either of the following set:
646
+	 *  a UTS (unix timestamp) which indicates that the request was redirected from the Ticket Selector
647
+	 *  a REG URL Link, which indicates that the request is a return visit to SPCO for a valid TXN
648
+	 * so if you're not coming from the Ticket Selector nor returning for a valid IP...
649
+	 * then where you coming from man?
650
+	 *
651
+	 * @return boolean
652
+	 */
653
+	private function _block_bots(): bool
654
+	{
655
+		return EED_Invalid_Checkout_Access::getInvalidCheckoutAccess()->checkoutAccessIsInvalid($this->checkout);
656
+	}
657
+
658
+
659
+	/**
660
+	 *  gets slug for first step in $_reg_steps_array
661
+	 *
662
+	 * @return string
663
+	 */
664
+	private function _get_first_step(): string
665
+	{
666
+		$first_step = reset(EED_Single_Page_Checkout::$_reg_steps_array);
667
+		return $first_step['slug'] ?? 'attendee_information';
668
+	}
669
+
670
+
671
+	/**
672
+	 * instantiates each reg step based on the loaded reg_steps array
673
+	 *
674
+	 * @return bool
675
+	 * @throws EE_Error
676
+	 * @throws InvalidArgumentException
677
+	 * @throws InvalidDataTypeException
678
+	 * @throws InvalidInterfaceException
679
+	 * @throws ReflectionException
680
+	 */
681
+	private function _load_and_instantiate_reg_steps(): bool
682
+	{
683
+		do_action('AHEE__Single_Page_Checkout___load_and_instantiate_reg_steps__start', $this->checkout);
684
+		// have reg_steps already been instantiated ?
685
+		if (
686
+			empty($this->checkout->reg_steps)
687
+			|| apply_filters('FHEE__Single_Page_Checkout__load_reg_steps__reload_reg_steps', false, $this->checkout)
688
+		) {
689
+			// if not, then loop through raw reg steps array
690
+			foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
691
+				if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
692
+					return false;
693
+				}
694
+			}
695
+			if (isset($this->checkout->reg_steps['registration_confirmation'])) {
696
+				// skip the registration_confirmation page ?
697
+				// just remove it from the reg steps array
698
+				$this->checkout->remove_reg_step('registration_confirmation', false);
699
+			}
700
+			// filter the array for good luck
701
+			$this->checkout->reg_steps = apply_filters(
702
+				'FHEE__Single_Page_Checkout__load_reg_steps__reg_steps',
703
+				$this->checkout->reg_steps
704
+			);
705
+			// finally re-sort based on the reg step class order properties
706
+			$this->checkout->sort_reg_steps();
707
+		} else {
708
+			foreach ($this->checkout->reg_steps as $reg_step) {
709
+				// set all current step stati to FALSE
710
+				$reg_step->set_is_current_step(false);
711
+			}
712
+		}
713
+		if (empty($this->checkout->reg_steps)) {
714
+			EE_Error::add_error(
715
+				esc_html__('No Reg Steps were loaded..', 'event_espresso'),
716
+				__FILE__,
717
+				__FUNCTION__,
718
+				__LINE__
719
+			);
720
+			return false;
721
+		}
722
+		// make reg step details available to JS
723
+		$this->checkout->set_reg_step_JSON_info();
724
+		return true;
725
+	}
726
+
727
+
728
+	/**
729
+	 * @param array $reg_step
730
+	 * @param int   $order
731
+	 * @return bool
732
+	 * @throws EE_Error
733
+	 * @throws ReflectionException
734
+	 */
735
+	private function _load_and_instantiate_reg_step(array $reg_step = [], int $order = 0): bool
736
+	{
737
+		// we need a file_path, class_name, and slug to add a reg step
738
+		if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
739
+			// if editing a specific step, but this is NOT that step... (and it's not the 'finalize_registration' step)
740
+			if (
741
+				$this->checkout->reg_url_link
742
+				&& $this->checkout->step !== $reg_step['slug']
743
+				&& $reg_step['slug'] !== 'finalize_registration'
744
+				// normally at this point we would NOT load the reg step, but this filter can change that
745
+				&& apply_filters(
746
+					'FHEE__Single_Page_Checkout___load_and_instantiate_reg_step__bypass_reg_step',
747
+					true,
748
+					$reg_step,
749
+					$this->checkout
750
+				)
751
+			) {
752
+				return true;
753
+			}
754
+
755
+			// instantiate step class using file path and class name
756
+			$reg_step_obj = EE_Registry::instance()->load_file(
757
+				$reg_step['file_path'],
758
+				$reg_step['class_name'],
759
+				'class',
760
+				[$this->checkout],
761
+				false
762
+			);
763
+			// did we get the goods ?
764
+			if ($reg_step_obj instanceof EE_SPCO_Reg_Step) {
765
+				// set reg step order based on config
766
+				$reg_step_obj->set_order($order);
767
+				// add instantiated reg step object to the master reg steps array
768
+				$this->checkout->add_reg_step($reg_step_obj);
769
+			} else {
770
+				EE_Error::add_error(
771
+					esc_html__('The current step could not be set.', 'event_espresso'),
772
+					__FILE__,
773
+					__FUNCTION__,
774
+					__LINE__
775
+				);
776
+				return false;
777
+			}
778
+		} else {
779
+			if (WP_DEBUG) {
780
+				EE_Error::add_error(
781
+					sprintf(
782
+						esc_html__(
783
+							'A registration step could not be loaded. One or more of the following data points is invalid:%4$s%5$sFile Path: %1$s%6$s%5$sClass Name: %2$s%6$s%5$sSlug: %3$s%6$s%7$s',
784
+							'event_espresso'
785
+						),
786
+						$reg_step['file_path'] ?? '',
787
+						$reg_step['class_name'] ?? '',
788
+						$reg_step['slug'] ?? '',
789
+						'<ul>',
790
+						'<li>',
791
+						'</li>',
792
+						'</ul>'
793
+					),
794
+					__FILE__,
795
+					__FUNCTION__,
796
+					__LINE__
797
+				);
798
+			}
799
+			return false;
800
+		}
801
+		return true;
802
+	}
803
+
804
+
805
+	/**
806
+	 * @return bool
807
+	 * @throws EE_Error
808
+	 * @throws ReflectionException
809
+	 */
810
+	private function _verify_transaction_and_get_registrations(): bool
811
+	{
812
+		// was there already a valid transaction in the checkout from the session ?
813
+		if (! $this->checkout->transaction instanceof EE_Transaction) {
814
+			// get transaction from db or session
815
+			$this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
816
+				? $this->_get_transaction_and_cart_for_previous_visit()
817
+				: $this->_get_cart_for_current_session_and_setup_new_transaction();
818
+			if (! $this->checkout->transaction instanceof EE_Transaction) {
819
+				EE_Error::add_error(
820
+					esc_html__(
821
+						'Your Registration and Transaction information could not be retrieved from the db.',
822
+						'event_espresso'
823
+					),
824
+					__FILE__,
825
+					__FUNCTION__,
826
+					__LINE__
827
+				);
828
+				$this->checkout->transaction = EE_Transaction::new_instance();
829
+				// add some style and make it dance
830
+				$this->add_styles_and_scripts($this);
831
+				EED_Single_Page_Checkout::$_initialized = true;
832
+				return false;
833
+			}
834
+			// and the registrations for the transaction
835
+			$this->_get_registrations($this->checkout->transaction);
836
+		}
837
+		return true;
838
+	}
839
+
840
+
841
+	/**
842
+	 * @return EE_Transaction|null
843
+	 * @throws EE_Error
844
+	 * @throws ReflectionException
845
+	 */
846
+	private function _get_transaction_and_cart_for_previous_visit(): ?EE_Transaction
847
+	{
848
+		/** @var $TXN_model EEM_Transaction */
849
+		$TXN_model = EE_Registry::instance()->load_model('Transaction');
850
+		// because the reg_url_link is present in the request,
851
+		// this is a return visit to SPCO, so we'll get the transaction data from the db
852
+		$transaction = $TXN_model->get_transaction_from_reg_url_link($this->checkout->reg_url_link);
853
+		// verify transaction
854
+		if ($transaction instanceof EE_Transaction) {
855
+			// and get the cart that was used for that transaction
856
+			$this->checkout->cart = $this->_get_cart_for_transaction($transaction);
857
+			return $transaction;
858
+		}
859
+		EE_Error::add_error(
860
+			esc_html__(
861
+				'Your Registration and Transaction information could not be retrieved from the db.',
862
+				'event_espresso'
863
+			),
864
+			__FILE__,
865
+			__FUNCTION__,
866
+			__LINE__
867
+		);
868
+		return null;
869
+	}
870
+
871
+
872
+	/**
873
+	 * @param EE_Transaction|null $transaction
874
+	 * @return EE_Cart
875
+	 * @throws EE_Error
876
+	 * @throws ReflectionException
877
+	 */
878
+	private function _get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
879
+	{
880
+		return $this->checkout->get_cart_for_transaction($transaction);
881
+	}
882
+
883
+
884
+	/**
885
+	 * @param EE_Transaction|null $transaction
886
+	 * @return EE_Cart
887
+	 * @throws EE_Error
888
+	 * @throws ReflectionException
889
+	 */
890
+	public function get_cart_for_transaction(?EE_Transaction $transaction): EE_Cart
891
+	{
892
+		return $this->checkout->get_cart_for_transaction($transaction);
893
+	}
894
+
895
+
896
+	/**
897
+	 * generates a new EE_Transaction object and adds it to the $_transaction property.
898
+	 *
899
+	 * @return EE_Transaction|null
900
+	 * @throws EE_Error
901
+	 * @throws ReflectionException
902
+	 */
903
+	private function _get_cart_for_current_session_and_setup_new_transaction(): ?EE_Transaction
904
+	{
905
+		//  if there's no transaction, then this is the FIRST visit to SPCO
906
+		// so load up the cart ( passing nothing for the TXN because it doesn't exist yet )
907
+		$this->checkout->cart = $this->_get_cart_for_transaction(null);
908
+		// and then create a new transaction
909
+		$transaction = $this->_initialize_transaction();
910
+		// verify transaction
911
+		if ($transaction instanceof EE_Transaction) {
912
+			// and save TXN data to the cart
913
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn($transaction->ID());
914
+		} else {
915
+			EE_Error::add_error(
916
+				esc_html__('A Valid Transaction could not be initialized.', 'event_espresso'),
917
+				__FILE__,
918
+				__FUNCTION__,
919
+				__LINE__
920
+			);
921
+		}
922
+		return $transaction;
923
+	}
924
+
925
+
926
+	/**
927
+	 * generates a new EE_Transaction object and adds it to the $_transaction property.
928
+	 *
929
+	 * @return EE_Transaction|null
930
+	 */
931
+	private function _initialize_transaction(): ?EE_Transaction
932
+	{
933
+		try {
934
+			// ensure cart totals have been calculated
935
+			$this->checkout->cart->get_grand_total()->recalculate_total_including_taxes();
936
+			// grab the cart grand total
937
+			$cart_total = $this->checkout->cart->get_cart_grand_total();
938
+			// create new TXN
939
+			$transaction = EE_Transaction::new_instance(
940
+				[
941
+					'TXN_reg_steps' => $this->checkout->initialize_txn_reg_steps_array(),
942
+					'TXN_total'     => max($cart_total, 0),
943
+					'TXN_paid'      => 0,
944
+					'STS_ID'        => EEM_Transaction::failed_status_code,
945
+				]
946
+			);
947
+			// save it so that we have an ID for other objects to use
948
+			$transaction->save();
949
+			// set cron job for following up on TXNs after their session has expired
950
+			EE_Cron_Tasks::schedule_expired_transaction_check(
951
+				$this->session->expiration() + 1,
952
+				$transaction->ID()
953
+			);
954
+			return $transaction;
955
+		} catch (Exception $e) {
956
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
957
+		}
958
+		return null;
959
+	}
960
+
961
+
962
+	/**
963
+	 * _get_registrations
964
+	 *
965
+	 * @param EE_Transaction $transaction
966
+	 * @return void
967
+	 * @throws EE_Error
968
+	 * @throws ReflectionException
969
+	 */
970
+	private function _get_registrations(EE_Transaction $transaction)
971
+	{
972
+		// first step: grab the registrants  { : o
973
+		$registrations                      = $transaction->registrations($this->checkout->reg_cache_where_params);
974
+		$this->checkout->total_ticket_count = count($registrations);
975
+		// verify registrations have been set
976
+		if (empty($registrations)) {
977
+			// if no cached registrations, then check the db
978
+			$registrations = $transaction->registrations($this->checkout->reg_cache_where_params);
979
+			// still nothing ? well as long as this isn't a revisit
980
+			if (empty($registrations) && ! $this->checkout->revisit) {
981
+				// generate new registrations from scratch
982
+				$registrations = $this->_initialize_registrations($transaction);
983
+			}
984
+		}
985
+		// sort by their original registration order
986
+		usort($registrations, ['EED_Single_Page_Checkout', 'sort_registrations_by_REG_count']);
987
+		// then loop thru the array
988
+		foreach ($registrations as $registration) {
989
+			// verify each registration
990
+			if ($registration instanceof EE_Registration) {
991
+				// we display all attendee info for the primary registrant
992
+				if (
993
+					$this->checkout->reg_url_link === $registration->reg_url_link()
994
+					&& $registration->is_primary_registrant()
995
+				) {
996
+					$this->checkout->primary_revisit = true;
997
+					break;
998
+				}
999
+				if ($this->checkout->revisit && $this->checkout->reg_url_link !== $registration->reg_url_link()) {
1000
+					// but hide info if it doesn't belong to you
1001
+					$transaction->clear_cache('Registration', $registration->ID());
1002
+					$this->checkout->total_ticket_count--;
1003
+				}
1004
+				$this->checkout->set_reg_status_updated($registration->ID(), false);
1005
+			}
1006
+		}
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * adds related EE_Registration objects for each ticket in the cart to the current EE_Transaction object
1012
+	 *
1013
+	 * @param EE_Transaction $transaction
1014
+	 * @return array
1015
+	 * @throws EE_Error
1016
+	 * @throws ReflectionException
1017
+	 */
1018
+	private function _initialize_registrations(EE_Transaction $transaction): array
1019
+	{
1020
+		$att_nmbr      = 0;
1021
+		$registrations = [];
1022
+		/** @type EE_Registration_Processor $registration_processor */
1023
+		$registration_processor             = EE_Registry::instance()->load_class('Registration_Processor');
1024
+		$this->checkout->total_ticket_count = $this->checkout->cart->all_ticket_quantity_count();
1025
+		// now let's add the cart items to the $transaction
1026
+		foreach ($this->checkout->cart->get_tickets() as $line_item) {
1027
+			// do the following for each ticket of this type they selected
1028
+			for ($x = 1; $x <= $line_item->quantity(); $x++) {
1029
+				$att_nmbr++;
1030
+				/** @var CreateRegistrationCommand $CreateRegistrationCommand */
1031
+				$CreateRegistrationCommand = EE_Registry::instance()->create(
1032
+					CreateRegistrationCommand::class,
1033
+					[
1034
+						$transaction,
1035
+						$line_item,
1036
+						$att_nmbr,
1037
+						$this->checkout->total_ticket_count,
1038
+					]
1039
+				);
1040
+				// override capabilities for frontend registrations
1041
+				if ($this->request->isFrontend()) {
1042
+					$CreateRegistrationCommand->setCapCheck(
1043
+						new PublicCapabilities('', 'create_new_registration')
1044
+					);
1045
+				}
1046
+				$registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1047
+				if (! $registration instanceof EE_Registration) {
1048
+					throw new InvalidEntityException($registration, 'EE_Registration');
1049
+				}
1050
+				$registrations[ $registration->ID() ] = $registration;
1051
+			}
1052
+		}
1053
+		$registration_processor->fix_reg_final_price_rounding_issue($transaction);
1054
+		return $registrations;
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * @param EE_Registration $reg_A
1060
+	 * @param EE_Registration $reg_B
1061
+	 * @return int
1062
+	 * @throws EE_Error
1063
+	 * @throws ReflectionException
1064
+	 */
1065
+	public static function sort_registrations_by_REG_count(EE_Registration $reg_A, EE_Registration $reg_B): int
1066
+	{
1067
+		// this shouldn't ever happen within the same TXN, but oh well
1068
+		if ($reg_A->count() === $reg_B->count()) {
1069
+			return 0;
1070
+		}
1071
+		return ($reg_A->count() > $reg_B->count()) ? 1 : -1;
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * just makes sure that everything is set up correctly before proceeding
1077
+	 *
1078
+	 * @return bool
1079
+	 * @throws EE_Error
1080
+	 * @throws ReflectionException
1081
+	 */
1082
+	private function _final_verifications(): bool
1083
+	{
1084
+		// filter checkout
1085
+		$this->checkout = apply_filters(
1086
+			'FHEE__EED_Single_Page_Checkout___final_verifications__checkout',
1087
+			$this->checkout
1088
+		);
1089
+		// verify that current step is still set correctly
1090
+		if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1091
+			EE_Error::add_error(
1092
+				esc_html__(
1093
+					'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
1094
+					'event_espresso'
1095
+				),
1096
+				__FILE__,
1097
+				__FUNCTION__,
1098
+				__LINE__
1099
+			);
1100
+			return false;
1101
+		}
1102
+		// if returning to SPCO, then verify that primary registrant is set
1103
+		if (! empty($this->checkout->reg_url_link)) {
1104
+			$valid_registrant = $this->checkout->transaction->primary_registration();
1105
+			if (! $valid_registrant instanceof EE_Registration) {
1106
+				EE_Error::add_error(
1107
+					esc_html__(
1108
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
1109
+						'event_espresso'
1110
+					),
1111
+					__FILE__,
1112
+					__FUNCTION__,
1113
+					__LINE__
1114
+				);
1115
+				return false;
1116
+			}
1117
+			$valid_registrant = null;
1118
+			foreach (
1119
+				$this->checkout->transaction->registrations(
1120
+					$this->checkout->reg_cache_where_params
1121
+				) as $registration
1122
+			) {
1123
+				if (
1124
+					$registration instanceof EE_Registration
1125
+					&& $registration->reg_url_link() === $this->checkout->reg_url_link
1126
+				) {
1127
+					$valid_registrant = $registration;
1128
+				}
1129
+			}
1130
+			if (! $valid_registrant instanceof EE_Registration) {
1131
+				// hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1132
+				if (EED_Single_Page_Checkout::$_checkout_verified) {
1133
+					// clear the session, mark the checkout as unverified, and try again
1134
+					$this->session->clear_session(__CLASS__, __FUNCTION__);
1135
+					EED_Single_Page_Checkout::$_initialized       = false;
1136
+					EED_Single_Page_Checkout::$_checkout_verified = false;
1137
+					$this->_initialize();
1138
+					EE_Error::reset_notices();
1139
+					return false;
1140
+				}
1141
+				EE_Error::add_error(
1142
+					esc_html__(
1143
+						'We\'re sorry but there appears to be an error with the "reg_url_link" or the transaction itself. Please refresh the page and try again or contact support.',
1144
+						'event_espresso'
1145
+					),
1146
+					__FILE__,
1147
+					__FUNCTION__,
1148
+					__LINE__
1149
+				);
1150
+				return false;
1151
+			}
1152
+		}
1153
+		// now that things have been kinda sufficiently verified,
1154
+		// let's add the checkout to the session so that it's available to other systems
1155
+		$this->session->set_checkout($this->checkout);
1156
+		return true;
1157
+	}
1158
+
1159
+
1160
+	/**
1161
+	 * first makes sure that EE_Transaction_Processor::set_reg_step_initiated() is called as required
1162
+	 * then loops thru all the active reg steps and calls the initialize_reg_step() method
1163
+	 *
1164
+	 * @param bool $reinitializing
1165
+	 * @throws EE_Error
1166
+	 * @throws ReflectionException
1167
+	 */
1168
+	private function _initialize_reg_steps(bool $reinitializing = false)
1169
+	{
1170
+		$this->checkout->set_reg_step_initiated($this->checkout->current_step);
1171
+		// loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1172
+		foreach ($this->checkout->reg_steps as $reg_step) {
1173
+			if (! $reg_step->initialize_reg_step()) {
1174
+				// if not initialized then maybe this step is being removed...
1175
+				if (! $reinitializing && $reg_step->is_current_step()) {
1176
+					// if it was the current step, then we need to start over here
1177
+					$this->_initialize_reg_steps(true);
1178
+					return;
1179
+				}
1180
+				continue;
1181
+			}
1182
+			// add css and JS for current step
1183
+			$this->add_styles_and_scripts($reg_step);
1184
+			if ($reg_step->is_current_step()) {
1185
+				// the text that appears on the reg step form submit button
1186
+				$reg_step->set_submit_button_text();
1187
+			}
1188
+		}
1189
+		// dynamically creates hook point like: AHEE__Single_Page_Checkout___initialize_reg_step__attendee_information
1190
+		do_action(
1191
+			"AHEE__Single_Page_Checkout___initialize_reg_step__{$this->checkout->current_step->slug()}",
1192
+			$this->checkout->current_step
1193
+		);
1194
+		$this->checkout->json_response->set_return_data(
1195
+			[
1196
+				'action'        => $this->checkout->action,
1197
+				'admin_request' => $this->checkout->admin_request,
1198
+				'current_step'  => $this->checkout->current_step->slug(),
1199
+				'revisit'       => $this->checkout->revisit,
1200
+			]
1201
+		);
1202
+	}
1203
+
1204
+
1205
+	/**
1206
+	 * @return boolean
1207
+	 * @throws EE_Error
1208
+	 * @throws ReflectionException
1209
+	 */
1210
+	private function _check_form_submission(): bool
1211
+	{
1212
+		// does this request require the reg form to be generated ?
1213
+		if ($this->checkout->generate_reg_form) {
1214
+			// ever heard that song by Blue Rodeo ?
1215
+			try {
1216
+				$this->checkout->current_step->reg_form = $this->checkout->current_step->generate_reg_form();
1217
+				// if not displaying a form, then check for form submission
1218
+				if (
1219
+					$this->checkout->process_form_submission
1220
+					&& $this->checkout->current_step->reg_form->was_submitted()
1221
+				) {
1222
+					// clear out any old data in case this step is being run again
1223
+					$this->checkout->current_step->set_valid_data([]);
1224
+					// capture submitted form data
1225
+					$request_data = $this->request->requestParams();
1226
+					$this->checkout->current_step->reg_form->receive_form_submission(
1227
+						(array) apply_filters(
1228
+							'FHEE__Single_Page_Checkout___check_form_submission__request_params',
1229
+							$request_data,
1230
+							$this->checkout
1231
+						)
1232
+					);
1233
+					// validate submitted form data
1234
+					if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1235
+						// thou shall not pass !!!
1236
+						$this->checkout->continue_reg = false;
1237
+						// any form validation errors?
1238
+						if ($this->checkout->current_step->reg_form->submission_error_message() !== '') {
1239
+							EE_Error::add_error(
1240
+								$this->checkout->current_step->reg_form->submission_error_message(),
1241
+								__FILE__,
1242
+								__FUNCTION__,
1243
+								__LINE__
1244
+							);
1245
+						}
1246
+						// well not really... what will happen is
1247
+						// we'll just get redirected back to redo the current step
1248
+						$this->go_to_next_step();
1249
+						return false;
1250
+					}
1251
+				}
1252
+			} catch (EE_Error $e) {
1253
+				$e->get_error();
1254
+			}
1255
+		}
1256
+		return true;
1257
+	}
1258
+
1259
+
1260
+	/**
1261
+	 * @return void
1262
+	 * @throws EE_Error
1263
+	 * @throws ReflectionException
1264
+	 */
1265
+	private function _process_form_action()
1266
+	{
1267
+		// what cha wanna do?
1268
+		switch ($this->checkout->action) {
1269
+			// AJAX next step reg form
1270
+			case 'display_spco_reg_step':
1271
+				$this->checkout->redirect = false;
1272
+				if ($this->request->isAjax()) {
1273
+					$this->checkout->json_response->set_reg_step_html(
1274
+						$this->checkout->current_step->display_reg_form()
1275
+					);
1276
+				}
1277
+				break;
1278
+			default:
1279
+				// meh... do one of those other steps first
1280
+				if (
1281
+					! empty($this->checkout->action)
1282
+					&& is_callable([$this->checkout->current_step, $this->checkout->action])
1283
+				) {
1284
+					// dynamically creates hook point like:
1285
+					//   AHEE__Single_Page_Checkout__before_attendee_information__process_reg_step
1286
+					do_action(
1287
+						"AHEE__Single_Page_Checkout__before_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1288
+						$this->checkout->current_step
1289
+					);
1290
+					$process_reg_step = apply_filters(
1291
+						"AHEE__Single_Page_Checkout__process_reg_step__{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1292
+						true,
1293
+						$this->checkout->current_step,
1294
+						$this
1295
+					);
1296
+					// call action on current step
1297
+					if ($process_reg_step && call_user_func([$this->checkout->current_step, $this->checkout->action])) {
1298
+						// good registrant, you get to proceed
1299
+						if (
1300
+							$this->checkout->current_step->success_message() !== ''
1301
+							&& apply_filters(
1302
+								'FHEE__Single_Page_Checkout___process_form_action__display_success',
1303
+								false
1304
+							)
1305
+						) {
1306
+							EE_Error::add_success(
1307
+								$this->checkout->current_step->success_message()
1308
+								. '<br />' . $this->checkout->next_step->_instructions()
1309
+							);
1310
+						}
1311
+						// pack it up, pack it in...
1312
+						$this->_setup_redirect();
1313
+					}
1314
+					// dynamically creates hook point like:
1315
+					//  AHEE__Single_Page_Checkout__after_payment_options__process_reg_step
1316
+					do_action(
1317
+						"AHEE__Single_Page_Checkout__after_{$this->checkout->current_step->slug()}__{$this->checkout->action}",
1318
+						$this->checkout->current_step
1319
+					);
1320
+				} else {
1321
+					EE_Error::add_error(
1322
+						sprintf(
1323
+							esc_html__(
1324
+								'The requested form action "%s" does not exist for the current "%s" registration step.',
1325
+								'event_espresso'
1326
+							),
1327
+							$this->checkout->action,
1328
+							$this->checkout->current_step->name()
1329
+						),
1330
+						__FILE__,
1331
+						__FUNCTION__,
1332
+						__LINE__
1333
+					);
1334
+				}
1335
+			// end default
1336
+		}
1337
+		// store our progress so far
1338
+		$this->checkout->stash_transaction_and_checkout();
1339
+		// advance to the next step! If you pass GO, collect $200
1340
+		$this->go_to_next_step();
1341
+	}
1342
+
1343
+
1344
+	/**
1345
+	 * @param EED_Single_Page_Checkout|EE_SPCO_Reg_Step $target an object with the method `translate_js_strings` and
1346
+	 *                                                          `enqueue_styles_and_scripts`.
1347
+	 * @return void
1348
+	 */
1349
+	public function add_styles_and_scripts($target)
1350
+	{
1351
+		// i18n
1352
+		$target->translate_js_strings();
1353
+		if ($this->checkout->admin_request) {
1354
+			add_action('admin_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1355
+		} else {
1356
+			add_action('wp_enqueue_scripts', [$target, 'enqueue_styles_and_scripts']);
1357
+		}
1358
+	}
1359
+
1360
+
1361
+	/**
1362
+	 * @return void
1363
+	 */
1364
+	public function translate_js_strings()
1365
+	{
1366
+		EE_Registry::$i18n_js_strings['revisit']                        = $this->checkout->revisit;
1367
+		EE_Registry::$i18n_js_strings['e_reg_url_link']                 = $this->checkout->reg_url_link;
1368
+		EE_Registry::$i18n_js_strings['server_error']                   = esc_html__(
1369
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1370
+			'event_espresso'
1371
+		);
1372
+		EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1373
+			'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1374
+			'event_espresso'
1375
+		);
1376
+		EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1377
+			'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1378
+			'event_espresso'
1379
+		);
1380
+		EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1381
+			'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1382
+			'event_espresso'
1383
+		);
1384
+		EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1385
+			'This registration step could not be completed. Please refresh the page and try again.',
1386
+			'event_espresso'
1387
+		);
1388
+		EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1389
+			'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1390
+			'event_espresso'
1391
+		);
1392
+		EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1393
+			esc_html__(
1394
+				'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1395
+				'event_espresso'
1396
+			),
1397
+			'<br/>',
1398
+			'<br/>'
1399
+		);
1400
+		EE_Registry::$i18n_js_strings['language']                       = get_bloginfo('language');
1401
+		EE_Registry::$i18n_js_strings['EESID']                          = $this->session->id();
1402
+		EE_Registry::$i18n_js_strings['currency']                       = EE_Registry::instance()->CFG->currency;
1403
+		EE_Registry::$i18n_js_strings['datepicker_yearRange']           = '-150:+20';
1404
+		EE_Registry::$i18n_js_strings['timer_years']                    = esc_html__('years', 'event_espresso');
1405
+		EE_Registry::$i18n_js_strings['timer_months']                   = esc_html__('months', 'event_espresso');
1406
+		EE_Registry::$i18n_js_strings['timer_weeks']                    = esc_html__('weeks', 'event_espresso');
1407
+		EE_Registry::$i18n_js_strings['timer_days']                     = esc_html__('days', 'event_espresso');
1408
+		EE_Registry::$i18n_js_strings['timer_hours']                    = esc_html__('hours', 'event_espresso');
1409
+		EE_Registry::$i18n_js_strings['timer_minutes']                  = esc_html__('minutes', 'event_espresso');
1410
+		EE_Registry::$i18n_js_strings['timer_seconds']                  = esc_html__('seconds', 'event_espresso');
1411
+		EE_Registry::$i18n_js_strings['timer_year']                     = esc_html__('year', 'event_espresso');
1412
+		EE_Registry::$i18n_js_strings['timer_month']                    = esc_html__('month', 'event_espresso');
1413
+		EE_Registry::$i18n_js_strings['timer_week']                     = esc_html__('week', 'event_espresso');
1414
+		EE_Registry::$i18n_js_strings['timer_day']                      = esc_html__('day', 'event_espresso');
1415
+		EE_Registry::$i18n_js_strings['timer_hour']                     = esc_html__('hour', 'event_espresso');
1416
+		EE_Registry::$i18n_js_strings['timer_minute']                   = esc_html__('minute', 'event_espresso');
1417
+		EE_Registry::$i18n_js_strings['timer_second']                   = esc_html__('second', 'event_espresso');
1418
+		EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
1419
+			EED_Single_Page_Checkout::getRegistrationExpirationNotice();
1420
+		EE_Registry::$i18n_js_strings['ajax_submit']                    = apply_filters(
1421
+			'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1422
+			true
1423
+		);
1424
+		EE_Registry::$i18n_js_strings['session_extension']              = absint(
1425
+			apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1426
+		);
1427
+		EE_Registry::$i18n_js_strings['session_expiration']    = $this->session->expiration();
1428
+		EE_Registry::$i18n_js_strings['use_session_countdown'] = EE_Registry::instance()->CFG->registration->useSessionCountdown();
1429
+		EE_Registry::$i18n_js_strings['no_copy_paste_email_confirm'] = esc_html__("We're sorry but copy and paste is disabled for email confirmation inputs. Please enter the email address manually.", 'event_espresso');
1430
+	}
1431
+
1432
+
1433
+	/**
1434
+	 * @return void
1435
+	 * @throws EE_Error
1436
+	 */
1437
+	public function enqueue_styles_and_scripts()
1438
+	{
1439
+		// load css
1440
+		wp_register_style(
1441
+			'single_page_checkout',
1442
+			SPCO_CSS_URL . 'single_page_checkout.css',
1443
+			['espresso_default'],
1444
+			EVENT_ESPRESSO_VERSION
1445
+		);
1446
+		wp_enqueue_style('single_page_checkout');
1447
+		// load JS
1448
+		wp_register_script(
1449
+			'single_page_checkout',
1450
+			SPCO_JS_URL . 'single_page_checkout.js',
1451
+			['espresso_core', 'underscore', 'ee_form_section_validation'],
1452
+			EVENT_ESPRESSO_VERSION,
1453
+			true
1454
+		);
1455
+		if ($this->checkout->registration_form instanceof EE_Form_Section_Proper) {
1456
+			$this->checkout->registration_form->enqueue_js();
1457
+		}
1458
+		if ($this->checkout->current_step->reg_form instanceof EE_Form_Section_Proper) {
1459
+			$this->checkout->current_step->reg_form->enqueue_js();
1460
+		}
1461
+		wp_enqueue_script('single_page_checkout');
1462
+		/**
1463
+		 * global action hook for enqueueing styles and scripts with
1464
+		 * spco calls.
1465
+		 */
1466
+		do_action('AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts', $this);
1467
+		/**
1468
+		 * dynamic action hook for enqueueing styles and scripts with spco calls.
1469
+		 * The hook will end up being something like:
1470
+		 *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1471
+		 */
1472
+		do_action(
1473
+			'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1474
+			$this
1475
+		);
1476
+	}
1477
+
1478
+
1479
+	/**
1480
+	 * display the Registration Single Page Checkout Form
1481
+	 *
1482
+	 * @return void
1483
+	 * @throws EE_Error
1484
+	 * @throws ReflectionException
1485
+	 */
1486
+	private function _display_spco_reg_form()
1487
+	{
1488
+		// if registering via the admin, just display the reg form for the current step
1489
+		if ($this->checkout->admin_request) {
1490
+			EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->current_step->display_reg_form());
1491
+			return;
1492
+		}
1493
+
1494
+		// add powered by EE msg
1495
+		add_action('AHEE__SPCO__reg_form_footer', ['EED_Single_Page_Checkout', 'display_registration_footer']);
1496
+		$empty_cart = count(
1497
+				$this->checkout->transaction->registrations($this->checkout->reg_cache_where_params)
1498
+			) < 1;
1499
+		EE_Registry::$i18n_js_strings['empty_cart'] = $empty_cart;
1500
+
1501
+		/** @var FeatureFlags $feature */
1502
+		$feature = LoaderFactory::getShared(FeatureFlags::class);
1503
+
1504
+		$this->checkout->registration_form = $feature->allowed(FeatureFlag::USE_SPCO_FORM_REFACTOR)
1505
+			? new SinglePageCheckoutForm($this->checkout, $empty_cart)
1506
+			: new LegacySpcoForm($this->checkout, $empty_cart, $this->session->expiration());
1507
+
1508
+		// load template and add to output sent that gets filtered into the_content()
1509
+		EED_Single_Page_Checkout::getResponse()->addOutput($this->checkout->registration_form->get_html());
1510
+
1511
+	}
1512
+
1513
+
1514
+	/**
1515
+	 * @param $next_step
1516
+	 * @return void
1517
+	 */
1518
+	public function add_extra_finalize_registration_inputs($next_step)
1519
+	{
1520
+		if ($next_step === 'finalize_registration') {
1521
+			echo '<div id="spco-extra-finalize_registration-inputs-dv"></div>';
1522
+		}
1523
+	}
1524
+
1525
+
1526
+	/**
1527
+	 * @return void
1528
+	 */
1529
+	public static function display_registration_footer()
1530
+	{
1531
+		if (
1532
+			apply_filters(
1533
+				'FHEE__EE_Front__Controller__show_reg_footer',
1534
+				EE_Registry::instance()->CFG->admin->show_reg_footer
1535
+			)
1536
+		) {
1537
+			add_filter(
1538
+				'FHEE__EEH_Template__powered_by_event_espresso__url',
1539
+				function ($url) {
1540
+					return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1541
+				}
1542
+			);
1543
+			echo apply_filters(
1544
+				'FHEE__EE_Front_Controller__display_registration_footer',
1545
+				EEH_Template::powered_by_event_espresso(
1546
+					'',
1547
+					'espresso-registration-footer-dv',
1548
+					['utm_content' => 'registration_checkout']
1549
+				)
1550
+			);
1551
+		}
1552
+	}
1553
+
1554
+
1555
+	/**
1556
+	 * @return void
1557
+	 * @throws EE_Error
1558
+	 * @throws ReflectionException
1559
+	 */
1560
+	public function unlock_transaction()
1561
+	{
1562
+		if ($this->checkout instanceof EE_Checkout && $this->checkout->transaction instanceof EE_Transaction) {
1563
+			$this->checkout->transaction->unlock();
1564
+		}
1565
+	}
1566
+
1567
+
1568
+	/**
1569
+	 * @return void
1570
+	 */
1571
+	private function _setup_redirect()
1572
+	{
1573
+		if ($this->checkout->continue_reg && $this->checkout->next_step instanceof EE_SPCO_Reg_Step) {
1574
+			$this->checkout->redirect = true;
1575
+			if (empty($this->checkout->redirect_url)) {
1576
+				$this->checkout->redirect_url = $this->checkout->next_step->reg_step_url();
1577
+			}
1578
+			$this->checkout->redirect_url = apply_filters(
1579
+				'FHEE__EED_Single_Page_Checkout___setup_redirect__checkout_redirect_url',
1580
+				$this->checkout->redirect_url,
1581
+				$this->checkout
1582
+			);
1583
+		}
1584
+	}
1585
+
1586
+
1587
+	/**
1588
+	 * handle ajax message responses and redirects
1589
+	 *
1590
+	 * @return void
1591
+	 * @throws EE_Error
1592
+	 * @throws ReflectionException
1593
+	 */
1594
+	public function go_to_next_step()
1595
+	{
1596
+		if ($this->request->isAjax()) {
1597
+			// capture contents of output buffer we started earlier in the request, and insert into JSON response
1598
+			$this->checkout->json_response->set_unexpected_errors(ob_get_clean());
1599
+		}
1600
+		$this->unlock_transaction();
1601
+		// just return for these conditions
1602
+		if (
1603
+			$this->checkout->admin_request
1604
+			|| $this->checkout->action === 'redirect_form'
1605
+			|| $this->checkout->action === 'update_checkout'
1606
+		) {
1607
+			return;
1608
+		}
1609
+		// AJAX response
1610
+		$this->_handle_json_response();
1611
+		// redirect to next step or the Thank-You page
1612
+		$this->_handle_html_redirects();
1613
+		// hmmm... must be something wrong, so let's just display the form again !
1614
+		$this->_display_spco_reg_form();
1615
+	}
1616
+
1617
+
1618
+	/**
1619
+	 * @return void
1620
+	 */
1621
+	protected function _handle_json_response()
1622
+	{
1623
+		// if this is an ajax request
1624
+		if ($this->request->isAjax()) {
1625
+			$this->checkout->json_response->set_registration_time_limit(
1626
+				$this->checkout->get_registration_time_limit()
1627
+			);
1628
+			$this->checkout->json_response->set_payment_amount($this->checkout->amount_owing);
1629
+			/** @var EE_SPCO_JSON_Response $json_response */
1630
+			$json_response = apply_filters(
1631
+				'FHEE__EE_Single_Page_Checkout__JSON_response',
1632
+				$this->checkout->json_response
1633
+			);
1634
+			// just send the ajax
1635
+			$json_response->sendResponse();
1636
+		}
1637
+	}
1638
+
1639
+
1640
+	/**
1641
+	 * @return void
1642
+	 */
1643
+	protected function _handle_html_redirects()
1644
+	{
1645
+		// going somewhere ?
1646
+		if ($this->checkout->redirect && ! empty($this->checkout->redirect_url)) {
1647
+			// store notices in a transient
1648
+			EE_Error::get_notices(false, true);
1649
+			wp_safe_redirect($this->checkout->redirect_url);
1650
+			exit();
1651
+		}
1652
+	}
1653
+
1654
+
1655
+	/**
1656
+	 * @return void
1657
+	 */
1658
+	public function set_checkout_anchor()
1659
+	{
1660
+		echo '<a id="checkout" style="float: left; margin-left: -999em;"></a>';
1661
+	}
1662
+
1663
+
1664
+	/**
1665
+	 * @return string
1666
+	 * @since 4.9.59.p
1667
+	 */
1668
+	public static function getRegistrationExpirationNotice(): string
1669
+	{
1670
+		return sprintf(
1671
+			esc_html__(
1672
+				'%1$sWe\'re sorry, but your registration time has expired.%2$s%3$s%4$sIf you still wish to complete your registration, please return to the %5$sEvent List%6$sEvent List%7$s and reselect your tickets if available. Please accept our apologies for any inconvenience this may have caused.%8$s',
1673
+				'event_espresso'
1674
+			),
1675
+			'<h4 class="important-notice">',
1676
+			'</h4>',
1677
+			'<br />',
1678
+			'<p>',
1679
+			'<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" title="',
1680
+			'">',
1681
+			'</a>',
1682
+			'</p>'
1683
+		);
1684
+	}
1685 1685
 }
Please login to merge, or discard this patch.
Spacing   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
 
52 52
     public ?EE_Session $session = null;
53 53
 
54
-    private bool $debug = false;    //  true    false
54
+    private bool $debug = false; //  true    false
55 55
 
56 56
 
57 57
     /**
@@ -115,7 +115,7 @@  discard block
 block discarded – undo
115 115
     public static function set_hooks_admin()
116 116
     {
117 117
         EED_Single_Page_Checkout::set_definitions();
118
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
118
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
119 119
             return;
120 120
         }
121 121
         // going to start an output buffer in case anything gets accidentally output
@@ -209,14 +209,14 @@  discard block
 block discarded – undo
209 209
         }
210 210
         define(
211 211
             'SPCO_BASE_PATH',
212
-            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/') . '/'
212
+            rtrim(str_replace(['\\', '/'], '/', plugin_dir_path(__FILE__)), '/').'/'
213 213
         );
214
-        define('SPCO_CSS_URL', plugin_dir_url(__FILE__) . 'css/');
215
-        define('SPCO_IMG_URL', plugin_dir_url(__FILE__) . 'img/');
216
-        define('SPCO_JS_URL', plugin_dir_url(__FILE__) . 'js/');
217
-        define('SPCO_INC_PATH', SPCO_BASE_PATH . 'inc/');
218
-        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH . 'reg_steps/');
219
-        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH . 'templates/');
214
+        define('SPCO_CSS_URL', plugin_dir_url(__FILE__).'css/');
215
+        define('SPCO_IMG_URL', plugin_dir_url(__FILE__).'img/');
216
+        define('SPCO_JS_URL', plugin_dir_url(__FILE__).'js/');
217
+        define('SPCO_INC_PATH', SPCO_BASE_PATH.'inc/');
218
+        define('SPCO_REG_STEPS_PATH', SPCO_BASE_PATH.'reg_steps/');
219
+        define('SPCO_TEMPLATES_PATH', SPCO_BASE_PATH.'templates/');
220 220
         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(SPCO_BASE_PATH, true);
221 221
         EE_Registry::$i18n_js_strings['registration_expiration_notice'] =
222 222
             EED_Single_Page_Checkout::getRegistrationExpirationNotice();
@@ -247,7 +247,7 @@  discard block
 block discarded – undo
247 247
             // we need a
248 248
             if (isset($reg_step['file_path'], $reg_step['class_name'], $reg_step['slug'])) {
249 249
                 // copy over to the reg_steps_array
250
-                EED_Single_Page_Checkout::$_reg_steps_array[ $order ] = $reg_step;
250
+                EED_Single_Page_Checkout::$_reg_steps_array[$order] = $reg_step;
251 251
                 // register custom key route for each reg step
252 252
                 // ie: step=>"slug" - this is the entire reason we load the reg steps array now
253 253
                 EED_Module::registerRoute(
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
                 // add AJAX or other hooks
260 260
                 if (isset($reg_step['has_hooks']) && $reg_step['has_hooks']) {
261 261
                     // setup autoloaders if necessary
262
-                    if (! class_exists($reg_step['class_name'])) {
262
+                    if ( ! class_exists($reg_step['class_name'])) {
263 263
                         EEH_Autoloader::register_autoloaders_for_each_file_in_folder(
264 264
                             $reg_step['file_path'],
265 265
                             true
@@ -286,19 +286,19 @@  discard block
 block discarded – undo
286 286
         if (empty($reg_steps)) {
287 287
             $reg_steps = [
288 288
                 10  => [
289
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'attendee_information',
289
+                    'file_path'  => SPCO_REG_STEPS_PATH.'attendee_information',
290 290
                     'class_name' => 'EE_SPCO_Reg_Step_Attendee_Information',
291 291
                     'slug'       => 'attendee_information',
292 292
                     'has_hooks'  => false,
293 293
                 ],
294 294
                 30  => [
295
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'payment_options',
295
+                    'file_path'  => SPCO_REG_STEPS_PATH.'payment_options',
296 296
                     'class_name' => 'EE_SPCO_Reg_Step_Payment_Options',
297 297
                     'slug'       => 'payment_options',
298 298
                     'has_hooks'  => true,
299 299
                 ],
300 300
                 999 => [
301
-                    'file_path'  => SPCO_REG_STEPS_PATH . 'finalize_registration',
301
+                    'file_path'  => SPCO_REG_STEPS_PATH.'finalize_registration',
302 302
                     'class_name' => 'EE_SPCO_Reg_Step_Finalize_Registration',
303 303
                     'slug'       => 'finalize_registration',
304 304
                     'has_hooks'  => false,
@@ -444,7 +444,7 @@  discard block
 block discarded – undo
444 444
                 $this->checkout
445 445
             );
446 446
             // load the reg steps array
447
-            if (! $this->_load_and_instantiate_reg_steps()) {
447
+            if ( ! $this->_load_and_instantiate_reg_steps()) {
448 448
                 EED_Single_Page_Checkout::$_initialized = true;
449 449
                 return;
450 450
             }
@@ -453,7 +453,7 @@  discard block
 block discarded – undo
453 453
             // and the next step
454 454
             $this->checkout->set_next_step();
455 455
             // verify that everything has been set up correctly
456
-            if (! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
456
+            if ( ! ($this->_verify_transaction_and_get_registrations() && $this->_final_verifications())) {
457 457
                 EED_Single_Page_Checkout::$_initialized = true;
458 458
                 return;
459 459
             }
@@ -469,7 +469,7 @@  discard block
 block discarded – undo
469 469
             // DEBUG LOG
470 470
             // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
471 471
             // get reg form
472
-            if (! $this->_check_form_submission()) {
472
+            if ( ! $this->_check_form_submission()) {
473 473
                 EED_Single_Page_Checkout::$_initialized = true;
474 474
                 return;
475 475
             }
@@ -499,9 +499,9 @@  discard block
 block discarded – undo
499 499
      */
500 500
     private function _verify_session()
501 501
     {
502
-        if (! $this->session instanceof EE_Session) {
502
+        if ( ! $this->session instanceof EE_Session) {
503 503
             $this->session = LoaderFactory::getShared(EE_Session::class);
504
-            if (! $this->session instanceof EE_Session) {
504
+            if ( ! $this->session instanceof EE_Session) {
505 505
                 throw new EE_Error(esc_html__('The EE_Session class could not be loaded.', 'event_espresso'));
506 506
             }
507 507
         }
@@ -516,7 +516,7 @@  discard block
 block discarded – undo
516 516
         ) {
517 517
             $this->checkout = new EE_Checkout();
518 518
             $this->session->clear_session(__CLASS__, __FUNCTION__);
519
-            if (! $clear_session_requested) {
519
+            if ( ! $clear_session_requested) {
520 520
                 EE_Error::add_attention(
521 521
                     EE_Registry::$i18n_js_strings['registration_expiration_notice'],
522 522
                     __FILE__,
@@ -541,7 +541,7 @@  discard block
 block discarded – undo
541 541
         /** @type EE_Checkout $checkout */
542 542
         $checkout = $this->session->checkout();
543 543
         // verify
544
-        if (! $checkout instanceof EE_Checkout) {
544
+        if ( ! $checkout instanceof EE_Checkout) {
545 545
             // instantiate EE_Checkout object for handling the properties of the current checkout process
546 546
             $checkout = EE_Registry::instance()->load_file(
547 547
                 SPCO_INC_PATH,
@@ -559,7 +559,7 @@  discard block
 block discarded – undo
559 559
         }
560 560
         $checkout = apply_filters('FHEE__EED_Single_Page_Checkout___initialize_checkout__checkout', $checkout);
561 561
         // verify again
562
-        if (! $checkout instanceof EE_Checkout) {
562
+        if ( ! $checkout instanceof EE_Checkout) {
563 563
             throw new EE_Error(esc_html__('The EE_Checkout class could not be loaded.', 'event_espresso'));
564 564
         }
565 565
         // reset anything that needs a clean slate for each request
@@ -616,7 +616,7 @@  discard block
 block discarded – undo
616 616
      */
617 617
     protected function _display_request_vars()
618 618
     {
619
-        if (! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
619
+        if ( ! ($this->debug && defined('WP_DEBUG') && WP_DEBUG)) {
620 620
             return;
621 621
         }
622 622
         EEH_Debug_Tools::printr($this->request->requestParams(), 'requestParams', __FILE__, __LINE__);
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
         ) {
689 689
             // if not, then loop through raw reg steps array
690 690
             foreach (EED_Single_Page_Checkout::$_reg_steps_array as $order => $reg_step) {
691
-                if (! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
691
+                if ( ! $this->_load_and_instantiate_reg_step($reg_step, $order)) {
692 692
                     return false;
693 693
                 }
694 694
             }
@@ -810,12 +810,12 @@  discard block
 block discarded – undo
810 810
     private function _verify_transaction_and_get_registrations(): bool
811 811
     {
812 812
         // was there already a valid transaction in the checkout from the session ?
813
-        if (! $this->checkout->transaction instanceof EE_Transaction) {
813
+        if ( ! $this->checkout->transaction instanceof EE_Transaction) {
814 814
             // get transaction from db or session
815 815
             $this->checkout->transaction = $this->checkout->reg_url_link && ! is_admin()
816 816
                 ? $this->_get_transaction_and_cart_for_previous_visit()
817 817
                 : $this->_get_cart_for_current_session_and_setup_new_transaction();
818
-            if (! $this->checkout->transaction instanceof EE_Transaction) {
818
+            if ( ! $this->checkout->transaction instanceof EE_Transaction) {
819 819
                 EE_Error::add_error(
820 820
                     esc_html__(
821 821
                         'Your Registration and Transaction information could not be retrieved from the db.',
@@ -1044,10 +1044,10 @@  discard block
 block discarded – undo
1044 1044
                     );
1045 1045
                 }
1046 1046
                 $registration = EE_Registry::instance()->BUS->execute($CreateRegistrationCommand);
1047
-                if (! $registration instanceof EE_Registration) {
1047
+                if ( ! $registration instanceof EE_Registration) {
1048 1048
                     throw new InvalidEntityException($registration, 'EE_Registration');
1049 1049
                 }
1050
-                $registrations[ $registration->ID() ] = $registration;
1050
+                $registrations[$registration->ID()] = $registration;
1051 1051
             }
1052 1052
         }
1053 1053
         $registration_processor->fix_reg_final_price_rounding_issue($transaction);
@@ -1087,7 +1087,7 @@  discard block
 block discarded – undo
1087 1087
             $this->checkout
1088 1088
         );
1089 1089
         // verify that current step is still set correctly
1090
-        if (! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1090
+        if ( ! $this->checkout->current_step instanceof EE_SPCO_Reg_Step) {
1091 1091
             EE_Error::add_error(
1092 1092
                 esc_html__(
1093 1093
                     'We\'re sorry but the registration process can not proceed because one or more registration steps were not setup correctly. Please refresh the page and try again or contact support.',
@@ -1100,9 +1100,9 @@  discard block
 block discarded – undo
1100 1100
             return false;
1101 1101
         }
1102 1102
         // if returning to SPCO, then verify that primary registrant is set
1103
-        if (! empty($this->checkout->reg_url_link)) {
1103
+        if ( ! empty($this->checkout->reg_url_link)) {
1104 1104
             $valid_registrant = $this->checkout->transaction->primary_registration();
1105
-            if (! $valid_registrant instanceof EE_Registration) {
1105
+            if ( ! $valid_registrant instanceof EE_Registration) {
1106 1106
                 EE_Error::add_error(
1107 1107
                     esc_html__(
1108 1108
                         'We\'re sorry but there appears to be an error with the "reg_url_link" or the primary registrant for this transaction. Please refresh the page and try again or contact support.',
@@ -1127,7 +1127,7 @@  discard block
 block discarded – undo
1127 1127
                     $valid_registrant = $registration;
1128 1128
                 }
1129 1129
             }
1130
-            if (! $valid_registrant instanceof EE_Registration) {
1130
+            if ( ! $valid_registrant instanceof EE_Registration) {
1131 1131
                 // hmmm... maybe we have the wrong session because the user is opening multiple tabs ?
1132 1132
                 if (EED_Single_Page_Checkout::$_checkout_verified) {
1133 1133
                     // clear the session, mark the checkout as unverified, and try again
@@ -1170,9 +1170,9 @@  discard block
 block discarded – undo
1170 1170
         $this->checkout->set_reg_step_initiated($this->checkout->current_step);
1171 1171
         // loop thru all steps to call their individual "initialize" methods and set i18n strings for JS
1172 1172
         foreach ($this->checkout->reg_steps as $reg_step) {
1173
-            if (! $reg_step->initialize_reg_step()) {
1173
+            if ( ! $reg_step->initialize_reg_step()) {
1174 1174
                 // if not initialized then maybe this step is being removed...
1175
-                if (! $reinitializing && $reg_step->is_current_step()) {
1175
+                if ( ! $reinitializing && $reg_step->is_current_step()) {
1176 1176
                     // if it was the current step, then we need to start over here
1177 1177
                     $this->_initialize_reg_steps(true);
1178 1178
                     return;
@@ -1231,7 +1231,7 @@  discard block
 block discarded – undo
1231 1231
                         )
1232 1232
                     );
1233 1233
                     // validate submitted form data
1234
-                    if (! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1234
+                    if ( ! $this->checkout->continue_reg || ! $this->checkout->current_step->reg_form->is_valid()) {
1235 1235
                         // thou shall not pass !!!
1236 1236
                         $this->checkout->continue_reg = false;
1237 1237
                         // any form validation errors?
@@ -1305,7 +1305,7 @@  discard block
 block discarded – undo
1305 1305
                         ) {
1306 1306
                             EE_Error::add_success(
1307 1307
                                 $this->checkout->current_step->success_message()
1308
-                                . '<br />' . $this->checkout->next_step->_instructions()
1308
+                                . '<br />'.$this->checkout->next_step->_instructions()
1309 1309
                             );
1310 1310
                         }
1311 1311
                         // pack it up, pack it in...
@@ -1369,27 +1369,27 @@  discard block
 block discarded – undo
1369 1369
             'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
1370 1370
             'event_espresso'
1371 1371
         );
1372
-        EE_Registry::$i18n_js_strings['invalid_json_response']          = esc_html__(
1372
+        EE_Registry::$i18n_js_strings['invalid_json_response'] = esc_html__(
1373 1373
             'An invalid response was returned from the server while attempting to process your request. Please refresh the page and try again or contact support.',
1374 1374
             'event_espresso'
1375 1375
         );
1376
-        EE_Registry::$i18n_js_strings['validation_error']               = esc_html__(
1376
+        EE_Registry::$i18n_js_strings['validation_error'] = esc_html__(
1377 1377
             'There appears to be a problem with the form validation configuration! Please check the admin settings or contact support.',
1378 1378
             'event_espresso'
1379 1379
         );
1380
-        EE_Registry::$i18n_js_strings['invalid_payment_method']         = esc_html__(
1380
+        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
1381 1381
             'There appears to be a problem with the payment method configuration! Please refresh the page and try again or contact support.',
1382 1382
             'event_espresso'
1383 1383
         );
1384
-        EE_Registry::$i18n_js_strings['reg_step_error']                 = esc_html__(
1384
+        EE_Registry::$i18n_js_strings['reg_step_error'] = esc_html__(
1385 1385
             'This registration step could not be completed. Please refresh the page and try again.',
1386 1386
             'event_espresso'
1387 1387
         );
1388
-        EE_Registry::$i18n_js_strings['invalid_coupon']                 = esc_html__(
1388
+        EE_Registry::$i18n_js_strings['invalid_coupon'] = esc_html__(
1389 1389
             'We\'re sorry but that coupon code does not appear to be valid. If this is incorrect, please contact the site administrator.',
1390 1390
             'event_espresso'
1391 1391
         );
1392
-        EE_Registry::$i18n_js_strings['process_registration']           = sprintf(
1392
+        EE_Registry::$i18n_js_strings['process_registration'] = sprintf(
1393 1393
             esc_html__(
1394 1394
                 'Please wait while we process your registration.%sDo not refresh the page or navigate away while this is happening.%sThank you for your patience.',
1395 1395
                 'event_espresso'
@@ -1421,7 +1421,7 @@  discard block
 block discarded – undo
1421 1421
             'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit',
1422 1422
             true
1423 1423
         );
1424
-        EE_Registry::$i18n_js_strings['session_extension']              = absint(
1424
+        EE_Registry::$i18n_js_strings['session_extension'] = absint(
1425 1425
             apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS)
1426 1426
         );
1427 1427
         EE_Registry::$i18n_js_strings['session_expiration']    = $this->session->expiration();
@@ -1439,7 +1439,7 @@  discard block
 block discarded – undo
1439 1439
         // load css
1440 1440
         wp_register_style(
1441 1441
             'single_page_checkout',
1442
-            SPCO_CSS_URL . 'single_page_checkout.css',
1442
+            SPCO_CSS_URL.'single_page_checkout.css',
1443 1443
             ['espresso_default'],
1444 1444
             EVENT_ESPRESSO_VERSION
1445 1445
         );
@@ -1447,7 +1447,7 @@  discard block
 block discarded – undo
1447 1447
         // load JS
1448 1448
         wp_register_script(
1449 1449
             'single_page_checkout',
1450
-            SPCO_JS_URL . 'single_page_checkout.js',
1450
+            SPCO_JS_URL.'single_page_checkout.js',
1451 1451
             ['espresso_core', 'underscore', 'ee_form_section_validation'],
1452 1452
             EVENT_ESPRESSO_VERSION,
1453 1453
             true
@@ -1470,7 +1470,7 @@  discard block
 block discarded – undo
1470 1470
          *      AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__attendee_information
1471 1471
          */
1472 1472
         do_action(
1473
-            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__' . $this->checkout->current_step->slug(),
1473
+            'AHEE__EED_Single_Page_Checkout__enqueue_styles_and_scripts__'.$this->checkout->current_step->slug(),
1474 1474
             $this
1475 1475
         );
1476 1476
     }
@@ -1536,7 +1536,7 @@  discard block
 block discarded – undo
1536 1536
         ) {
1537 1537
             add_filter(
1538 1538
                 'FHEE__EEH_Template__powered_by_event_espresso__url',
1539
-                function ($url) {
1539
+                function($url) {
1540 1540
                     return apply_filters('FHEE__EE_Front_Controller__registration_footer__url', $url);
1541 1541
                 }
1542 1542
             );
@@ -1676,7 +1676,7 @@  discard block
 block discarded – undo
1676 1676
             '</h4>',
1677 1677
             '<br />',
1678 1678
             '<p>',
1679
-            '<a href="' . get_post_type_archive_link(EspressoPostType::EVENTS) . '" title="',
1679
+            '<a href="'.get_post_type_archive_link(EspressoPostType::EVENTS).'" title="',
1680 1680
             '">',
1681 1681
             '</a>',
1682 1682
             '</p>'
Please login to merge, or discard this patch.
single_page_checkout/templates/registration_page_wrapper.template.php 2 patches
Indentation   +43 added lines, -43 removed lines patch added patch discarded remove patch
@@ -17,37 +17,37 @@  discard block
 block discarded – undo
17 17
 
18 18
 <div id="ee-single-page-checkout-dv">
19 19
     <?php
20
-    if (! $empty_cart) {
21
-        if ($use_session_countdown) { ?>
20
+	if (! $empty_cart) {
21
+		if ($use_session_countdown) { ?>
22 22
             <p id="spco-registration-time-limit-pg" class="spco-steps-pg ee-attention important-notice">
23 23
                 <?php echo sprintf(
24
-                    apply_filters(
25
-                        'FHEE__registration_page_wrapper_template___time_limit',
26
-                        esc_html__('You have %1$s to complete your registration.', 'event_espresso')
27
-                    ),
28
-                    '<span id="spco-registration-time-limit-spn" class="spco-registration-time-limit-spn">'
29
-                    . $registration_time_limit
30
-                    . '</span>'
31
-                );
32
-                ?>
24
+					apply_filters(
25
+						'FHEE__registration_page_wrapper_template___time_limit',
26
+						esc_html__('You have %1$s to complete your registration.', 'event_espresso')
27
+					),
28
+					'<span id="spco-registration-time-limit-spn" class="spco-registration-time-limit-spn">'
29
+					. $registration_time_limit
30
+					. '</span>'
31
+				);
32
+				?>
33 33
                 <span id="spco-registration-expiration-spn" class="" style="display:none;"></span>
34 34
             </p>
35 35
         <?php }
36
-        if (! $revisit && apply_filters('FHEE__registration_page_wrapper_template__steps_display', true)) {
37
-            ?>
36
+		if (! $revisit && apply_filters('FHEE__registration_page_wrapper_template__steps_display', true)) {
37
+			?>
38 38
             <h2 id="spco-steps-big-hdr" class="spco-steps-big-hdr">
39 39
                 <?php esc_html_e(' Steps', 'event_espresso'); ?>
40 40
             </h2>
41 41
 
42 42
             <div id="spco-steps-display-dv">
43 43
                 <?php
44
-                $step_nmbr = 1;
45
-                $total_steps = count($reg_steps) - 1;
46
-                foreach ($reg_steps as $reg_step) {
47
-                    if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() != 'finalize_registration') {
48
-                        $slug = $reg_step->slug();
49
-                        $step_display_dv_class = $reg_step->is_current_step() ? 'active-step' : 'inactive-step';
50
-                        ?>
44
+				$step_nmbr = 1;
45
+				$total_steps = count($reg_steps) - 1;
46
+				foreach ($reg_steps as $reg_step) {
47
+					if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() != 'finalize_registration') {
48
+						$slug = $reg_step->slug();
49
+						$step_display_dv_class = $reg_step->is_current_step() ? 'active-step' : 'inactive-step';
50
+						?>
51 51
                         <div id="spco-step-<?php echo esc_attr($slug); ?>-display-dv"
52 52
                              class="spco-step-display-dv <?php echo esc_attr($step_display_dv_class); ?> steps-<?php echo esc_attr($total_steps); ?>"
53 53
                         >
@@ -60,28 +60,28 @@  discard block
 block discarded – undo
60 60
                         </div>
61 61
 
62 62
                         <?php
63
-                        if ($step_nmbr < $total_steps) { ?>
63
+						if ($step_nmbr < $total_steps) { ?>
64 64
                             <div class="spco-step-arrow-dv">&raquo;</div>
65 65
                             <?php
66
-                        }
67
-                        $step_nmbr++;
68
-                    }
69
-                }
70
-                ?>
66
+						}
67
+						$step_nmbr++;
68
+					}
69
+				}
70
+				?>
71 71
                 <div class="clear-float"></div>
72 72
             </div>
73 73
 
74 74
             <?php
75
-        }
75
+		}
76 76
 
77
-        do_action('AHEE__SPCO__before_registration_steps');
78
-        $step_nmbr = 1;
79
-        foreach ($reg_steps as $reg_step) {
80
-            if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() != 'finalize_registration') {
81
-                $slug = $reg_step->slug();
82
-                do_action('AHEE__' . $slug . '__reg_step_start', $reg_step);
83
-                // todo: deprecate hook AHEE__registration_page_attendee_information__start
84
-                ?>
77
+		do_action('AHEE__SPCO__before_registration_steps');
78
+		$step_nmbr = 1;
79
+		foreach ($reg_steps as $reg_step) {
80
+			if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() != 'finalize_registration') {
81
+				$slug = $reg_step->slug();
82
+				do_action('AHEE__' . $slug . '__reg_step_start', $reg_step);
83
+				// todo: deprecate hook AHEE__registration_page_attendee_information__start
84
+				?>
85 85
                 <div id="spco-<?php echo esc_attr($slug); ?>-dv"
86 86
                      class="spco-step-dv <?php echo esc_attr($reg_step->div_class()); ?>"
87 87
                 >
@@ -89,19 +89,19 @@  discard block
 block discarded – undo
89 89
                     <?php do_action('AHEE__SPCO_after_reg_step_form', $slug, $next_step); ?>
90 90
                 </div>
91 91
                 <?php $step_nmbr++;
92
-            }
93
-        }
94
-        do_action('AHEE__SPCO__after_registration_steps');
95
-    } else {
96
-        ?>
92
+			}
93
+		}
94
+		do_action('AHEE__SPCO__after_registration_steps');
95
+	} else {
96
+		?>
97 97
         <h3 id="spco-empty-cart-hdr" class="spco-step-title-hdr">
98 98
             <?php esc_html_e('Nothing in your Event Queue', 'event_espresso'); ?>
99 99
         </h3>
100 100
         <p><?php echo wp_kses($empty_msg, AllowedTags::getWithFormTags()); ?></p>
101 101
         <?php echo wp_kses($cookies_not_set_msg, AllowedTags::getWithFormTags()); ?>
102 102
         <?php
103
-    }
104
-    do_action('AHEE__SPCO__reg_form_footer');
105
-    ?>
103
+	}
104
+	do_action('AHEE__SPCO__reg_form_footer');
105
+	?>
106 106
 
107 107
 </div>
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
 
18 18
 <div id="ee-single-page-checkout-dv">
19 19
     <?php
20
-    if (! $empty_cart) {
20
+    if ( ! $empty_cart) {
21 21
         if ($use_session_countdown) { ?>
22 22
             <p id="spco-registration-time-limit-pg" class="spco-steps-pg ee-attention important-notice">
23 23
                 <?php echo sprintf(
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
                 <span id="spco-registration-expiration-spn" class="" style="display:none;"></span>
34 34
             </p>
35 35
         <?php }
36
-        if (! $revisit && apply_filters('FHEE__registration_page_wrapper_template__steps_display', true)) {
36
+        if ( ! $revisit && apply_filters('FHEE__registration_page_wrapper_template__steps_display', true)) {
37 37
             ?>
38 38
             <h2 id="spco-steps-big-hdr" class="spco-steps-big-hdr">
39 39
                 <?php esc_html_e(' Steps', 'event_espresso'); ?>
@@ -79,7 +79,7 @@  discard block
 block discarded – undo
79 79
         foreach ($reg_steps as $reg_step) {
80 80
             if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() != 'finalize_registration') {
81 81
                 $slug = $reg_step->slug();
82
-                do_action('AHEE__' . $slug . '__reg_step_start', $reg_step);
82
+                do_action('AHEE__'.$slug.'__reg_step_start', $reg_step);
83 83
                 // todo: deprecate hook AHEE__registration_page_attendee_information__start
84 84
                 ?>
85 85
                 <div id="spco-<?php echo esc_attr($slug); ?>-dv"
Please login to merge, or discard this patch.
modules/single_page_checkout/form/LegacySpcoForm.php 2 patches
Indentation   +67 added lines, -67 removed lines patch added patch discarded remove patch
@@ -17,74 +17,74 @@
 block discarded – undo
17 17
  */
18 18
 class LegacySpcoForm extends EE_Form_Section_Proper
19 19
 {
20
-    public function __construct(EE_Checkout $checkout, bool $empty_cart, int $session_expiration)
21
-    {
22
-        parent::__construct(
23
-            [
24
-                'name'            => 'single-page-checkout',
25
-                'html_id'         => 'ee-single-page-checkout-dv',
26
-                'layout_strategy' =>
27
-                    new EE_Template_Layout(
28
-                        [
29
-                            'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
30
-                            'template_args'        => [
31
-                                'empty_cart'              => $empty_cart,
32
-                                'revisit'                 => $checkout->revisit,
33
-                                'reg_steps'               => $checkout->reg_steps,
34
-                                'next_step'               => $checkout->next_step instanceof EE_SPCO_Reg_Step
35
-                                    ? $checkout->next_step->slug()
36
-                                    : '',
37
-                                'empty_msg'               => apply_filters(
38
-                                    'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
39
-                                    sprintf(
40
-                                        esc_html__(
41
-                                            'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
42
-                                            'event_espresso'
43
-                                        ),
44
-                                        '<a href="'
45
-                                        . get_post_type_archive_link(EspressoPostType::EVENTS)
46
-                                        . '" title="',
47
-                                        '">',
48
-                                        '</a>'
49
-                                    )
50
-                                ),
51
-                                'cookies_not_set_msg'     => $this->getCookiesNotSetMessage($empty_cart),
52
-                                'registration_time_limit' => $checkout->get_registration_time_limit(),
53
-                                'session_expiration'      => gmdate(
54
-                                    'M d, Y H:i:s',
55
-                                    $session_expiration + (get_option('gmt_offset') * HOUR_IN_SECONDS)
56
-                                ),
57
-                                'use_session_countdown'   => EE_Registry::instance()->CFG->registration->useSessionCountdown(),
58
-                            ],
59
-                        ]
60
-                    ),
61
-            ]
62
-        );
63
-    }
20
+	public function __construct(EE_Checkout $checkout, bool $empty_cart, int $session_expiration)
21
+	{
22
+		parent::__construct(
23
+			[
24
+				'name'            => 'single-page-checkout',
25
+				'html_id'         => 'ee-single-page-checkout-dv',
26
+				'layout_strategy' =>
27
+					new EE_Template_Layout(
28
+						[
29
+							'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
30
+							'template_args'        => [
31
+								'empty_cart'              => $empty_cart,
32
+								'revisit'                 => $checkout->revisit,
33
+								'reg_steps'               => $checkout->reg_steps,
34
+								'next_step'               => $checkout->next_step instanceof EE_SPCO_Reg_Step
35
+									? $checkout->next_step->slug()
36
+									: '',
37
+								'empty_msg'               => apply_filters(
38
+									'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
39
+									sprintf(
40
+										esc_html__(
41
+											'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
42
+											'event_espresso'
43
+										),
44
+										'<a href="'
45
+										. get_post_type_archive_link(EspressoPostType::EVENTS)
46
+										. '" title="',
47
+										'">',
48
+										'</a>'
49
+									)
50
+								),
51
+								'cookies_not_set_msg'     => $this->getCookiesNotSetMessage($empty_cart),
52
+								'registration_time_limit' => $checkout->get_registration_time_limit(),
53
+								'session_expiration'      => gmdate(
54
+									'M d, Y H:i:s',
55
+									$session_expiration + (get_option('gmt_offset') * HOUR_IN_SECONDS)
56
+								),
57
+								'use_session_countdown'   => EE_Registry::instance()->CFG->registration->useSessionCountdown(),
58
+							],
59
+						]
60
+					),
61
+			]
62
+		);
63
+	}
64 64
 
65 65
 
66
-    private function getCookiesNotSetMessage($empty_cart)
67
-    {
68
-        return $empty_cart
69
-            ? apply_filters(
70
-                'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
71
-                sprintf(
72
-                    esc_html__(
73
-                        '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
74
-                        'event_espresso'
75
-                    ),
76
-                    '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
77
-                    '</div>',
78
-                    '<h6 class="important-notice">',
79
-                    '</h6>',
80
-                    '<p>',
81
-                    '</p>',
82
-                    '<br />',
83
-                    '<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
84
-                    '</a>'
85
-                )
86
-            )
87
-            : '';
66
+	private function getCookiesNotSetMessage($empty_cart)
67
+	{
68
+		return $empty_cart
69
+			? apply_filters(
70
+				'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
71
+				sprintf(
72
+					esc_html__(
73
+						'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
74
+						'event_espresso'
75
+					),
76
+					'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
77
+					'</div>',
78
+					'<h6 class="important-notice">',
79
+					'</h6>',
80
+					'<p>',
81
+					'</p>',
82
+					'<br />',
83
+					'<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
84
+					'</a>'
85
+				)
86
+			)
87
+			: '';
88 88
 
89
-    }
89
+	}
90 90
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -26,7 +26,7 @@
 block discarded – undo
26 26
                 'layout_strategy' =>
27 27
                     new EE_Template_Layout(
28 28
                         [
29
-                            'layout_template_file' => SPCO_TEMPLATES_PATH . 'registration_page_wrapper.template.php',
29
+                            'layout_template_file' => SPCO_TEMPLATES_PATH.'registration_page_wrapper.template.php',
30 30
                             'template_args'        => [
31 31
                                 'empty_cart'              => $empty_cart,
32 32
                                 'revisit'                 => $checkout->revisit,
Please login to merge, or discard this patch.
modules/single_page_checkout/form/SinglePageCheckoutForm.php 2 patches
Indentation   +135 added lines, -135 removed lines patch added patch discarded remove patch
@@ -13,139 +13,139 @@
 block discarded – undo
13 13
 
14 14
 class SinglePageCheckoutForm extends EE_Form_Section_Proper
15 15
 {
16
-    private EE_Checkout $checkout;
17
-
18
-    private bool $empty_cart;
19
-
20
-    private array $subsections = [];
21
-
22
-
23
-    public function __construct(EE_Checkout $checkout, bool $empty_cart)
24
-    {
25
-        $this->checkout   = $checkout;
26
-        $this->empty_cart = $empty_cart;
27
-        parent::__construct(
28
-            [
29
-                'name'            => 'single-page-checkout',
30
-                'html_id'         => 'ee-single-page-checkout-dv',
31
-                'layout_strategy' => new EE_No_Layout(),
32
-                'subsections'     => $this->generateSubsections(),
33
-            ]
34
-        );
35
-    }
36
-
37
-
38
-    /**
39
-     * @throws EE_Error
40
-     */
41
-    private function generateSubsections(): array
42
-    {
43
-        $this->subsections['spco-div-open'] = new EE_Form_Section_HTML(
44
-            EEH_HTML::div('', 'ee-single-page-checkout-dv')
45
-        );
46
-
47
-        if ($this->empty_cart) {
48
-            $this->subsections['empty-cart-notice'] = new EmptyCartNotice();
49
-        } else {
50
-            $this->addTimeLimitNotice();
51
-            $this->addRegStepsHeader();
52
-            $this->addRegStepHookPoint('AHEE__SPCO__before_registration_steps');
53
-            $this->addRegistrationSteps();
54
-            $this->addRegStepHookPoint('AHEE__SPCO__after_registration_steps');
55
-        }
56
-
57
-        $this->addRegStepHookPoint('AHEE__SPCO__reg_form_footer');
58
-
59
-        $this->subsections['spco-div-close'] = new EE_Form_Section_HTML(
60
-            EEH_HTML::divx('ee-single-page-checkout-dv')
61
-        );
62
-
63
-        return $this->subsections;
64
-    }
65
-
66
-
67
-    private function addTimeLimitNotice()
68
-    {
69
-        if (
70
-            ! EE_Registry::instance()->CFG->registration->useSessionCountdown() ||
71
-            ! apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)
72
-        ) {
73
-            return;
74
-        }
75
-
76
-        $this->subsections['registration_time_limit'] = new EE_Form_Section_HTML(
77
-            EEH_HTML::p(
78
-                sprintf(
79
-                    apply_filters(
80
-                        'FHEE__registration_page_wrapper_template___time_limit',
81
-                        esc_html__('You have %1$s to complete your registration.', 'event_espresso')
82
-                    ),
83
-                    EEH_HTML::span(
84
-                        $this->checkout->get_registration_time_limit(),
85
-                        'spco-registration-time-limit-spn',
86
-                        'spco-registration-time-limit-spn'
87
-                    )
88
-                ),
89
-                'spco-registration-time-limit-pg',
90
-                'spco-steps-pg ee-attention important-notice',
91
-                'display: none;'
92
-            )
93
-        );
94
-    }
95
-
96
-    private function addRegStepsHeader(): void
97
-    {
98
-        if (
99
-            $this->checkout->revisit
100
-            || ! apply_filters('FHEE__registration_page_wrapper_template__steps_display', true)
101
-        ) {
102
-            return;
103
-        }
104
-        $this->subsections['registration_steps_display'] = new RegStepsHeader($this->checkout);
105
-    }
106
-
107
-
108
-    private function addRegStepHookPoint(string $hook_name)
109
-    {
110
-        $key = str_replace('AHEE__SPCO__', '', $hook_name);
111
-        $this->subsections[ $key ] = new EE_Form_Section_HTML($this->captureRegStepHookPoint($hook_name));
112
-    }
113
-
114
-    private function captureRegStepHookPoint()
115
-    {
116
-        $args = func_get_args();
117
-        ob_start();
118
-        do_action(...$args);
119
-        return ob_get_clean();
120
-    }
121
-
122
-
123
-    /**
124
-     * @throws EE_Error
125
-     */
126
-    private function addRegistrationSteps()
127
-    {
128
-        $reg_steps = '';
129
-        foreach ($this->checkout->reg_steps as $reg_step) {
130
-            if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() !== 'finalize_registration') {
131
-                $slug = $reg_step->slug();
132
-                $reg_steps .= $this->captureRegStepHookPoint("AHEE__{$slug}__reg_step_start", $reg_step);
133
-                $reg_form_html = $reg_step->display_reg_form();
134
-                $reg_steps .= EEH_HTML::div(
135
-                    $reg_form_html
136
-                    . $this->captureRegStepHookPoint(
137
-                        'AHEE__SPCO_after_reg_step_form',
138
-                        $slug,
139
-                        $this->checkout->next_step->slug()
140
-                    ),
141
-                    'spco-' . esc_attr($slug) . '-dv',
142
-                    "spco-step-dv " . esc_attr($reg_step->div_class())
143
-                );
144
-                if (empty($reg_form_html)) {
145
-                    $reg_steps .= EEH_HTML::divx();
146
-                }
147
-            }
148
-        }
149
-        $this->subsections['registration_steps'] = new EE_Form_Section_HTML($reg_steps);
150
-    }
16
+	private EE_Checkout $checkout;
17
+
18
+	private bool $empty_cart;
19
+
20
+	private array $subsections = [];
21
+
22
+
23
+	public function __construct(EE_Checkout $checkout, bool $empty_cart)
24
+	{
25
+		$this->checkout   = $checkout;
26
+		$this->empty_cart = $empty_cart;
27
+		parent::__construct(
28
+			[
29
+				'name'            => 'single-page-checkout',
30
+				'html_id'         => 'ee-single-page-checkout-dv',
31
+				'layout_strategy' => new EE_No_Layout(),
32
+				'subsections'     => $this->generateSubsections(),
33
+			]
34
+		);
35
+	}
36
+
37
+
38
+	/**
39
+	 * @throws EE_Error
40
+	 */
41
+	private function generateSubsections(): array
42
+	{
43
+		$this->subsections['spco-div-open'] = new EE_Form_Section_HTML(
44
+			EEH_HTML::div('', 'ee-single-page-checkout-dv')
45
+		);
46
+
47
+		if ($this->empty_cart) {
48
+			$this->subsections['empty-cart-notice'] = new EmptyCartNotice();
49
+		} else {
50
+			$this->addTimeLimitNotice();
51
+			$this->addRegStepsHeader();
52
+			$this->addRegStepHookPoint('AHEE__SPCO__before_registration_steps');
53
+			$this->addRegistrationSteps();
54
+			$this->addRegStepHookPoint('AHEE__SPCO__after_registration_steps');
55
+		}
56
+
57
+		$this->addRegStepHookPoint('AHEE__SPCO__reg_form_footer');
58
+
59
+		$this->subsections['spco-div-close'] = new EE_Form_Section_HTML(
60
+			EEH_HTML::divx('ee-single-page-checkout-dv')
61
+		);
62
+
63
+		return $this->subsections;
64
+	}
65
+
66
+
67
+	private function addTimeLimitNotice()
68
+	{
69
+		if (
70
+			! EE_Registry::instance()->CFG->registration->useSessionCountdown() ||
71
+			! apply_filters('FHEE__registration_page_wrapper_template__display_time_limit', false)
72
+		) {
73
+			return;
74
+		}
75
+
76
+		$this->subsections['registration_time_limit'] = new EE_Form_Section_HTML(
77
+			EEH_HTML::p(
78
+				sprintf(
79
+					apply_filters(
80
+						'FHEE__registration_page_wrapper_template___time_limit',
81
+						esc_html__('You have %1$s to complete your registration.', 'event_espresso')
82
+					),
83
+					EEH_HTML::span(
84
+						$this->checkout->get_registration_time_limit(),
85
+						'spco-registration-time-limit-spn',
86
+						'spco-registration-time-limit-spn'
87
+					)
88
+				),
89
+				'spco-registration-time-limit-pg',
90
+				'spco-steps-pg ee-attention important-notice',
91
+				'display: none;'
92
+			)
93
+		);
94
+	}
95
+
96
+	private function addRegStepsHeader(): void
97
+	{
98
+		if (
99
+			$this->checkout->revisit
100
+			|| ! apply_filters('FHEE__registration_page_wrapper_template__steps_display', true)
101
+		) {
102
+			return;
103
+		}
104
+		$this->subsections['registration_steps_display'] = new RegStepsHeader($this->checkout);
105
+	}
106
+
107
+
108
+	private function addRegStepHookPoint(string $hook_name)
109
+	{
110
+		$key = str_replace('AHEE__SPCO__', '', $hook_name);
111
+		$this->subsections[ $key ] = new EE_Form_Section_HTML($this->captureRegStepHookPoint($hook_name));
112
+	}
113
+
114
+	private function captureRegStepHookPoint()
115
+	{
116
+		$args = func_get_args();
117
+		ob_start();
118
+		do_action(...$args);
119
+		return ob_get_clean();
120
+	}
121
+
122
+
123
+	/**
124
+	 * @throws EE_Error
125
+	 */
126
+	private function addRegistrationSteps()
127
+	{
128
+		$reg_steps = '';
129
+		foreach ($this->checkout->reg_steps as $reg_step) {
130
+			if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() !== 'finalize_registration') {
131
+				$slug = $reg_step->slug();
132
+				$reg_steps .= $this->captureRegStepHookPoint("AHEE__{$slug}__reg_step_start", $reg_step);
133
+				$reg_form_html = $reg_step->display_reg_form();
134
+				$reg_steps .= EEH_HTML::div(
135
+					$reg_form_html
136
+					. $this->captureRegStepHookPoint(
137
+						'AHEE__SPCO_after_reg_step_form',
138
+						$slug,
139
+						$this->checkout->next_step->slug()
140
+					),
141
+					'spco-' . esc_attr($slug) . '-dv',
142
+					"spco-step-dv " . esc_attr($reg_step->div_class())
143
+				);
144
+				if (empty($reg_form_html)) {
145
+					$reg_steps .= EEH_HTML::divx();
146
+				}
147
+			}
148
+		}
149
+		$this->subsections['registration_steps'] = new EE_Form_Section_HTML($reg_steps);
150
+	}
151 151
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -108,7 +108,7 @@  discard block
 block discarded – undo
108 108
     private function addRegStepHookPoint(string $hook_name)
109 109
     {
110 110
         $key = str_replace('AHEE__SPCO__', '', $hook_name);
111
-        $this->subsections[ $key ] = new EE_Form_Section_HTML($this->captureRegStepHookPoint($hook_name));
111
+        $this->subsections[$key] = new EE_Form_Section_HTML($this->captureRegStepHookPoint($hook_name));
112 112
     }
113 113
 
114 114
     private function captureRegStepHookPoint()
@@ -138,8 +138,8 @@  discard block
 block discarded – undo
138 138
                         $slug,
139 139
                         $this->checkout->next_step->slug()
140 140
                     ),
141
-                    'spco-' . esc_attr($slug) . '-dv',
142
-                    "spco-step-dv " . esc_attr($reg_step->div_class())
141
+                    'spco-'.esc_attr($slug).'-dv',
142
+                    "spco-step-dv ".esc_attr($reg_step->div_class())
143 143
                 );
144 144
                 if (empty($reg_form_html)) {
145 145
                     $reg_steps .= EEH_HTML::divx();
Please login to merge, or discard this patch.
modules/single_page_checkout/form/EmptyCartNotice.php 1 patch
Indentation   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -8,66 +8,66 @@
 block discarded – undo
8 8
 
9 9
 class EmptyCartNotice extends EE_Form_Section_HTML
10 10
 {
11
-    public function __construct()
12
-    {
13
-        parent::__construct(
14
-            $this->nothingInYourCartHeader()
15
-            . $this->emptyCartMessage()
16
-            . $this->cookiesNotSetMessage()
17
-        );
18
-    }
11
+	public function __construct()
12
+	{
13
+		parent::__construct(
14
+			$this->nothingInYourCartHeader()
15
+			. $this->emptyCartMessage()
16
+			. $this->cookiesNotSetMessage()
17
+		);
18
+	}
19 19
 
20 20
 
21
-    private function nothingInYourCartHeader(): string
22
-    {
23
-        return EEH_HTML::h3(
24
-            esc_html__('Nothing in your Event Queue', 'event_espresso'),
25
-            'spco-empty-cart-hdr',
26
-            'spco-step-title-hdr'
27
-        );
28
-    }
21
+	private function nothingInYourCartHeader(): string
22
+	{
23
+		return EEH_HTML::h3(
24
+			esc_html__('Nothing in your Event Queue', 'event_espresso'),
25
+			'spco-empty-cart-hdr',
26
+			'spco-step-title-hdr'
27
+		);
28
+	}
29 29
 
30 30
 
31
-    private function emptyCartMessage(): string
32
-    {
33
-        return EEH_HTML::p(
34
-            apply_filters(
35
-                'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
36
-                sprintf(
37
-                    esc_html__(
38
-                        'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
39
-                        'event_espresso'
40
-                    ),
41
-                    '<a href="'
42
-                    . get_post_type_archive_link(EspressoPostType::EVENTS)
43
-                    . '" title="',
44
-                    '">',
45
-                    '</a>'
46
-                )
47
-            )
48
-        );
49
-    }
31
+	private function emptyCartMessage(): string
32
+	{
33
+		return EEH_HTML::p(
34
+			apply_filters(
35
+				'FHEE__Single_Page_Checkout__display_spco_reg_form__empty_msg',
36
+				sprintf(
37
+					esc_html__(
38
+						'You need to %1$sReturn to Events list%2$sselect at least one event%3$s before you can proceed with the registration process.',
39
+						'event_espresso'
40
+					),
41
+					'<a href="'
42
+					. get_post_type_archive_link(EspressoPostType::EVENTS)
43
+					. '" title="',
44
+					'">',
45
+					'</a>'
46
+				)
47
+			)
48
+		);
49
+	}
50 50
 
51 51
 
52
-    private function cookiesNotSetMessage(): string
53
-    {
54
-        return apply_filters(
55
-            'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
56
-            sprintf(
57
-                esc_html__(
58
-                    '%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
59
-                    'event_espresso'
60
-                ),
61
-                '<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
62
-                '</div>',
63
-                '<h6 class="important-notice">',
64
-                '</h6>',
65
-                '<p>',
66
-                '</p>',
67
-                '<br />',
68
-                '<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
69
-                '</a>'
70
-            )
71
-        );
72
-    }
52
+	private function cookiesNotSetMessage(): string
53
+	{
54
+		return apply_filters(
55
+			'FHEE__Single_Page_Checkout__display_spco_reg_form__cookies_not_set_msg',
56
+			sprintf(
57
+				esc_html__(
58
+					'%1$s%3$sIt appears your browser is not currently set to accept Cookies%4$s%5$sIn order to register for events, you need to enable cookies.%7$sIf you require assistance, then click the following link to learn how to %8$senable cookies%9$s%6$s%2$s',
59
+					'event_espresso'
60
+				),
61
+				'<div class="ee-attention hidden" id="ee-cookies-not-set-msg">',
62
+				'</div>',
63
+				'<h6 class="important-notice">',
64
+				'</h6>',
65
+				'<p>',
66
+				'</p>',
67
+				'<br />',
68
+				'<a href="https://www.whatismybrowser.com/guides/how-to-enable-cookies/" target="_blank" rel="noopener noreferrer">',
69
+				'</a>'
70
+			)
71
+		);
72
+	}
73 73
 }
Please login to merge, or discard this patch.
modules/single_page_checkout/form/RegStepsHeader.php 2 patches
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -9,61 +9,61 @@
 block discarded – undo
9 9
 
10 10
 class RegStepsHeader extends EE_Form_Section_HTML
11 11
 {
12
-    private EE_Checkout $checkout;
12
+	private EE_Checkout $checkout;
13 13
 
14 14
 
15
-    /**
16
-     * @param EE_Checkout $checkout
17
-     */
18
-    public function __construct(EE_Checkout $checkout)
19
-    {
20
-        $this->checkout = $checkout;
21
-        parent::__construct(
22
-            EEH_HTML::h2(
23
-                esc_html__('Steps', 'event_espresso'),
24
-                'spco-steps-big-hdr',
25
-                'spco-steps-big-hdr'
26
-            )
27
-            . EEH_HTML::div($this->regStepsHeader(), 'spco-steps-display-dv')
28
-        );
29
-    }
15
+	/**
16
+	 * @param EE_Checkout $checkout
17
+	 */
18
+	public function __construct(EE_Checkout $checkout)
19
+	{
20
+		$this->checkout = $checkout;
21
+		parent::__construct(
22
+			EEH_HTML::h2(
23
+				esc_html__('Steps', 'event_espresso'),
24
+				'spco-steps-big-hdr',
25
+				'spco-steps-big-hdr'
26
+			)
27
+			. EEH_HTML::div($this->regStepsHeader(), 'spco-steps-display-dv')
28
+		);
29
+	}
30 30
 
31 31
 
32
-    private function regStepsHeader(): string
33
-    {
34
-        $reg_steps = '';
35
-        $step_nmbr = 1;
36
-        $total_steps = count($this->checkout->reg_steps) - 1;
37
-        foreach ($this->checkout->reg_steps as $reg_step) {
38
-            if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() !== 'finalize_registration') {
39
-                $slug = esc_attr($reg_step->slug());
40
-                $step_display_dv_class = $reg_step->is_current_step() ? 'active-step' : 'inactive-step';
41
-                $reg_steps .= EEH_HTML::div(
42
-                    EEH_HTML::h4(
43
-                        EEH_HTML::span(
44
-                            esc_html($step_nmbr),
45
-                            '',
46
-                            'spco-step-big-nmbr'
47
-                        )
48
-                        . EEH_HTML::nbsp()
49
-                        . EEH_HTML::span(
50
-                            str_replace('&nbsp;', '<br/>&nbsp;', $reg_step->name()),
51
-                            '',
52
-                            'spco-step-name'
53
-                        ),
54
-                        "spco-step-$slug-display-hdr",
55
-                        'spco-steps-display-hdr'
56
-                    ),
57
-                    "spco-step-$slug-display-dv",
58
-                    "spco-step-display-dv $step_display_dv_class steps-$total_steps",
59
-                );
32
+	private function regStepsHeader(): string
33
+	{
34
+		$reg_steps = '';
35
+		$step_nmbr = 1;
36
+		$total_steps = count($this->checkout->reg_steps) - 1;
37
+		foreach ($this->checkout->reg_steps as $reg_step) {
38
+			if ($reg_step instanceof EE_SPCO_Reg_Step && $reg_step->slug() !== 'finalize_registration') {
39
+				$slug = esc_attr($reg_step->slug());
40
+				$step_display_dv_class = $reg_step->is_current_step() ? 'active-step' : 'inactive-step';
41
+				$reg_steps .= EEH_HTML::div(
42
+					EEH_HTML::h4(
43
+						EEH_HTML::span(
44
+							esc_html($step_nmbr),
45
+							'',
46
+							'spco-step-big-nmbr'
47
+						)
48
+						. EEH_HTML::nbsp()
49
+						. EEH_HTML::span(
50
+							str_replace('&nbsp;', '<br/>&nbsp;', $reg_step->name()),
51
+							'',
52
+							'spco-step-name'
53
+						),
54
+						"spco-step-$slug-display-hdr",
55
+						'spco-steps-display-hdr'
56
+					),
57
+					"spco-step-$slug-display-dv",
58
+					"spco-step-display-dv $step_display_dv_class steps-$total_steps",
59
+				);
60 60
 
61
-                if ($step_nmbr < $total_steps) {
62
-                    $reg_steps .= EEH_HTML::div('&raquo;', '', 'spco-step-arrow-dv');
63
-                }
64
-                $step_nmbr++;
65
-            }
66
-        }
67
-        return $reg_steps . EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx();
68
-    }
61
+				if ($step_nmbr < $total_steps) {
62
+					$reg_steps .= EEH_HTML::div('&raquo;', '', 'spco-step-arrow-dv');
63
+				}
64
+				$step_nmbr++;
65
+			}
66
+		}
67
+		return $reg_steps . EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx();
68
+	}
69 69
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -64,6 +64,6 @@
 block discarded – undo
64 64
                 $step_nmbr++;
65 65
             }
66 66
         }
67
-        return $reg_steps . EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx();
67
+        return $reg_steps.EEH_HTML::div('', '', 'clear-float').EEH_HTML::divx();
68 68
     }
69 69
 }
Please login to merge, or discard this patch.
modules/single_page_checkout/inc/EE_SPCO_JSON_Response.php 2 patches
Indentation   +250 added lines, -250 removed lines patch added patch discarded remove patch
@@ -15,292 +15,292 @@
 block discarded – undo
15 15
  */
16 16
 class EE_SPCO_JSON_Response
17 17
 {
18
-    protected string $_errors = '';
19
-
20
-    protected string $_unexpected_errors = '';
21
-
22
-    protected string $_attention = '';
23
-
24
-    protected string $_success = '';
25
-
26
-    protected string $_plz_select_method_of_payment = '';
27
-
28
-    protected string $_redirect_url = '';
29
-
30
-    protected string $_registration_time_limit = '';
31
-
32
-    protected string $_redirect_form = '';
33
-
34
-    protected string $_reg_step_html = '';
35
-
36
-    protected string $_method_of_payment = '';
37
-
38
-    protected ?float $_payment_amount = 0.00;
39
-
40
-    protected array $_return_data = [];
41
-
42
-    protected array $request_data = [];
43
-
44
-    protected array $_validation_rules = [];
45
-
46
-
47
-    public function __construct()
48
-    {
49
-    }
50
-
51
-
52
-    /**
53
-     * allows you to simply echo or print an EE_SPCO_JSON_Response object to produce a  JSON encoded string
54
-     *
55
-     * @return string
56
-     */
57
-    public function __toString()
58
-    {
59
-        return json_encode($this->buildResponse());
60
-    }
61
-
62
-
63
-    /**
64
-     * @return array
65
-     */
66
-    public function buildResponse(): array
67
-    {
68
-        $JSON_response = [];
69
-        // grab notices
70
-        $notices = EE_Error::get_notices(false);
71
-        $this->set_attention($notices['attention'] ?? '');
72
-        $this->set_errors($notices['errors'] ?? '');
73
-        $this->set_success($notices['success'] ?? '');
74
-        // add notices to JSON response, but only if they exist
75
-        if ($this->attention()) {
76
-            $JSON_response['attention'] = $this->attention();
77
-        }
78
-        if ($this->errors()) {
79
-            $JSON_response['errors'] = $this->errors();
80
-        }
81
-        if ($this->unexpected_errors()) {
82
-            $JSON_response['unexpected_errors'] = $this->unexpected_errors();
83
-        }
84
-        if ($this->success()) {
85
-            $JSON_response['success'] = $this->success();
86
-        }
87
-        // but if NO notices are set... at least set the "success" as a key so that the JS knows everything worked
88
-        if (! isset($JSON_response['attention']) && ! isset($JSON_response['errors']) && ! isset($JSON_response['success'])) {
89
-            $JSON_response['success'] = null;
90
-        }
91
-        // set redirect_url, IF it exists
92
-        if ($this->redirect_url()) {
93
-            $JSON_response['redirect_url'] = $this->redirect_url();
94
-        }
95
-        // set registration_time_limit, IF it exists
96
-        if ($this->registration_time_limit()) {
97
-            $JSON_response['registration_time_limit'] = $this->registration_time_limit();
98
-        }
99
-        // set payment_amount, IF it exists
100
-        if ($this->payment_amount() !== null) {
101
-            $JSON_response['payment_amount'] = $this->payment_amount();
102
-        }
103
-        // grab generic return data
104
-        $return_data = $this->return_data();
105
-        // add billing form validation rules
106
-        if ($this->validation_rules()) {
107
-            $return_data['validation_rules'] = $this->validation_rules();
108
-        }
109
-        // set reg_step_html, IF it exists
110
-        if ($this->reg_step_html()) {
111
-            $return_data['reg_step_html'] = $this->reg_step_html();
112
-        }
113
-        // set method of payment, IF it exists
114
-        if ($this->method_of_payment()) {
115
-            $return_data['method_of_payment'] = $this->method_of_payment();
116
-        }
117
-        // set "plz_select_method_of_payment" message, IF it exists
118
-        if ($this->plz_select_method_of_payment()) {
119
-            $return_data['plz_select_method_of_payment'] = $this->plz_select_method_of_payment();
120
-        }
121
-        // set redirect_form, IF it exists
122
-        if ($this->redirect_form()) {
123
-            $return_data['redirect_form'] = $this->redirect_form();
124
-        }
125
-        // and finally, add return_data array to main JSON response array, IF it contains anything
126
-        // why did we add some of the above properties to the return data array?
127
-        // because it is easier and cleaner in the Javascript to deal with this way
128
-        if (! empty($return_data)) {
129
-            $JSON_response['return_data'] = $return_data;
130
-        }
131
-        // filter & return final array
132
-        return apply_filters('FHEE__EE_SPCO_JSON_Response___toString__JSON_response', $JSON_response);
133
-    }
134
-
135
-    public function sendResponse()
136
-    {
137
-        wp_send_json($this->buildResponse());
138
-    }
139
-
140
-
141
-    public function set_attention(string $attention)
142
-    {
143
-        $this->_attention = $attention;
144
-    }
145
-
146
-
147
-    public function attention(): string
148
-    {
149
-        return $this->_attention;
150
-    }
151
-
152
-
153
-    public function set_errors(string $errors)
154
-    {
155
-        $this->_errors = $errors;
156
-    }
157
-
158
-
159
-    public function errors(): string
160
-    {
161
-        return $this->_errors;
162
-    }
163
-
164
-
165
-    public function unexpected_errors(): string
166
-    {
167
-        return $this->_unexpected_errors;
168
-    }
169
-
170
-
171
-    public function set_unexpected_errors(string $unexpected_errors)
172
-    {
173
-        $this->_unexpected_errors = $unexpected_errors;
174
-    }
175
-
176
-
177
-    public function set_success(string $success)
178
-    {
179
-        $this->_success = $success;
180
-    }
181
-
182
-
183
-    public function success(): string
184
-    {
185
-        return $this->_success;
186
-    }
18
+	protected string $_errors = '';
19
+
20
+	protected string $_unexpected_errors = '';
21
+
22
+	protected string $_attention = '';
23
+
24
+	protected string $_success = '';
25
+
26
+	protected string $_plz_select_method_of_payment = '';
27
+
28
+	protected string $_redirect_url = '';
29
+
30
+	protected string $_registration_time_limit = '';
31
+
32
+	protected string $_redirect_form = '';
33
+
34
+	protected string $_reg_step_html = '';
35
+
36
+	protected string $_method_of_payment = '';
37
+
38
+	protected ?float $_payment_amount = 0.00;
39
+
40
+	protected array $_return_data = [];
41
+
42
+	protected array $request_data = [];
43
+
44
+	protected array $_validation_rules = [];
45
+
46
+
47
+	public function __construct()
48
+	{
49
+	}
50
+
51
+
52
+	/**
53
+	 * allows you to simply echo or print an EE_SPCO_JSON_Response object to produce a  JSON encoded string
54
+	 *
55
+	 * @return string
56
+	 */
57
+	public function __toString()
58
+	{
59
+		return json_encode($this->buildResponse());
60
+	}
61
+
62
+
63
+	/**
64
+	 * @return array
65
+	 */
66
+	public function buildResponse(): array
67
+	{
68
+		$JSON_response = [];
69
+		// grab notices
70
+		$notices = EE_Error::get_notices(false);
71
+		$this->set_attention($notices['attention'] ?? '');
72
+		$this->set_errors($notices['errors'] ?? '');
73
+		$this->set_success($notices['success'] ?? '');
74
+		// add notices to JSON response, but only if they exist
75
+		if ($this->attention()) {
76
+			$JSON_response['attention'] = $this->attention();
77
+		}
78
+		if ($this->errors()) {
79
+			$JSON_response['errors'] = $this->errors();
80
+		}
81
+		if ($this->unexpected_errors()) {
82
+			$JSON_response['unexpected_errors'] = $this->unexpected_errors();
83
+		}
84
+		if ($this->success()) {
85
+			$JSON_response['success'] = $this->success();
86
+		}
87
+		// but if NO notices are set... at least set the "success" as a key so that the JS knows everything worked
88
+		if (! isset($JSON_response['attention']) && ! isset($JSON_response['errors']) && ! isset($JSON_response['success'])) {
89
+			$JSON_response['success'] = null;
90
+		}
91
+		// set redirect_url, IF it exists
92
+		if ($this->redirect_url()) {
93
+			$JSON_response['redirect_url'] = $this->redirect_url();
94
+		}
95
+		// set registration_time_limit, IF it exists
96
+		if ($this->registration_time_limit()) {
97
+			$JSON_response['registration_time_limit'] = $this->registration_time_limit();
98
+		}
99
+		// set payment_amount, IF it exists
100
+		if ($this->payment_amount() !== null) {
101
+			$JSON_response['payment_amount'] = $this->payment_amount();
102
+		}
103
+		// grab generic return data
104
+		$return_data = $this->return_data();
105
+		// add billing form validation rules
106
+		if ($this->validation_rules()) {
107
+			$return_data['validation_rules'] = $this->validation_rules();
108
+		}
109
+		// set reg_step_html, IF it exists
110
+		if ($this->reg_step_html()) {
111
+			$return_data['reg_step_html'] = $this->reg_step_html();
112
+		}
113
+		// set method of payment, IF it exists
114
+		if ($this->method_of_payment()) {
115
+			$return_data['method_of_payment'] = $this->method_of_payment();
116
+		}
117
+		// set "plz_select_method_of_payment" message, IF it exists
118
+		if ($this->plz_select_method_of_payment()) {
119
+			$return_data['plz_select_method_of_payment'] = $this->plz_select_method_of_payment();
120
+		}
121
+		// set redirect_form, IF it exists
122
+		if ($this->redirect_form()) {
123
+			$return_data['redirect_form'] = $this->redirect_form();
124
+		}
125
+		// and finally, add return_data array to main JSON response array, IF it contains anything
126
+		// why did we add some of the above properties to the return data array?
127
+		// because it is easier and cleaner in the Javascript to deal with this way
128
+		if (! empty($return_data)) {
129
+			$JSON_response['return_data'] = $return_data;
130
+		}
131
+		// filter & return final array
132
+		return apply_filters('FHEE__EE_SPCO_JSON_Response___toString__JSON_response', $JSON_response);
133
+	}
134
+
135
+	public function sendResponse()
136
+	{
137
+		wp_send_json($this->buildResponse());
138
+	}
139
+
140
+
141
+	public function set_attention(string $attention)
142
+	{
143
+		$this->_attention = $attention;
144
+	}
145
+
146
+
147
+	public function attention(): string
148
+	{
149
+		return $this->_attention;
150
+	}
151
+
152
+
153
+	public function set_errors(string $errors)
154
+	{
155
+		$this->_errors = $errors;
156
+	}
157
+
158
+
159
+	public function errors(): string
160
+	{
161
+		return $this->_errors;
162
+	}
163
+
164
+
165
+	public function unexpected_errors(): string
166
+	{
167
+		return $this->_unexpected_errors;
168
+	}
169
+
170
+
171
+	public function set_unexpected_errors(string $unexpected_errors)
172
+	{
173
+		$this->_unexpected_errors = $unexpected_errors;
174
+	}
175
+
176
+
177
+	public function set_success(string $success)
178
+	{
179
+		$this->_success = $success;
180
+	}
181
+
182
+
183
+	public function success(): string
184
+	{
185
+		return $this->_success;
186
+	}
187 187
 
188 188
 
189
-    public function set_method_of_payment(string $method_of_payment)
190
-    {
191
-        $this->_method_of_payment = $method_of_payment;
192
-    }
189
+	public function set_method_of_payment(string $method_of_payment)
190
+	{
191
+		$this->_method_of_payment = $method_of_payment;
192
+	}
193 193
 
194 194
 
195
-    public function method_of_payment(): string
196
-    {
197
-        return $this->_method_of_payment;
198
-    }
195
+	public function method_of_payment(): string
196
+	{
197
+		return $this->_method_of_payment;
198
+	}
199 199
 
200 200
 
201
-    public function payment_amount(): float
202
-    {
203
-        return $this->_payment_amount;
204
-    }
201
+	public function payment_amount(): float
202
+	{
203
+		return $this->_payment_amount;
204
+	}
205 205
 
206 206
 
207
-    /**
208
-     * @param float|int $payment_amount
209
-     */
210
-    public function set_payment_amount($payment_amount)
211
-    {
212
-        $this->_payment_amount = (float) $payment_amount;
213
-    }
207
+	/**
208
+	 * @param float|int $payment_amount
209
+	 */
210
+	public function set_payment_amount($payment_amount)
211
+	{
212
+		$this->_payment_amount = (float) $payment_amount;
213
+	}
214 214
 
215 215
 
216
-    public function set_reg_step_html(string $next_step_html)
217
-    {
218
-        $this->_reg_step_html = $next_step_html;
219
-    }
216
+	public function set_reg_step_html(string $next_step_html)
217
+	{
218
+		$this->_reg_step_html = $next_step_html;
219
+	}
220 220
 
221 221
 
222
-    public function reg_step_html(): string
223
-    {
224
-        return $this->_reg_step_html;
225
-    }
222
+	public function reg_step_html(): string
223
+	{
224
+		return $this->_reg_step_html;
225
+	}
226 226
 
227 227
 
228
-    public function set_redirect_form(string $redirect_form)
229
-    {
230
-        $this->_redirect_form = $redirect_form;
231
-    }
228
+	public function set_redirect_form(string $redirect_form)
229
+	{
230
+		$this->_redirect_form = $redirect_form;
231
+	}
232 232
 
233 233
 
234
-    public function redirect_form()
235
-    {
236
-        return ! empty($this->_redirect_form) ? $this->_redirect_form : false;
237
-    }
234
+	public function redirect_form()
235
+	{
236
+		return ! empty($this->_redirect_form) ? $this->_redirect_form : false;
237
+	}
238 238
 
239 239
 
240
-    public function set_plz_select_method_of_payment(string $plz_select_method_of_payment)
241
-    {
242
-        $this->_plz_select_method_of_payment = $plz_select_method_of_payment;
243
-    }
240
+	public function set_plz_select_method_of_payment(string $plz_select_method_of_payment)
241
+	{
242
+		$this->_plz_select_method_of_payment = $plz_select_method_of_payment;
243
+	}
244 244
 
245 245
 
246
-    public function plz_select_method_of_payment(): string
247
-    {
248
-        return $this->_plz_select_method_of_payment;
249
-    }
246
+	public function plz_select_method_of_payment(): string
247
+	{
248
+		return $this->_plz_select_method_of_payment;
249
+	}
250 250
 
251 251
 
252
-    public function set_redirect_url(string $redirect_url)
253
-    {
254
-        $this->_redirect_url = $redirect_url;
255
-    }
252
+	public function set_redirect_url(string $redirect_url)
253
+	{
254
+		$this->_redirect_url = $redirect_url;
255
+	}
256 256
 
257 257
 
258
-    public function redirect_url(): string
259
-    {
260
-        return $this->_redirect_url;
261
-    }
258
+	public function redirect_url(): string
259
+	{
260
+		return $this->_redirect_url;
261
+	}
262 262
 
263 263
 
264
-    public function registration_time_limit(): string
265
-    {
266
-        return $this->_registration_time_limit;
267
-    }
264
+	public function registration_time_limit(): string
265
+	{
266
+		return $this->_registration_time_limit;
267
+	}
268 268
 
269 269
 
270
-    public function set_registration_time_limit(string $registration_time_limit)
271
-    {
272
-        $this->_registration_time_limit = $registration_time_limit;
273
-    }
270
+	public function set_registration_time_limit(string $registration_time_limit)
271
+	{
272
+		$this->_registration_time_limit = $registration_time_limit;
273
+	}
274 274
 
275 275
 
276
-    public function set_return_data(array $return_data)
277
-    {
278
-        $this->_return_data = array_merge($this->_return_data, $return_data);
279
-    }
276
+	public function set_return_data(array $return_data)
277
+	{
278
+		$this->_return_data = array_merge($this->_return_data, $return_data);
279
+	}
280 280
 
281 281
 
282
-    public function return_data(): array
283
-    {
284
-        return $this->_return_data;
285
-    }
282
+	public function return_data(): array
283
+	{
284
+		return $this->_return_data;
285
+	}
286 286
 
287 287
 
288
-    public function add_validation_rules(array $validation_rules = [])
289
-    {
290
-        if (is_array($validation_rules) && ! empty($validation_rules)) {
291
-            $this->_validation_rules = array_merge($this->_validation_rules, $validation_rules);
292
-        }
293
-    }
288
+	public function add_validation_rules(array $validation_rules = [])
289
+	{
290
+		if (is_array($validation_rules) && ! empty($validation_rules)) {
291
+			$this->_validation_rules = array_merge($this->_validation_rules, $validation_rules);
292
+		}
293
+	}
294 294
 
295 295
 
296
-    public function validation_rules(): array
297
-    {
298
-        return ! empty($this->_validation_rules) ? $this->_validation_rules : [];
299
-    }
296
+	public function validation_rules(): array
297
+	{
298
+		return ! empty($this->_validation_rules) ? $this->_validation_rules : [];
299
+	}
300 300
 
301 301
 
302
-    public function echoAndExit()
303
-    {
304
-        exit($this->__toString());
305
-    }
302
+	public function echoAndExit()
303
+	{
304
+		exit($this->__toString());
305
+	}
306 306
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -85,7 +85,7 @@  discard block
 block discarded – undo
85 85
             $JSON_response['success'] = $this->success();
86 86
         }
87 87
         // but if NO notices are set... at least set the "success" as a key so that the JS knows everything worked
88
-        if (! isset($JSON_response['attention']) && ! isset($JSON_response['errors']) && ! isset($JSON_response['success'])) {
88
+        if ( ! isset($JSON_response['attention']) && ! isset($JSON_response['errors']) && ! isset($JSON_response['success'])) {
89 89
             $JSON_response['success'] = null;
90 90
         }
91 91
         // set redirect_url, IF it exists
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
         // and finally, add return_data array to main JSON response array, IF it contains anything
126 126
         // why did we add some of the above properties to the return data array?
127 127
         // because it is easier and cleaner in the Javascript to deal with this way
128
-        if (! empty($return_data)) {
128
+        if ( ! empty($return_data)) {
129 129
             $JSON_response['return_data'] = $return_data;
130 130
         }
131 131
         // filter & return final array
Please login to merge, or discard this patch.