Completed
Branch fix-dummy-related-question-qst... (e5efcf)
by
unknown
07:49 queued 03:45
created
help_tabs/transactions_overview_table_column_headings.help_tab.php 1 patch
Indentation   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -6,25 +6,25 @@  discard block
 block discarded – undo
6 6
         <p><strong><?php esc_html_e('ID', 'event_espresso'); ?></strong>
7 7
             <br />
8 8
             <?php esc_html_e(
9
-                'This is the transaction ID is that is used throughout the payment process.',
10
-                'event_espresso'
11
-            ); ?>
9
+				'This is the transaction ID is that is used throughout the payment process.',
10
+				'event_espresso'
11
+			); ?>
12 12
         </p>
13 13
     </li>
14 14
     <li><strong><?php esc_html_e('Transaction Date', 'event_espresso'); ?></strong>
15 15
         <br />
16 16
         <?php esc_html_e(
17
-            'This is the date that the transaction occurred on. Clicking the date will take you to another page where you can view the transaction details.',
18
-            'event_espresso'
19
-        ); ?>
17
+			'This is the date that the transaction occurred on. Clicking the date will take you to another page where you can view the transaction details.',
18
+			'event_espresso'
19
+		); ?>
20 20
     </li>
21 21
     <li>
22 22
         <strong><?php esc_html_e('Status', 'event_espresso'); ?></strong>
23 23
         <br />
24 24
         <?php esc_html_e(
25
-            'The status helps you understand if the transaction was successful or not. Below are available statuses for transactions.',
26
-            'event_espresso'
27
-        ); ?>
25
+			'The status helps you understand if the transaction was successful or not. Below are available statuses for transactions.',
26
+			'event_espresso'
27
+		); ?>
28 28
         <ul>
29 29
             <li style="list-style-type: none;">
30 30
                 <strong><?php esc_html_e('Overpaid', 'event_espresso'); ?></strong>
@@ -40,9 +40,9 @@  discard block
 block discarded – undo
40 40
                 <strong><?php esc_html_e('Incomplete', 'event_espresso'); ?></strong>
41 41
                 <br />
42 42
                 <?php esc_html_e(
43
-                    'The payment has not yet been completed. This is the status for online payments that have yet to be processed.',
44
-                    'event_espresso'
45
-                ); ?>
43
+					'The payment has not yet been completed. This is the status for online payments that have yet to be processed.',
44
+					'event_espresso'
45
+				); ?>
46 46
             </li>
47 47
             <li style="list-style-type: none;">
48 48
                 <strong><?php esc_html_e('Failed', 'event_espresso'); ?></strong>
@@ -55,69 +55,69 @@  discard block
 block discarded – undo
55 55
         <strong><?php esc_html_e('Total', 'event_espresso'); ?></strong>
56 56
         <br />
57 57
         <?php esc_html_e(
58
-            'This is the total amount for that transaction. It will include the total of every ticket purchased even if from separate events.',
59
-            'event_espresso'
60
-        ); ?>
58
+			'This is the total amount for that transaction. It will include the total of every ticket purchased even if from separate events.',
59
+			'event_espresso'
60
+		); ?>
61 61
     </li>
62 62
     <li>
63 63
         <strong><?php esc_html_e('Paid', 'event_espresso'); ?></strong>
64 64
         <br />
65 65
         <?php esc_html_e(
66
-            'This shows much has been paid. If this column matches the amount in the total column, then the transaction has been paid in full.',
67
-            'event_espresso'
68
-        ); ?>
66
+			'This shows much has been paid. If this column matches the amount in the total column, then the transaction has been paid in full.',
67
+			'event_espresso'
68
+		); ?>
69 69
     </li>
70 70
     <li>
71 71
         <strong><?php esc_html_e('Primary Registrant', 'event_espresso'); ?></strong>
72 72
         <br />
73 73
         <?php esc_html_e(
74
-            'The name of the primary registrant. Clicking the name will take you to the registration details page.',
75
-            'event_espresso'
76
-        ); ?>
74
+			'The name of the primary registrant. Clicking the name will take you to the registration details page.',
75
+			'event_espresso'
76
+		); ?>
77 77
     </li>
78 78
     <li>
79 79
         <strong><?php esc_html_e('Email Address', 'event_espresso'); ?></strong>
80 80
         <br />
81 81
         <?php esc_html_e(
82
-            'This is the email address for the primary registrant. Clicking the email address will open your default email client.',
83
-            'event_espresso'
84
-        ); ?>
82
+			'This is the email address for the primary registrant. Clicking the email address will open your default email client.',
83
+			'event_espresso'
84
+		); ?>
85 85
     </li>
86 86
     <li>
87 87
         <strong><?php esc_html_e('Event', 'event_espresso'); ?></strong>
88 88
         <br />
89 89
         <?php esc_html_e(
90
-            'The name of the events are shown here. Clicking the name will take you the edit event page.',
91
-            'event_espresso'
92
-        ); ?>
90
+			'The name of the events are shown here. Clicking the name will take you the edit event page.',
91
+			'event_espresso'
92
+		); ?>
93 93
     </li>
94 94
     <li>
95 95
         <strong><?php esc_html_e('Actions', 'event_espresso'); ?></strong>
96 96
         <br />
97 97
         <?php esc_html_e(
98
-            'There are several actions that can be done by clicking the icons. These are explained below.',
99
-            'event_espresso'
100
-        ); ?>
98
+			'There are several actions that can be done by clicking the icons. These are explained below.',
99
+			'event_espresso'
100
+		); ?>
101 101
         <ul>
102 102
             <li style="list-style-type: none;">
103 103
                 <strong>
104 104
                     <?php printf(
105
-                        esc_html__('View Transaction Details %1$s', 'event_espresso'),
106
-                        '<span class="dashicons dashicons-cart"></span>'
107
-                    ); ?>
105
+						esc_html__('View Transaction Details %1$s', 'event_espresso'),
106
+						'<span class="dashicons dashicons-cart"></span>'
107
+					); ?>
108 108
                 </strong>
109 109
                 <br />
110 110
                 <?php esc_html_e(
111
-                    'Takes you to the individual transaction page. Clicking the date also takes you to the individual transaction page.',
112
-                    'event_espresso'
113
-                ); ?>
111
+					'Takes you to the individual transaction page. Clicking the date also takes you to the individual transaction page.',
112
+					'event_espresso'
113
+				); ?>
114 114
             </li>
115 115
             <li style="list-style-type: none;">
116 116
                 <strong>
117 117
                     <?php printf(
118
-                        esc_html__('View Invoice for Transaction %1$s', 'event_espresso'),
119
-                        '<span class="dashicons dashicons-media-spreadsheet"></span>'
120
-                    ); ?>
118
+						esc_html__('View Invoice for Transaction %1$s', 'event_espresso'),
119
+						'<span class="dashicons dashicons-media-spreadsheet"></span>'
120
+					); ?>
121 121
                 </strong>
122 122
                 <br />
123 123
                 <?php esc_html_e('Takes you to the invoice for the transaction.', 'event_espresso'); ?>
@@ -125,9 +125,9 @@  discard block
 block discarded – undo
125 125
             <li style="list-style-type: none;">
126 126
                 <strong>
127 127
                     <?php printf(
128
-                        esc_html__('View Receipt for Transaction %1$s', 'event_espresso'),
129
-                        '<span class="dashicons dashicons-media-default"></span>'
130
-                    ); ?>
128
+						esc_html__('View Receipt for Transaction %1$s', 'event_espresso'),
129
+						'<span class="dashicons dashicons-media-default"></span>'
130
+					); ?>
131 131
                 </strong>
132 132
                 <br />
133 133
                 <?php esc_html_e('Takes you to the receipt for the transaction.', 'event_espresso'); ?>
@@ -135,36 +135,36 @@  discard block
 block discarded – undo
135 135
             <li style="list-style-type: none;">
136 136
                 <strong>
137 137
                     <?php printf(
138
-                        esc_html__('View Registration Details %1$s', 'event_espresso'),
139
-                        '<span class="dashicons dashicons-clipboard"></span>'
140
-                    ); ?>
138
+						esc_html__('View Registration Details %1$s', 'event_espresso'),
139
+						'<span class="dashicons dashicons-clipboard"></span>'
140
+					); ?>
141 141
                 </strong>
142 142
                 <br />
143 143
                 <?php printf(
144
-                    esc_html__(
145
-                        'Clicking this icon will take you to the registration page for this transaction. You can also get there via the %sRegistrations page%s.',
146
-                        'event_espresso'
147
-                    ),
148
-                    '<a href="admin.php?page=espresso_registrations">',
149
-                    '</a>'
150
-                ); ?>
144
+					esc_html__(
145
+						'Clicking this icon will take you to the registration page for this transaction. You can also get there via the %sRegistrations page%s.',
146
+						'event_espresso'
147
+					),
148
+					'<a href="admin.php?page=espresso_registrations">',
149
+					'</a>'
150
+				); ?>
151 151
             </li>
152 152
             <li style="list-style-type: none;">
153 153
                 <strong>
154 154
                     <?php printf(
155
-                        esc_html__('Send Payment Reminder %1$s', 'event_espresso'),
156
-                        '<span class="dashicons dashicons-email-alt"></span>'
157
-                    ); ?>
155
+						esc_html__('Send Payment Reminder %1$s', 'event_espresso'),
156
+						'<span class="dashicons dashicons-email-alt"></span>'
157
+					); ?>
158 158
                 </strong>
159 159
                 <br />
160 160
                 <?php printf(
161
-                    esc_html__(
162
-                        'Emails the primary registrant the Payment Reminder message. This is set up in the %sMessages page%s.',
163
-                        'event_espresso'
164
-                    ),
165
-                    '<a href="admin.php?page=espresso_messages">',
166
-                    '</a>'
167
-                ); ?>
161
+					esc_html__(
162
+						'Emails the primary registrant the Payment Reminder message. This is set up in the %sMessages page%s.',
163
+						'event_espresso'
164
+					),
165
+					'<a href="admin.php?page=espresso_messages">',
166
+					'</a>'
167
+				); ?>
168 168
             </li>
169 169
         </ul>
170 170
     </li>
Please login to merge, or discard this patch.
core/db_classes/EE_Ticket.class.php 2 patches
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
     public function ticket_status($display = false, $remaining = null)
135 135
     {
136 136
         $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
137
-        if (! $remaining) {
137
+        if ( ! $remaining) {
138 138
             return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
139 139
         }
140 140
         if ($this->get('TKT_deleted')) {
@@ -259,13 +259,13 @@  discard block
 block discarded – undo
259 259
                 'DTT_EVT_start',
260 260
                 $dt_frmt
261 261
             ) : '';
262
-        $last_date  =
262
+        $last_date =
263 263
             $this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->get_i18n_datetime(
264 264
                 'DTT_EVT_end',
265 265
                 $dt_frmt
266 266
             ) : '';
267 267
 
268
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
268
+        return $first_date && $last_date ? $first_date.$conjunction.$last_date : '';
269 269
     }
270 270
 
271 271
 
@@ -294,7 +294,7 @@  discard block
 block discarded – undo
294 294
      */
295 295
     public function datetimes($query_params = [])
296 296
     {
297
-        if (! isset($query_params['order_by'])) {
297
+        if ( ! isset($query_params['order_by'])) {
298 298
             $query_params['order_by']['DTT_order'] = 'ASC';
299 299
         }
300 300
         return $this->get_many_related('Datetime', $query_params);
@@ -339,7 +339,7 @@  discard block
 block discarded – undo
339 339
                 if (empty($tickets_sold['datetime'])) {
340 340
                     return $total;
341 341
                 }
342
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
342
+                if ( ! empty($dtt_id) && ! isset($tickets_sold['datetime'][$dtt_id])) {
343 343
                     EE_Error::add_error(
344 344
                         esc_html__(
345 345
                             'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
@@ -351,7 +351,7 @@  discard block
 block discarded – undo
351 351
                     );
352 352
                     return $total;
353 353
                 }
354
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
354
+                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][$dtt_id];
355 355
                 break;
356 356
             default:
357 357
                 return $total;
@@ -370,9 +370,9 @@  discard block
 block discarded – undo
370 370
     {
371 371
         $datetimes    = $this->get_many_related('Datetime');
372 372
         $tickets_sold = [];
373
-        if (! empty($datetimes)) {
373
+        if ( ! empty($datetimes)) {
374 374
             foreach ($datetimes as $datetime) {
375
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
375
+                $tickets_sold['datetime'][$datetime->ID()] = $datetime->get('DTT_sold');
376 376
             }
377 377
         }
378 378
         // Tickets sold
@@ -970,7 +970,7 @@  discard block
 block discarded – undo
970 970
                 'TKT_qty',
971 971
                 $qty
972 972
             );
973
-            if (! $success) {
973
+            if ( ! $success) {
974 974
                 // The datetimes were successfully bumped, but not the
975 975
                 // ticket. So we need to manually rollback the datetimes.
976 976
                 $this->decreaseReservedForDatetimes($qty);
@@ -1439,7 +1439,7 @@  discard block
 block discarded – undo
1439 1439
         foreach ($this->datetimes() as $datetime) {
1440 1440
             $times[] = $datetime->start_date_and_time();
1441 1441
         }
1442
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1442
+        return $this->name().' @ '.implode(', ', $times).' for '.$this->pretty_price();
1443 1443
     }
1444 1444
 
1445 1445
 
@@ -1544,7 +1544,7 @@  discard block
 block discarded – undo
1544 1544
     {
1545 1545
         // get one datetime to use for getting the event
1546 1546
         $datetime = $this->first_datetime();
1547
-        if (! $datetime instanceof \EE_Datetime) {
1547
+        if ( ! $datetime instanceof \EE_Datetime) {
1548 1548
             throw new UnexpectedEntityException(
1549 1549
                 $datetime,
1550 1550
                 'EE_Datetime',
@@ -1555,7 +1555,7 @@  discard block
 block discarded – undo
1555 1555
             );
1556 1556
         }
1557 1557
         $event = $datetime->event();
1558
-        if (! $event instanceof \EE_Event) {
1558
+        if ( ! $event instanceof \EE_Event) {
1559 1559
             throw new UnexpectedEntityException(
1560 1560
                 $event,
1561 1561
                 'EE_Event',
Please login to merge, or discard this patch.
Indentation   +1795 added lines, -1795 removed lines patch added patch discarded remove patch
@@ -13,1803 +13,1803 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Ticket extends EE_Soft_Delete_Base_Class implements EEI_Line_Item_Object, EEI_Event_Relation, EEI_Has_Icon
15 15
 {
16
-    /**
17
-     * The following constants are used by the ticket_status() method to indicate whether a ticket is on sale or not.
18
-     */
19
-    const sold_out = 'TKS';
20
-
21
-    /**
22
-     *
23
-     */
24
-    const expired = 'TKE';
25
-
26
-    /**
27
-     *
28
-     */
29
-    const archived = 'TKA';
30
-
31
-    /**
32
-     *
33
-     */
34
-    const pending = 'TKP';
35
-
36
-    /**
37
-     *
38
-     */
39
-    const onsale = 'TKO';
40
-
41
-    /**
42
-     * extra meta key for tracking ticket reservations
43
-     *
44
-     * @type string
45
-     */
46
-    const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
47
-
48
-    /**
49
-     * cached result from method of the same name
50
-     *
51
-     * @var float $_ticket_total_with_taxes
52
-     */
53
-    private $_ticket_total_with_taxes;
54
-
55
-
56
-    /**
57
-     * @param array  $props_n_values          incoming values
58
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
59
-     *                                        used.)
60
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
61
-     *                                        date_format and the second value is the time format
62
-     * @return EE_Ticket
63
-     * @throws EE_Error
64
-     * @throws ReflectionException
65
-     */
66
-    public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
67
-    {
68
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
69
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
70
-    }
71
-
72
-
73
-    /**
74
-     * @param array  $props_n_values  incoming values from the database
75
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
76
-     *                                the website will be used.
77
-     * @return EE_Ticket
78
-     * @throws EE_Error
79
-     * @throws ReflectionException
80
-     */
81
-    public static function new_instance_from_db($props_n_values = [], $timezone = null)
82
-    {
83
-        return new self($props_n_values, true, $timezone);
84
-    }
85
-
86
-
87
-    /**
88
-     * @return bool
89
-     * @throws EE_Error
90
-     * @throws ReflectionException
91
-     */
92
-    public function parent()
93
-    {
94
-        return $this->get('TKT_parent');
95
-    }
96
-
97
-
98
-    /**
99
-     * return if a ticket has quantities available for purchase
100
-     *
101
-     * @param int $DTT_ID the primary key for a particular datetime
102
-     * @return boolean
103
-     * @throws EE_Error
104
-     * @throws ReflectionException
105
-     */
106
-    public function available($DTT_ID = 0)
107
-    {
108
-        // are we checking availability for a particular datetime ?
109
-        if ($DTT_ID) {
110
-            // get that datetime object
111
-            $datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
112
-            // if  ticket sales for this datetime have exceeded the reg limit...
113
-            if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
114
-                return false;
115
-            }
116
-        }
117
-        // datetime is still open for registration, but is this ticket sold out ?
118
-        return $this->qty() < 1 || $this->qty() > $this->sold() ? true : false;
119
-    }
120
-
121
-
122
-    /**
123
-     * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
124
-     *
125
-     * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
126
-     *                               relevant status const
127
-     * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
128
-     *                               further processing
129
-     * @return mixed status int if the display string isn't requested
130
-     * @throws EE_Error
131
-     * @throws ReflectionException
132
-     */
133
-    public function ticket_status($display = false, $remaining = null)
134
-    {
135
-        $remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
136
-        if (! $remaining) {
137
-            return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
138
-        }
139
-        if ($this->get('TKT_deleted')) {
140
-            return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
141
-        }
142
-        if ($this->is_expired()) {
143
-            return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
144
-        }
145
-        if ($this->is_pending()) {
146
-            return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
147
-        }
148
-        if ($this->is_on_sale()) {
149
-            return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
150
-        }
151
-        return '';
152
-    }
153
-
154
-
155
-    /**
156
-     * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
157
-     * considering ALL the factors used for figuring that out.
158
-     *
159
-     * @access public
160
-     * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
161
-     * @return boolean         true = tickets remaining, false not.
162
-     * @throws EE_Error
163
-     */
164
-    public function is_remaining($DTT_ID = 0)
165
-    {
166
-        $num_remaining = $this->remaining($DTT_ID);
167
-        if ($num_remaining === 0) {
168
-            return false;
169
-        }
170
-        if ($num_remaining > 0 && $num_remaining < $this->min()) {
171
-            return false;
172
-        }
173
-        return true;
174
-    }
175
-
176
-
177
-    /**
178
-     * return the total number of tickets available for purchase
179
-     *
180
-     * @param int $DTT_ID  the primary key for a particular datetime.
181
-     *                     set to 0 for all related datetimes
182
-     * @return int
183
-     * @throws EE_Error
184
-     */
185
-    public function remaining($DTT_ID = 0)
186
-    {
187
-        return $this->real_quantity_on_ticket('saleable', $DTT_ID);
188
-    }
189
-
190
-
191
-    /**
192
-     * Gets min
193
-     *
194
-     * @return int
195
-     * @throws EE_Error
196
-     * @throws ReflectionException
197
-     */
198
-    public function min()
199
-    {
200
-        return $this->get('TKT_min');
201
-    }
202
-
203
-
204
-    /**
205
-     * return if a ticket is no longer available cause its available dates have expired.
206
-     *
207
-     * @return boolean
208
-     * @throws EE_Error
209
-     * @throws ReflectionException
210
-     */
211
-    public function is_expired()
212
-    {
213
-        return ($this->get_raw('TKT_end_date') < time());
214
-    }
215
-
216
-
217
-    /**
218
-     * Return if a ticket is yet to go on sale or not
219
-     *
220
-     * @return boolean
221
-     * @throws EE_Error
222
-     * @throws ReflectionException
223
-     */
224
-    public function is_pending()
225
-    {
226
-        return ($this->get_raw('TKT_start_date') > time());
227
-    }
228
-
229
-
230
-    /**
231
-     * Return if a ticket is on sale or not
232
-     *
233
-     * @return boolean
234
-     * @throws EE_Error
235
-     * @throws ReflectionException
236
-     */
237
-    public function is_on_sale()
238
-    {
239
-        return ($this->get_raw('TKT_start_date') < time() && $this->get_raw('TKT_end_date') > time());
240
-    }
241
-
242
-
243
-    /**
244
-     * This returns the chronologically last datetime that this ticket is associated with
245
-     *
246
-     * @param string $dt_frmt
247
-     * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
248
-     *                            the end date ie: Jan 01 "to" Dec 31
249
-     * @return string
250
-     * @throws EE_Error
251
-     * @throws ReflectionException
252
-     */
253
-    public function date_range($dt_frmt = '', $conjunction = ' - ')
254
-    {
255
-        $dt_frmt    = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
256
-        $first_date = $this->first_datetime() instanceof EE_Datetime
257
-            ? $this->first_datetime()->get_i18n_datetime(
258
-                'DTT_EVT_start',
259
-                $dt_frmt
260
-            ) : '';
261
-        $last_date  =
262
-            $this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->get_i18n_datetime(
263
-                'DTT_EVT_end',
264
-                $dt_frmt
265
-            ) : '';
266
-
267
-        return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
268
-    }
269
-
270
-
271
-    /**
272
-     * This returns the chronologically first datetime that this ticket is associated with
273
-     *
274
-     * @return EE_Datetime
275
-     * @throws EE_Error
276
-     */
277
-    public function first_datetime()
278
-    {
279
-        $datetimes = $this->datetimes(['limit' => 1]);
280
-        return reset($datetimes);
281
-    }
282
-
283
-
284
-    /**
285
-     * Gets all the datetimes this ticket can be used for attending.
286
-     * Unless otherwise specified, orders datetimes by start date.
287
-     *
288
-     * @param array $query_params @see
289
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
290
-     * @return EE_Datetime[]|EE_Base_Class[]
291
-     * @throws EE_Error
292
-     * @throws ReflectionException
293
-     */
294
-    public function datetimes($query_params = [])
295
-    {
296
-        if (! isset($query_params['order_by'])) {
297
-            $query_params['order_by']['DTT_order'] = 'ASC';
298
-        }
299
-        return $this->get_many_related('Datetime', $query_params);
300
-    }
301
-
302
-
303
-    /**
304
-     * This returns the chronologically last datetime that this ticket is associated with
305
-     *
306
-     * @return EE_Datetime
307
-     * @throws EE_Error
308
-     */
309
-    public function last_datetime()
310
-    {
311
-        $datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
312
-        return end($datetimes);
313
-    }
314
-
315
-
316
-    /**
317
-     * This returns the total tickets sold depending on the given parameters.
318
-     *
319
-     * @param string $what    Can be one of two options: 'ticket', 'datetime'.
320
-     *                        'ticket' = total ticket sales for all datetimes this ticket is related to
321
-     *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
322
-     *                        'datetime' = total ticket sales in the datetime_ticket table.
323
-     *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
324
-     *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
325
-     * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
326
-     * @return mixed (array|int)          how many tickets have sold
327
-     * @throws EE_Error
328
-     */
329
-    public function tickets_sold($what = 'ticket', $dtt_id = null)
330
-    {
331
-        $total        = 0;
332
-        $tickets_sold = $this->_all_tickets_sold();
333
-        switch ($what) {
334
-            case 'ticket':
335
-                return $tickets_sold['ticket'];
336
-                break;
337
-            case 'datetime':
338
-                if (empty($tickets_sold['datetime'])) {
339
-                    return $total;
340
-                }
341
-                if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
342
-                    EE_Error::add_error(
343
-                        esc_html__(
344
-                            'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
345
-                            'event_espresso'
346
-                        ),
347
-                        __FILE__,
348
-                        __FUNCTION__,
349
-                        __LINE__
350
-                    );
351
-                    return $total;
352
-                }
353
-                return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
354
-                break;
355
-            default:
356
-                return $total;
357
-        }
358
-    }
359
-
360
-
361
-    /**
362
-     * This returns an array indexed by datetime_id for tickets sold with this ticket.
363
-     *
364
-     * @return EE_Ticket[]
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    protected function _all_tickets_sold()
369
-    {
370
-        $datetimes    = $this->get_many_related('Datetime');
371
-        $tickets_sold = [];
372
-        if (! empty($datetimes)) {
373
-            foreach ($datetimes as $datetime) {
374
-                $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
375
-            }
376
-        }
377
-        // Tickets sold
378
-        $tickets_sold['ticket'] = $this->sold();
379
-        return $tickets_sold;
380
-    }
381
-
382
-
383
-    /**
384
-     * This returns the base price object for the ticket.
385
-     *
386
-     * @param bool $return_array whether to return as an array indexed by price id or just the object.
387
-     * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
388
-     * @throws EE_Error
389
-     * @throws ReflectionException
390
-     */
391
-    public function base_price($return_array = false)
392
-    {
393
-        $_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
394
-        return $return_array
395
-            ? $this->get_many_related('Price', [$_where])
396
-            : $this->get_first_related('Price', [$_where]);
397
-    }
398
-
399
-
400
-    /**
401
-     * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
402
-     *
403
-     * @access public
404
-     * @return EE_Price[]
405
-     * @throws EE_Error
406
-     */
407
-    public function price_modifiers()
408
-    {
409
-        $query_params = [
410
-            0 => [
411
-                'Price_Type.PBT_ID' => [
412
-                    'NOT IN',
413
-                    [EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
414
-                ],
415
-            ],
416
-        ];
417
-        return $this->prices($query_params);
418
-    }
419
-
420
-
421
-    /**
422
-     * Gets all the prices that combine to form the final price of this ticket
423
-     *
424
-     * @param array $query_params @see
425
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
426
-     * @return EE_Price[]|EE_Base_Class[]
427
-     * @throws EE_Error
428
-     * @throws ReflectionException
429
-     */
430
-    public function prices($query_params = [])
431
-    {
432
-        return $this->get_many_related('Price', $query_params);
433
-    }
434
-
435
-
436
-    /**
437
-     * Gets all the ticket applicabilities (ie, relations between datetimes and tickets)
438
-     *
439
-     * @param array $query_params @see
440
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
441
-     * @return EE_Datetime_Ticket|EE_Base_Class[]
442
-     * @throws EE_Error
443
-     * @throws ReflectionException
444
-     */
445
-    public function datetime_tickets($query_params = [])
446
-    {
447
-        return $this->get_many_related('Datetime_Ticket', $query_params);
448
-    }
449
-
450
-
451
-    /**
452
-     * Gets all the datetimes from the db ordered by DTT_order
453
-     *
454
-     * @param boolean $show_expired
455
-     * @param boolean $show_deleted
456
-     * @return EE_Datetime[]
457
-     * @throws EE_Error
458
-     */
459
-    public function datetimes_ordered($show_expired = true, $show_deleted = false)
460
-    {
461
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
462
-            $this->ID(),
463
-            $show_expired,
464
-            $show_deleted
465
-        );
466
-    }
467
-
468
-
469
-    /**
470
-     * Gets ID
471
-     *
472
-     * @return int
473
-     * @throws EE_Error
474
-     * @throws ReflectionException
475
-     */
476
-    public function ID()
477
-    {
478
-        return (int) $this->get('TKT_ID');
479
-    }
480
-
481
-
482
-    /**
483
-     * get the author of the ticket.
484
-     *
485
-     * @return int
486
-     * @throws EE_Error
487
-     * @throws ReflectionException
488
-     * @since 4.5.0
489
-     */
490
-    public function wp_user()
491
-    {
492
-        return $this->get('TKT_wp_user');
493
-    }
494
-
495
-
496
-    /**
497
-     * Gets the template for the ticket
498
-     *
499
-     * @return EE_Ticket_Template|EE_Base_Class
500
-     * @throws EE_Error
501
-     * @throws ReflectionException
502
-     */
503
-    public function template()
504
-    {
505
-        return $this->get_first_related('Ticket_Template');
506
-    }
507
-
508
-
509
-    /**
510
-     * Simply returns an array of EE_Price objects that are taxes.
511
-     *
512
-     * @return EE_Price[]
513
-     * @throws EE_Error
514
-     */
515
-    public function get_ticket_taxes_for_admin()
516
-    {
517
-        return EE_Taxes::get_taxes_for_admin();
518
-    }
519
-
520
-
521
-    /**
522
-     * @return float
523
-     * @throws EE_Error
524
-     * @throws ReflectionException
525
-     */
526
-    public function ticket_price()
527
-    {
528
-        return $this->get('TKT_price');
529
-    }
530
-
531
-
532
-    /**
533
-     * @return mixed
534
-     * @throws EE_Error
535
-     * @throws ReflectionException
536
-     */
537
-    public function pretty_price()
538
-    {
539
-        return $this->get_pretty('TKT_price');
540
-    }
541
-
542
-
543
-    /**
544
-     * @return bool
545
-     * @throws EE_Error
546
-     */
547
-    public function is_free()
548
-    {
549
-        return $this->get_ticket_total_with_taxes() === (float) 0;
550
-    }
551
-
552
-
553
-    /**
554
-     * get_ticket_total_with_taxes
555
-     *
556
-     * @param bool $no_cache
557
-     * @return float
558
-     * @throws EE_Error
559
-     */
560
-    public function get_ticket_total_with_taxes($no_cache = false)
561
-    {
562
-        if ($this->_ticket_total_with_taxes === null || $no_cache) {
563
-            $this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
564
-        }
565
-        return (float) $this->_ticket_total_with_taxes;
566
-    }
567
-
568
-
569
-    public function ensure_TKT_Price_correct()
570
-    {
571
-        $this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
572
-        $this->save();
573
-    }
574
-
575
-
576
-    /**
577
-     * @return float
578
-     * @throws EE_Error
579
-     */
580
-    public function get_ticket_subtotal()
581
-    {
582
-        return EE_Taxes::get_subtotal_for_admin($this);
583
-    }
584
-
585
-
586
-    /**
587
-     * Returns the total taxes applied to this ticket
588
-     *
589
-     * @return float
590
-     * @throws EE_Error
591
-     */
592
-    public function get_ticket_taxes_total_for_admin()
593
-    {
594
-        return EE_Taxes::get_total_taxes_for_admin($this);
595
-    }
596
-
597
-
598
-    /**
599
-     * Sets name
600
-     *
601
-     * @param string $name
602
-     * @throws EE_Error
603
-     * @throws ReflectionException
604
-     */
605
-    public function set_name($name)
606
-    {
607
-        $this->set('TKT_name', $name);
608
-    }
609
-
610
-
611
-    /**
612
-     * Gets description
613
-     *
614
-     * @return string
615
-     * @throws EE_Error
616
-     * @throws ReflectionException
617
-     */
618
-    public function description()
619
-    {
620
-        return $this->get('TKT_description');
621
-    }
622
-
623
-
624
-    /**
625
-     * Sets description
626
-     *
627
-     * @param string $description
628
-     * @throws EE_Error
629
-     * @throws ReflectionException
630
-     */
631
-    public function set_description($description)
632
-    {
633
-        $this->set('TKT_description', $description);
634
-    }
635
-
636
-
637
-    /**
638
-     * Gets start_date
639
-     *
640
-     * @param string $dt_frmt
641
-     * @param string $tm_frmt
642
-     * @return string
643
-     * @throws EE_Error
644
-     * @throws ReflectionException
645
-     */
646
-    public function start_date($dt_frmt = '', $tm_frmt = '')
647
-    {
648
-        return $this->_get_datetime('TKT_start_date', $dt_frmt, $tm_frmt);
649
-    }
650
-
651
-
652
-    /**
653
-     * Sets start_date
654
-     *
655
-     * @param string $start_date
656
-     * @return void
657
-     * @throws EE_Error
658
-     * @throws ReflectionException
659
-     */
660
-    public function set_start_date($start_date)
661
-    {
662
-        $this->_set_date_time('B', $start_date, 'TKT_start_date');
663
-    }
664
-
665
-
666
-    /**
667
-     * Gets end_date
668
-     *
669
-     * @param string $dt_frmt
670
-     * @param string $tm_frmt
671
-     * @return string
672
-     * @throws EE_Error
673
-     * @throws ReflectionException
674
-     */
675
-    public function end_date($dt_frmt = '', $tm_frmt = '')
676
-    {
677
-        return $this->_get_datetime('TKT_end_date', $dt_frmt, $tm_frmt);
678
-    }
679
-
680
-
681
-    /**
682
-     * Sets end_date
683
-     *
684
-     * @param string $end_date
685
-     * @return void
686
-     * @throws EE_Error
687
-     * @throws ReflectionException
688
-     */
689
-    public function set_end_date($end_date)
690
-    {
691
-        $this->_set_date_time('B', $end_date, 'TKT_end_date');
692
-    }
693
-
694
-
695
-    /**
696
-     * Sets sell until time
697
-     *
698
-     * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
699
-     * @throws EE_Error*@throws ReflectionException
700
-     * @since 4.5.0
701
-     */
702
-    public function set_end_time($time)
703
-    {
704
-        $this->_set_time_for($time, 'TKT_end_date');
705
-    }
706
-
707
-
708
-    /**
709
-     * Sets min
710
-     *
711
-     * @param int $min
712
-     * @return void
713
-     * @throws EE_Error
714
-     * @throws ReflectionException
715
-     */
716
-    public function set_min($min)
717
-    {
718
-        $this->set('TKT_min', $min);
719
-    }
720
-
721
-
722
-    /**
723
-     * Gets max
724
-     *
725
-     * @return int
726
-     * @throws EE_Error
727
-     * @throws ReflectionException
728
-     */
729
-    public function max()
730
-    {
731
-        return $this->get('TKT_max');
732
-    }
733
-
734
-
735
-    /**
736
-     * Sets max
737
-     *
738
-     * @param int $max
739
-     * @return void
740
-     * @throws EE_Error
741
-     * @throws ReflectionException
742
-     */
743
-    public function set_max($max)
744
-    {
745
-        $this->set('TKT_max', $max);
746
-    }
747
-
748
-
749
-    /**
750
-     * Sets price
751
-     *
752
-     * @param float $price
753
-     * @return void
754
-     * @throws EE_Error
755
-     * @throws ReflectionException
756
-     */
757
-    public function set_price($price)
758
-    {
759
-        $this->set('TKT_price', $price);
760
-    }
761
-
762
-
763
-    /**
764
-     * Gets sold
765
-     *
766
-     * @return int
767
-     * @throws EE_Error
768
-     * @throws ReflectionException
769
-     */
770
-    public function sold()
771
-    {
772
-        return $this->get_raw('TKT_sold');
773
-    }
774
-
775
-
776
-    /**
777
-     * Sets sold
778
-     *
779
-     * @param int $sold
780
-     * @return void
781
-     * @throws EE_Error
782
-     * @throws ReflectionException
783
-     */
784
-    public function set_sold($sold)
785
-    {
786
-        // sold can not go below zero
787
-        $sold = max(0, $sold);
788
-        $this->set('TKT_sold', $sold);
789
-    }
790
-
791
-
792
-    /**
793
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
794
-     * associated datetimes.
795
-     *
796
-     * @param int $qty
797
-     * @return boolean
798
-     * @throws EE_Error
799
-     * @throws InvalidArgumentException
800
-     * @throws InvalidDataTypeException
801
-     * @throws InvalidInterfaceException
802
-     * @throws ReflectionException
803
-     * @since 4.9.80.p
804
-     */
805
-    public function increaseSold($qty = 1)
806
-    {
807
-        $qty = absint($qty);
808
-        // increment sold and decrement reserved datetime quantities simultaneously
809
-        // don't worry about failures, because they must have already had a spot reserved
810
-        $this->increaseSoldForDatetimes($qty);
811
-        // Increment and decrement ticket quantities simultaneously
812
-        $success = $this->adjustNumericFieldsInDb(
813
-            [
814
-                'TKT_reserved' => $qty * -1,
815
-                'TKT_sold'     => $qty,
816
-            ]
817
-        );
818
-        do_action(
819
-            'AHEE__EE_Ticket__increase_sold',
820
-            $this,
821
-            $qty,
822
-            $this->sold(),
823
-            $success
824
-        );
825
-        return $success;
826
-    }
827
-
828
-
829
-    /**
830
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
831
-     *
832
-     * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
833
-     *                           counts), Negative means to decreases old counts (and increase reserved counts).
834
-     * @param EE_Datetime[] $datetimes
835
-     * @throws EE_Error
836
-     * @throws InvalidArgumentException
837
-     * @throws InvalidDataTypeException
838
-     * @throws InvalidInterfaceException
839
-     * @throws ReflectionException
840
-     * @since 4.9.80.p
841
-     */
842
-    protected function increaseSoldForDatetimes($qty, array $datetimes = [])
843
-    {
844
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
845
-        foreach ($datetimes as $datetime) {
846
-            $datetime->increaseSold($qty);
847
-        }
848
-    }
849
-
850
-
851
-    /**
852
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
853
-     * DB and then updates the model objects.
854
-     * Does not affect the reserved counts.
855
-     *
856
-     * @param int $qty
857
-     * @return boolean
858
-     * @throws EE_Error
859
-     * @throws InvalidArgumentException
860
-     * @throws InvalidDataTypeException
861
-     * @throws InvalidInterfaceException
862
-     * @throws ReflectionException
863
-     * @since 4.9.80.p
864
-     */
865
-    public function decreaseSold($qty = 1)
866
-    {
867
-        $qty = absint($qty);
868
-        $this->decreaseSoldForDatetimes($qty);
869
-        $success = $this->adjustNumericFieldsInDb(
870
-            [
871
-                'TKT_sold' => $qty * -1,
872
-            ]
873
-        );
874
-        do_action(
875
-            'AHEE__EE_Ticket__decrease_sold',
876
-            $this,
877
-            $qty,
878
-            $this->sold(),
879
-            $success
880
-        );
881
-        return $success;
882
-    }
883
-
884
-
885
-    /**
886
-     * Decreases sold on related datetimes
887
-     *
888
-     * @param int           $qty
889
-     * @param EE_Datetime[] $datetimes
890
-     * @return void
891
-     * @throws EE_Error
892
-     * @throws InvalidArgumentException
893
-     * @throws InvalidDataTypeException
894
-     * @throws InvalidInterfaceException
895
-     * @throws ReflectionException
896
-     * @since 4.9.80.p
897
-     */
898
-    protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
899
-    {
900
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
901
-        if (is_array($datetimes)) {
902
-            foreach ($datetimes as $datetime) {
903
-                if ($datetime instanceof EE_Datetime) {
904
-                    $datetime->decreaseSold($qty);
905
-                }
906
-            }
907
-        }
908
-    }
909
-
910
-
911
-    /**
912
-     * Gets qty of reserved tickets
913
-     *
914
-     * @return int
915
-     * @throws EE_Error
916
-     * @throws ReflectionException
917
-     */
918
-    public function reserved()
919
-    {
920
-        return $this->get_raw('TKT_reserved');
921
-    }
922
-
923
-
924
-    /**
925
-     * Sets reserved
926
-     *
927
-     * @param int $reserved
928
-     * @return void
929
-     * @throws EE_Error
930
-     * @throws ReflectionException
931
-     */
932
-    public function set_reserved($reserved)
933
-    {
934
-        // reserved can not go below zero
935
-        $reserved = max(0, (int) $reserved);
936
-        $this->set('TKT_reserved', $reserved);
937
-    }
938
-
939
-
940
-    /**
941
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
942
-     *
943
-     * @param int    $qty
944
-     * @param string $source
945
-     * @return bool whether we successfully reserved the ticket or not.
946
-     * @throws EE_Error
947
-     * @throws InvalidArgumentException
948
-     * @throws ReflectionException
949
-     * @throws InvalidDataTypeException
950
-     * @throws InvalidInterfaceException
951
-     * @since 4.9.80.p
952
-     */
953
-    public function increaseReserved($qty = 1, $source = 'unknown')
954
-    {
955
-        $qty = absint($qty);
956
-        do_action(
957
-            'AHEE__EE_Ticket__increase_reserved__begin',
958
-            $this,
959
-            $qty,
960
-            $source
961
-        );
962
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
963
-        $success                         = false;
964
-        $datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
965
-        if ($datetimes_adjusted_successfully) {
966
-            $success = $this->incrementFieldConditionallyInDb(
967
-                'TKT_reserved',
968
-                'TKT_sold',
969
-                'TKT_qty',
970
-                $qty
971
-            );
972
-            if (! $success) {
973
-                // The datetimes were successfully bumped, but not the
974
-                // ticket. So we need to manually rollback the datetimes.
975
-                $this->decreaseReservedForDatetimes($qty);
976
-            }
977
-        }
978
-        do_action(
979
-            'AHEE__EE_Ticket__increase_reserved',
980
-            $this,
981
-            $qty,
982
-            $this->reserved(),
983
-            $success
984
-        );
985
-        return $success;
986
-    }
987
-
988
-
989
-    /**
990
-     * Increases reserved counts on related datetimes
991
-     *
992
-     * @param int           $qty
993
-     * @param EE_Datetime[] $datetimes
994
-     * @return boolean indicating success
995
-     * @throws EE_Error
996
-     * @throws InvalidArgumentException
997
-     * @throws InvalidDataTypeException
998
-     * @throws InvalidInterfaceException
999
-     * @throws ReflectionException
1000
-     * @since 4.9.80.p
1001
-     */
1002
-    protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1003
-    {
1004
-        $datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1005
-        $datetimes_updated = [];
1006
-        $limit_exceeded    = false;
1007
-        if (is_array($datetimes)) {
1008
-            foreach ($datetimes as $datetime) {
1009
-                if ($datetime instanceof EE_Datetime) {
1010
-                    if ($datetime->increaseReserved($qty)) {
1011
-                        $datetimes_updated[] = $datetime;
1012
-                    } else {
1013
-                        $limit_exceeded = true;
1014
-                        break;
1015
-                    }
1016
-                }
1017
-            }
1018
-            // If somewhere along the way we detected a datetime whose
1019
-            // limit was exceeded, do a manual rollback.
1020
-            if ($limit_exceeded) {
1021
-                $this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1022
-                return false;
1023
-            }
1024
-        }
1025
-        return true;
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1031
-     *
1032
-     * @param int    $qty
1033
-     * @param bool   $adjust_datetimes
1034
-     * @param string $source
1035
-     * @return boolean
1036
-     * @throws EE_Error
1037
-     * @throws InvalidArgumentException
1038
-     * @throws ReflectionException
1039
-     * @throws InvalidDataTypeException
1040
-     * @throws InvalidInterfaceException
1041
-     * @since 4.9.80.p
1042
-     */
1043
-    public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1044
-    {
1045
-        $qty = absint($qty);
1046
-        $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1047
-        if ($adjust_datetimes) {
1048
-            $this->decreaseReservedForDatetimes($qty);
1049
-        }
1050
-        $success = $this->adjustNumericFieldsInDb(
1051
-            [
1052
-                'TKT_reserved' => $qty * -1,
1053
-            ]
1054
-        );
1055
-        do_action(
1056
-            'AHEE__EE_Ticket__decrease_reserved',
1057
-            $this,
1058
-            $qty,
1059
-            $this->reserved(),
1060
-            $success
1061
-        );
1062
-        return $success;
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * Decreases the reserved count on the specified datetimes.
1068
-     *
1069
-     * @param int           $qty
1070
-     * @param EE_Datetime[] $datetimes
1071
-     * @throws EE_Error
1072
-     * @throws InvalidArgumentException
1073
-     * @throws ReflectionException
1074
-     * @throws InvalidDataTypeException
1075
-     * @throws InvalidInterfaceException
1076
-     * @since 4.9.80.p
1077
-     */
1078
-    protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1079
-    {
1080
-        $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1081
-        foreach ($datetimes as $datetime) {
1082
-            if ($datetime instanceof EE_Datetime) {
1083
-                $datetime->decreaseReserved($qty);
1084
-            }
1085
-        }
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     * Gets ticket quantity
1091
-     *
1092
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1093
-     *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1094
-     *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1095
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1096
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1097
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1098
-     * @return int
1099
-     * @throws EE_Error
1100
-     * @throws ReflectionException
1101
-     */
1102
-    public function qty($context = '')
1103
-    {
1104
-        switch ($context) {
1105
-            case 'reg_limit':
1106
-                return $this->real_quantity_on_ticket();
1107
-            case 'saleable':
1108
-                return $this->real_quantity_on_ticket('saleable');
1109
-            default:
1110
-                return $this->get_raw('TKT_qty');
1111
-        }
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * Gets ticket quantity
1117
-     *
1118
-     * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1119
-     *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1120
-     *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1121
-     *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1122
-     *                            is therefore the truest measure of tickets that can be purchased at the moment
1123
-     * @param int    $DTT_ID      the primary key for a particular datetime.
1124
-     *                            set to 0 for all related datetimes
1125
-     * @return int
1126
-     * @throws EE_Error
1127
-     * @throws ReflectionException
1128
-     */
1129
-    public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1130
-    {
1131
-        $raw = $this->get_raw('TKT_qty');
1132
-        // return immediately if it's zero
1133
-        if ($raw === 0) {
1134
-            return $raw;
1135
-        }
1136
-        // echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1137
-        // ensure qty doesn't exceed raw value for THIS ticket
1138
-        $qty = min(EE_INF, $raw);
1139
-        // echo "\n . qty: " . $qty . '<br />';
1140
-        // calculate this ticket's total sales and reservations
1141
-        $sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1142
-        // echo "\n . sold: " . $this->sold() . '<br />';
1143
-        // echo "\n . reserved: " . $this->reserved() . '<br />';
1144
-        // echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1145
-        // first we need to calculate the maximum number of tickets available for the datetime
1146
-        // do we want data for one datetime or all of them ?
1147
-        $query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1148
-        $datetimes    = $this->datetimes($query_params);
1149
-        if (is_array($datetimes) && ! empty($datetimes)) {
1150
-            foreach ($datetimes as $datetime) {
1151
-                if ($datetime instanceof EE_Datetime) {
1152
-                    $datetime->refresh_from_db();
1153
-                    // echo "\n . . datetime name: " . $datetime->name() . '<br />';
1154
-                    // echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1155
-                    // initialize with no restrictions for each datetime
1156
-                    // but adjust datetime qty based on datetime reg limit
1157
-                    $datetime_qty = min(EE_INF, $datetime->reg_limit());
1158
-                    // echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1159
-                    // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1160
-                    // if we want the actual saleable amount, then we need to consider OTHER ticket sales
1161
-                    // and reservations for this datetime, that do NOT include sales and reservations
1162
-                    // for this ticket (so we add $this->sold() and $this->reserved() back in)
1163
-                    if ($context === 'saleable') {
1164
-                        $datetime_qty = max(
1165
-                            $datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1166
-                            0
1167
-                        );
1168
-                        // echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1169
-                        // echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1170
-                        // echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1171
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1172
-                        $datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1173
-                        // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1174
-                    }
1175
-                    $qty = min($datetime_qty, $qty);
1176
-                    // echo "\n . . qty: " . $qty . '<br />';
1177
-                }
1178
-            }
1179
-        }
1180
-        // NOW that we know the  maximum number of tickets available for the datetime
1181
-        // we can finally factor in the details for this specific ticket
1182
-        if ($qty > 0 && $context === 'saleable') {
1183
-            // and subtract the sales for THIS ticket
1184
-            $qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1185
-            // echo "\n . qty: " . $qty . '<br />';
1186
-        }
1187
-        // echo "\nFINAL QTY: " . $qty . "<br /><br />";
1188
-        return $qty;
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1194
-     *
1195
-     * @param int $qty
1196
-     * @return void
1197
-     * @throws EE_Error
1198
-     * @throws ReflectionException
1199
-     */
1200
-    public function set_qty($qty)
1201
-    {
1202
-        $datetimes = $this->datetimes();
1203
-        foreach ($datetimes as $datetime) {
1204
-            if ($datetime instanceof EE_Datetime) {
1205
-                $qty = min($qty, $datetime->reg_limit());
1206
-            }
1207
-        }
1208
-        $this->set('TKT_qty', $qty);
1209
-    }
1210
-
1211
-
1212
-    /**
1213
-     * Gets uses
1214
-     *
1215
-     * @return int
1216
-     * @throws EE_Error
1217
-     * @throws ReflectionException
1218
-     */
1219
-    public function uses()
1220
-    {
1221
-        return $this->get('TKT_uses');
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * Sets uses
1227
-     *
1228
-     * @param int $uses
1229
-     * @return void
1230
-     * @throws EE_Error
1231
-     * @throws ReflectionException
1232
-     */
1233
-    public function set_uses($uses)
1234
-    {
1235
-        $this->set('TKT_uses', $uses);
1236
-    }
1237
-
1238
-
1239
-    /**
1240
-     * returns whether ticket is required or not.
1241
-     *
1242
-     * @return boolean
1243
-     * @throws EE_Error
1244
-     * @throws ReflectionException
1245
-     */
1246
-    public function required()
1247
-    {
1248
-        return $this->get('TKT_required');
1249
-    }
1250
-
1251
-
1252
-    /**
1253
-     * sets the TKT_required property
1254
-     *
1255
-     * @param boolean $required
1256
-     * @return void
1257
-     * @throws EE_Error
1258
-     * @throws ReflectionException
1259
-     */
1260
-    public function set_required($required)
1261
-    {
1262
-        $this->set('TKT_required', $required);
1263
-    }
1264
-
1265
-
1266
-    /**
1267
-     * Gets taxable
1268
-     *
1269
-     * @return boolean
1270
-     * @throws EE_Error
1271
-     * @throws ReflectionException
1272
-     */
1273
-    public function taxable()
1274
-    {
1275
-        return $this->get('TKT_taxable');
1276
-    }
1277
-
1278
-
1279
-    /**
1280
-     * Sets taxable
1281
-     *
1282
-     * @param boolean $taxable
1283
-     * @return void
1284
-     * @throws EE_Error
1285
-     * @throws ReflectionException
1286
-     */
1287
-    public function set_taxable($taxable)
1288
-    {
1289
-        $this->set('TKT_taxable', $taxable);
1290
-    }
1291
-
1292
-
1293
-    /**
1294
-     * Gets is_default
1295
-     *
1296
-     * @return boolean
1297
-     * @throws EE_Error
1298
-     * @throws ReflectionException
1299
-     */
1300
-    public function is_default()
1301
-    {
1302
-        return $this->get('TKT_is_default');
1303
-    }
1304
-
1305
-
1306
-    /**
1307
-     * Sets is_default
1308
-     *
1309
-     * @param boolean $is_default
1310
-     * @return void
1311
-     * @throws EE_Error
1312
-     * @throws ReflectionException
1313
-     */
1314
-    public function set_is_default($is_default)
1315
-    {
1316
-        $this->set('TKT_is_default', $is_default);
1317
-    }
1318
-
1319
-
1320
-    /**
1321
-     * Gets order
1322
-     *
1323
-     * @return int
1324
-     * @throws EE_Error
1325
-     * @throws ReflectionException
1326
-     */
1327
-    public function order()
1328
-    {
1329
-        return $this->get('TKT_order');
1330
-    }
1331
-
1332
-
1333
-    /**
1334
-     * Sets order
1335
-     *
1336
-     * @param int $order
1337
-     * @return void
1338
-     * @throws EE_Error
1339
-     * @throws ReflectionException
1340
-     */
1341
-    public function set_order($order)
1342
-    {
1343
-        $this->set('TKT_order', $order);
1344
-    }
1345
-
1346
-
1347
-    /**
1348
-     * Gets row
1349
-     *
1350
-     * @return int
1351
-     * @throws EE_Error
1352
-     * @throws ReflectionException
1353
-     */
1354
-    public function row()
1355
-    {
1356
-        return $this->get('TKT_row');
1357
-    }
1358
-
1359
-
1360
-    /**
1361
-     * Sets row
1362
-     *
1363
-     * @param int $row
1364
-     * @return void
1365
-     * @throws EE_Error
1366
-     * @throws ReflectionException
1367
-     */
1368
-    public function set_row($row)
1369
-    {
1370
-        $this->set('TKT_row', $row);
1371
-    }
1372
-
1373
-
1374
-    /**
1375
-     * Gets deleted
1376
-     *
1377
-     * @return boolean
1378
-     * @throws EE_Error
1379
-     * @throws ReflectionException
1380
-     */
1381
-    public function deleted()
1382
-    {
1383
-        return $this->get('TKT_deleted');
1384
-    }
1385
-
1386
-
1387
-    /**
1388
-     * Sets deleted
1389
-     *
1390
-     * @param boolean $deleted
1391
-     * @return void
1392
-     * @throws EE_Error
1393
-     * @throws ReflectionException
1394
-     */
1395
-    public function set_deleted($deleted)
1396
-    {
1397
-        $this->set('TKT_deleted', $deleted);
1398
-    }
1399
-
1400
-
1401
-    /**
1402
-     * Gets parent
1403
-     *
1404
-     * @return int
1405
-     * @throws EE_Error
1406
-     * @throws ReflectionException
1407
-     */
1408
-    public function parent_ID()
1409
-    {
1410
-        return $this->get('TKT_parent');
1411
-    }
1412
-
1413
-
1414
-    /**
1415
-     * Sets parent
1416
-     *
1417
-     * @param int $parent
1418
-     * @return void
1419
-     * @throws EE_Error
1420
-     * @throws ReflectionException
1421
-     */
1422
-    public function set_parent_ID($parent)
1423
-    {
1424
-        $this->set('TKT_parent', $parent);
1425
-    }
1426
-
1427
-
1428
-    /**
1429
-     * Gets a string which is handy for showing in gateways etc that describes the ticket.
1430
-     *
1431
-     * @return string
1432
-     * @throws EE_Error
1433
-     * @throws ReflectionException
1434
-     */
1435
-    public function name_and_info()
1436
-    {
1437
-        $times = [];
1438
-        foreach ($this->datetimes() as $datetime) {
1439
-            $times[] = $datetime->start_date_and_time();
1440
-        }
1441
-        return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1442
-    }
1443
-
1444
-
1445
-    /**
1446
-     * Gets name
1447
-     *
1448
-     * @return string
1449
-     * @throws EE_Error
1450
-     * @throws ReflectionException
1451
-     */
1452
-    public function name()
1453
-    {
1454
-        return $this->get('TKT_name');
1455
-    }
1456
-
1457
-
1458
-    /**
1459
-     * Gets price
1460
-     *
1461
-     * @return float
1462
-     * @throws EE_Error
1463
-     * @throws ReflectionException
1464
-     */
1465
-    public function price()
1466
-    {
1467
-        return $this->get('TKT_price');
1468
-    }
1469
-
1470
-
1471
-    /**
1472
-     * Gets all the registrations for this ticket
1473
-     *
1474
-     * @param array $query_params @see
1475
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1476
-     * @return EE_Registration[]|EE_Base_Class[]
1477
-     * @throws EE_Error
1478
-     * @throws ReflectionException
1479
-     */
1480
-    public function registrations($query_params = [])
1481
-    {
1482
-        return $this->get_many_related('Registration', $query_params);
1483
-    }
1484
-
1485
-
1486
-    /**
1487
-     * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1488
-     *
1489
-     * @return int
1490
-     * @throws EE_Error
1491
-     * @throws ReflectionException
1492
-     */
1493
-    public function update_tickets_sold()
1494
-    {
1495
-        $count_regs_for_this_ticket = $this->count_registrations(
1496
-            [
1497
-                [
1498
-                    'STS_ID'      => EEM_Registration::status_id_approved,
1499
-                    'REG_deleted' => 0,
1500
-                ],
1501
-            ]
1502
-        );
1503
-        $this->set_sold($count_regs_for_this_ticket);
1504
-        $this->save();
1505
-        return $count_regs_for_this_ticket;
1506
-    }
1507
-
1508
-
1509
-    /**
1510
-     * Counts the registrations for this ticket
1511
-     *
1512
-     * @param array $query_params @see
1513
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1514
-     * @return int
1515
-     */
1516
-    public function count_registrations($query_params = [])
1517
-    {
1518
-        return $this->count_related('Registration', $query_params);
1519
-    }
1520
-
1521
-
1522
-    /**
1523
-     * Implementation for EEI_Has_Icon interface method.
1524
-     *
1525
-     * @return string
1526
-     * @see EEI_Visual_Representation for comments
1527
-     */
1528
-    public function get_icon()
1529
-    {
1530
-        return '<span class="dashicons dashicons-tickets-alt"></span>';
1531
-    }
1532
-
1533
-
1534
-    /**
1535
-     * Implementation of the EEI_Event_Relation interface method
1536
-     *
1537
-     * @return EE_Event
1538
-     * @throws EE_Error
1539
-     * @throws UnexpectedEntityException*@throws ReflectionException
1540
-     * @see EEI_Event_Relation for comments
1541
-     */
1542
-    public function get_related_event()
1543
-    {
1544
-        // get one datetime to use for getting the event
1545
-        $datetime = $this->first_datetime();
1546
-        if (! $datetime instanceof \EE_Datetime) {
1547
-            throw new UnexpectedEntityException(
1548
-                $datetime,
1549
-                'EE_Datetime',
1550
-                sprintf(
1551
-                    esc_html__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1552
-                    $this->name()
1553
-                )
1554
-            );
1555
-        }
1556
-        $event = $datetime->event();
1557
-        if (! $event instanceof \EE_Event) {
1558
-            throw new UnexpectedEntityException(
1559
-                $event,
1560
-                'EE_Event',
1561
-                sprintf(
1562
-                    esc_html__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1563
-                    $this->name()
1564
-                )
1565
-            );
1566
-        }
1567
-        return $event;
1568
-    }
1569
-
1570
-
1571
-    /**
1572
-     * Implementation of the EEI_Event_Relation interface method
1573
-     *
1574
-     * @return string
1575
-     * @throws UnexpectedEntityException
1576
-     * @throws EE_Error*@throws ReflectionException
1577
-     * @see EEI_Event_Relation for comments
1578
-     */
1579
-    public function get_event_name()
1580
-    {
1581
-        $event = $this->get_related_event();
1582
-        return $event instanceof EE_Event ? $event->name() : '';
1583
-    }
1584
-
1585
-
1586
-    /**
1587
-     * Implementation of the EEI_Event_Relation interface method
1588
-     *
1589
-     * @return int
1590
-     * @throws UnexpectedEntityException
1591
-     * @throws EE_Error*@throws ReflectionException
1592
-     * @see EEI_Event_Relation for comments
1593
-     */
1594
-    public function get_event_ID()
1595
-    {
1596
-        $event = $this->get_related_event();
1597
-        return $event instanceof EE_Event ? $event->ID() : 0;
1598
-    }
1599
-
1600
-
1601
-    /**
1602
-     * This simply returns whether a ticket can be permanently deleted or not.
1603
-     * The criteria for determining this is whether the ticket has any related registrations.
1604
-     * If there are none then it can be permanently deleted.
1605
-     *
1606
-     * @return bool
1607
-     */
1608
-    public function is_permanently_deleteable()
1609
-    {
1610
-        return $this->count_registrations() === 0;
1611
-    }
1612
-
1613
-
1614
-    /*******************************************************************
16
+	/**
17
+	 * The following constants are used by the ticket_status() method to indicate whether a ticket is on sale or not.
18
+	 */
19
+	const sold_out = 'TKS';
20
+
21
+	/**
22
+	 *
23
+	 */
24
+	const expired = 'TKE';
25
+
26
+	/**
27
+	 *
28
+	 */
29
+	const archived = 'TKA';
30
+
31
+	/**
32
+	 *
33
+	 */
34
+	const pending = 'TKP';
35
+
36
+	/**
37
+	 *
38
+	 */
39
+	const onsale = 'TKO';
40
+
41
+	/**
42
+	 * extra meta key for tracking ticket reservations
43
+	 *
44
+	 * @type string
45
+	 */
46
+	const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations';
47
+
48
+	/**
49
+	 * cached result from method of the same name
50
+	 *
51
+	 * @var float $_ticket_total_with_taxes
52
+	 */
53
+	private $_ticket_total_with_taxes;
54
+
55
+
56
+	/**
57
+	 * @param array  $props_n_values          incoming values
58
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
59
+	 *                                        used.)
60
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
61
+	 *                                        date_format and the second value is the time format
62
+	 * @return EE_Ticket
63
+	 * @throws EE_Error
64
+	 * @throws ReflectionException
65
+	 */
66
+	public static function new_instance($props_n_values = [], $timezone = null, $date_formats = [])
67
+	{
68
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
69
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
70
+	}
71
+
72
+
73
+	/**
74
+	 * @param array  $props_n_values  incoming values from the database
75
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
76
+	 *                                the website will be used.
77
+	 * @return EE_Ticket
78
+	 * @throws EE_Error
79
+	 * @throws ReflectionException
80
+	 */
81
+	public static function new_instance_from_db($props_n_values = [], $timezone = null)
82
+	{
83
+		return new self($props_n_values, true, $timezone);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @return bool
89
+	 * @throws EE_Error
90
+	 * @throws ReflectionException
91
+	 */
92
+	public function parent()
93
+	{
94
+		return $this->get('TKT_parent');
95
+	}
96
+
97
+
98
+	/**
99
+	 * return if a ticket has quantities available for purchase
100
+	 *
101
+	 * @param int $DTT_ID the primary key for a particular datetime
102
+	 * @return boolean
103
+	 * @throws EE_Error
104
+	 * @throws ReflectionException
105
+	 */
106
+	public function available($DTT_ID = 0)
107
+	{
108
+		// are we checking availability for a particular datetime ?
109
+		if ($DTT_ID) {
110
+			// get that datetime object
111
+			$datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]);
112
+			// if  ticket sales for this datetime have exceeded the reg limit...
113
+			if ($datetime instanceof EE_Datetime && $datetime->sold_out()) {
114
+				return false;
115
+			}
116
+		}
117
+		// datetime is still open for registration, but is this ticket sold out ?
118
+		return $this->qty() < 1 || $this->qty() > $this->sold() ? true : false;
119
+	}
120
+
121
+
122
+	/**
123
+	 * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired
124
+	 *
125
+	 * @param bool        $display   true = we'll return a localized string, otherwise we just return the value of the
126
+	 *                               relevant status const
127
+	 * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save
128
+	 *                               further processing
129
+	 * @return mixed status int if the display string isn't requested
130
+	 * @throws EE_Error
131
+	 * @throws ReflectionException
132
+	 */
133
+	public function ticket_status($display = false, $remaining = null)
134
+	{
135
+		$remaining = is_bool($remaining) ? $remaining : $this->is_remaining();
136
+		if (! $remaining) {
137
+			return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out;
138
+		}
139
+		if ($this->get('TKT_deleted')) {
140
+			return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived;
141
+		}
142
+		if ($this->is_expired()) {
143
+			return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired;
144
+		}
145
+		if ($this->is_pending()) {
146
+			return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending;
147
+		}
148
+		if ($this->is_on_sale()) {
149
+			return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale;
150
+		}
151
+		return '';
152
+	}
153
+
154
+
155
+	/**
156
+	 * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale
157
+	 * considering ALL the factors used for figuring that out.
158
+	 *
159
+	 * @access public
160
+	 * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt.
161
+	 * @return boolean         true = tickets remaining, false not.
162
+	 * @throws EE_Error
163
+	 */
164
+	public function is_remaining($DTT_ID = 0)
165
+	{
166
+		$num_remaining = $this->remaining($DTT_ID);
167
+		if ($num_remaining === 0) {
168
+			return false;
169
+		}
170
+		if ($num_remaining > 0 && $num_remaining < $this->min()) {
171
+			return false;
172
+		}
173
+		return true;
174
+	}
175
+
176
+
177
+	/**
178
+	 * return the total number of tickets available for purchase
179
+	 *
180
+	 * @param int $DTT_ID  the primary key for a particular datetime.
181
+	 *                     set to 0 for all related datetimes
182
+	 * @return int
183
+	 * @throws EE_Error
184
+	 */
185
+	public function remaining($DTT_ID = 0)
186
+	{
187
+		return $this->real_quantity_on_ticket('saleable', $DTT_ID);
188
+	}
189
+
190
+
191
+	/**
192
+	 * Gets min
193
+	 *
194
+	 * @return int
195
+	 * @throws EE_Error
196
+	 * @throws ReflectionException
197
+	 */
198
+	public function min()
199
+	{
200
+		return $this->get('TKT_min');
201
+	}
202
+
203
+
204
+	/**
205
+	 * return if a ticket is no longer available cause its available dates have expired.
206
+	 *
207
+	 * @return boolean
208
+	 * @throws EE_Error
209
+	 * @throws ReflectionException
210
+	 */
211
+	public function is_expired()
212
+	{
213
+		return ($this->get_raw('TKT_end_date') < time());
214
+	}
215
+
216
+
217
+	/**
218
+	 * Return if a ticket is yet to go on sale or not
219
+	 *
220
+	 * @return boolean
221
+	 * @throws EE_Error
222
+	 * @throws ReflectionException
223
+	 */
224
+	public function is_pending()
225
+	{
226
+		return ($this->get_raw('TKT_start_date') > time());
227
+	}
228
+
229
+
230
+	/**
231
+	 * Return if a ticket is on sale or not
232
+	 *
233
+	 * @return boolean
234
+	 * @throws EE_Error
235
+	 * @throws ReflectionException
236
+	 */
237
+	public function is_on_sale()
238
+	{
239
+		return ($this->get_raw('TKT_start_date') < time() && $this->get_raw('TKT_end_date') > time());
240
+	}
241
+
242
+
243
+	/**
244
+	 * This returns the chronologically last datetime that this ticket is associated with
245
+	 *
246
+	 * @param string $dt_frmt
247
+	 * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with
248
+	 *                            the end date ie: Jan 01 "to" Dec 31
249
+	 * @return string
250
+	 * @throws EE_Error
251
+	 * @throws ReflectionException
252
+	 */
253
+	public function date_range($dt_frmt = '', $conjunction = ' - ')
254
+	{
255
+		$dt_frmt    = ! empty($dt_frmt) ? $dt_frmt : $this->_dt_frmt;
256
+		$first_date = $this->first_datetime() instanceof EE_Datetime
257
+			? $this->first_datetime()->get_i18n_datetime(
258
+				'DTT_EVT_start',
259
+				$dt_frmt
260
+			) : '';
261
+		$last_date  =
262
+			$this->last_datetime() instanceof EE_Datetime ? $this->last_datetime()->get_i18n_datetime(
263
+				'DTT_EVT_end',
264
+				$dt_frmt
265
+			) : '';
266
+
267
+		return $first_date && $last_date ? $first_date . $conjunction . $last_date : '';
268
+	}
269
+
270
+
271
+	/**
272
+	 * This returns the chronologically first datetime that this ticket is associated with
273
+	 *
274
+	 * @return EE_Datetime
275
+	 * @throws EE_Error
276
+	 */
277
+	public function first_datetime()
278
+	{
279
+		$datetimes = $this->datetimes(['limit' => 1]);
280
+		return reset($datetimes);
281
+	}
282
+
283
+
284
+	/**
285
+	 * Gets all the datetimes this ticket can be used for attending.
286
+	 * Unless otherwise specified, orders datetimes by start date.
287
+	 *
288
+	 * @param array $query_params @see
289
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
290
+	 * @return EE_Datetime[]|EE_Base_Class[]
291
+	 * @throws EE_Error
292
+	 * @throws ReflectionException
293
+	 */
294
+	public function datetimes($query_params = [])
295
+	{
296
+		if (! isset($query_params['order_by'])) {
297
+			$query_params['order_by']['DTT_order'] = 'ASC';
298
+		}
299
+		return $this->get_many_related('Datetime', $query_params);
300
+	}
301
+
302
+
303
+	/**
304
+	 * This returns the chronologically last datetime that this ticket is associated with
305
+	 *
306
+	 * @return EE_Datetime
307
+	 * @throws EE_Error
308
+	 */
309
+	public function last_datetime()
310
+	{
311
+		$datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]);
312
+		return end($datetimes);
313
+	}
314
+
315
+
316
+	/**
317
+	 * This returns the total tickets sold depending on the given parameters.
318
+	 *
319
+	 * @param string $what    Can be one of two options: 'ticket', 'datetime'.
320
+	 *                        'ticket' = total ticket sales for all datetimes this ticket is related to
321
+	 *                        'datetime' = total ticket sales for a specified datetime (required $dtt_id)
322
+	 *                        'datetime' = total ticket sales in the datetime_ticket table.
323
+	 *                        If $dtt_id is not given then we return an array of sales indexed by datetime.
324
+	 *                        If $dtt_id IS given then we return the tickets sold for that given datetime.
325
+	 * @param int    $dtt_id  [optional] include the dtt_id with $what = 'datetime'.
326
+	 * @return mixed (array|int)          how many tickets have sold
327
+	 * @throws EE_Error
328
+	 */
329
+	public function tickets_sold($what = 'ticket', $dtt_id = null)
330
+	{
331
+		$total        = 0;
332
+		$tickets_sold = $this->_all_tickets_sold();
333
+		switch ($what) {
334
+			case 'ticket':
335
+				return $tickets_sold['ticket'];
336
+				break;
337
+			case 'datetime':
338
+				if (empty($tickets_sold['datetime'])) {
339
+					return $total;
340
+				}
341
+				if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) {
342
+					EE_Error::add_error(
343
+						esc_html__(
344
+							'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included.  Are you SURE that is a datetime related to this ticket?',
345
+							'event_espresso'
346
+						),
347
+						__FILE__,
348
+						__FUNCTION__,
349
+						__LINE__
350
+					);
351
+					return $total;
352
+				}
353
+				return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ];
354
+				break;
355
+			default:
356
+				return $total;
357
+		}
358
+	}
359
+
360
+
361
+	/**
362
+	 * This returns an array indexed by datetime_id for tickets sold with this ticket.
363
+	 *
364
+	 * @return EE_Ticket[]
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	protected function _all_tickets_sold()
369
+	{
370
+		$datetimes    = $this->get_many_related('Datetime');
371
+		$tickets_sold = [];
372
+		if (! empty($datetimes)) {
373
+			foreach ($datetimes as $datetime) {
374
+				$tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold');
375
+			}
376
+		}
377
+		// Tickets sold
378
+		$tickets_sold['ticket'] = $this->sold();
379
+		return $tickets_sold;
380
+	}
381
+
382
+
383
+	/**
384
+	 * This returns the base price object for the ticket.
385
+	 *
386
+	 * @param bool $return_array whether to return as an array indexed by price id or just the object.
387
+	 * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[]
388
+	 * @throws EE_Error
389
+	 * @throws ReflectionException
390
+	 */
391
+	public function base_price($return_array = false)
392
+	{
393
+		$_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price];
394
+		return $return_array
395
+			? $this->get_many_related('Price', [$_where])
396
+			: $this->get_first_related('Price', [$_where]);
397
+	}
398
+
399
+
400
+	/**
401
+	 * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price)
402
+	 *
403
+	 * @access public
404
+	 * @return EE_Price[]
405
+	 * @throws EE_Error
406
+	 */
407
+	public function price_modifiers()
408
+	{
409
+		$query_params = [
410
+			0 => [
411
+				'Price_Type.PBT_ID' => [
412
+					'NOT IN',
413
+					[EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax],
414
+				],
415
+			],
416
+		];
417
+		return $this->prices($query_params);
418
+	}
419
+
420
+
421
+	/**
422
+	 * Gets all the prices that combine to form the final price of this ticket
423
+	 *
424
+	 * @param array $query_params @see
425
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
426
+	 * @return EE_Price[]|EE_Base_Class[]
427
+	 * @throws EE_Error
428
+	 * @throws ReflectionException
429
+	 */
430
+	public function prices($query_params = [])
431
+	{
432
+		return $this->get_many_related('Price', $query_params);
433
+	}
434
+
435
+
436
+	/**
437
+	 * Gets all the ticket applicabilities (ie, relations between datetimes and tickets)
438
+	 *
439
+	 * @param array $query_params @see
440
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
441
+	 * @return EE_Datetime_Ticket|EE_Base_Class[]
442
+	 * @throws EE_Error
443
+	 * @throws ReflectionException
444
+	 */
445
+	public function datetime_tickets($query_params = [])
446
+	{
447
+		return $this->get_many_related('Datetime_Ticket', $query_params);
448
+	}
449
+
450
+
451
+	/**
452
+	 * Gets all the datetimes from the db ordered by DTT_order
453
+	 *
454
+	 * @param boolean $show_expired
455
+	 * @param boolean $show_deleted
456
+	 * @return EE_Datetime[]
457
+	 * @throws EE_Error
458
+	 */
459
+	public function datetimes_ordered($show_expired = true, $show_deleted = false)
460
+	{
461
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order(
462
+			$this->ID(),
463
+			$show_expired,
464
+			$show_deleted
465
+		);
466
+	}
467
+
468
+
469
+	/**
470
+	 * Gets ID
471
+	 *
472
+	 * @return int
473
+	 * @throws EE_Error
474
+	 * @throws ReflectionException
475
+	 */
476
+	public function ID()
477
+	{
478
+		return (int) $this->get('TKT_ID');
479
+	}
480
+
481
+
482
+	/**
483
+	 * get the author of the ticket.
484
+	 *
485
+	 * @return int
486
+	 * @throws EE_Error
487
+	 * @throws ReflectionException
488
+	 * @since 4.5.0
489
+	 */
490
+	public function wp_user()
491
+	{
492
+		return $this->get('TKT_wp_user');
493
+	}
494
+
495
+
496
+	/**
497
+	 * Gets the template for the ticket
498
+	 *
499
+	 * @return EE_Ticket_Template|EE_Base_Class
500
+	 * @throws EE_Error
501
+	 * @throws ReflectionException
502
+	 */
503
+	public function template()
504
+	{
505
+		return $this->get_first_related('Ticket_Template');
506
+	}
507
+
508
+
509
+	/**
510
+	 * Simply returns an array of EE_Price objects that are taxes.
511
+	 *
512
+	 * @return EE_Price[]
513
+	 * @throws EE_Error
514
+	 */
515
+	public function get_ticket_taxes_for_admin()
516
+	{
517
+		return EE_Taxes::get_taxes_for_admin();
518
+	}
519
+
520
+
521
+	/**
522
+	 * @return float
523
+	 * @throws EE_Error
524
+	 * @throws ReflectionException
525
+	 */
526
+	public function ticket_price()
527
+	{
528
+		return $this->get('TKT_price');
529
+	}
530
+
531
+
532
+	/**
533
+	 * @return mixed
534
+	 * @throws EE_Error
535
+	 * @throws ReflectionException
536
+	 */
537
+	public function pretty_price()
538
+	{
539
+		return $this->get_pretty('TKT_price');
540
+	}
541
+
542
+
543
+	/**
544
+	 * @return bool
545
+	 * @throws EE_Error
546
+	 */
547
+	public function is_free()
548
+	{
549
+		return $this->get_ticket_total_with_taxes() === (float) 0;
550
+	}
551
+
552
+
553
+	/**
554
+	 * get_ticket_total_with_taxes
555
+	 *
556
+	 * @param bool $no_cache
557
+	 * @return float
558
+	 * @throws EE_Error
559
+	 */
560
+	public function get_ticket_total_with_taxes($no_cache = false)
561
+	{
562
+		if ($this->_ticket_total_with_taxes === null || $no_cache) {
563
+			$this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin();
564
+		}
565
+		return (float) $this->_ticket_total_with_taxes;
566
+	}
567
+
568
+
569
+	public function ensure_TKT_Price_correct()
570
+	{
571
+		$this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this));
572
+		$this->save();
573
+	}
574
+
575
+
576
+	/**
577
+	 * @return float
578
+	 * @throws EE_Error
579
+	 */
580
+	public function get_ticket_subtotal()
581
+	{
582
+		return EE_Taxes::get_subtotal_for_admin($this);
583
+	}
584
+
585
+
586
+	/**
587
+	 * Returns the total taxes applied to this ticket
588
+	 *
589
+	 * @return float
590
+	 * @throws EE_Error
591
+	 */
592
+	public function get_ticket_taxes_total_for_admin()
593
+	{
594
+		return EE_Taxes::get_total_taxes_for_admin($this);
595
+	}
596
+
597
+
598
+	/**
599
+	 * Sets name
600
+	 *
601
+	 * @param string $name
602
+	 * @throws EE_Error
603
+	 * @throws ReflectionException
604
+	 */
605
+	public function set_name($name)
606
+	{
607
+		$this->set('TKT_name', $name);
608
+	}
609
+
610
+
611
+	/**
612
+	 * Gets description
613
+	 *
614
+	 * @return string
615
+	 * @throws EE_Error
616
+	 * @throws ReflectionException
617
+	 */
618
+	public function description()
619
+	{
620
+		return $this->get('TKT_description');
621
+	}
622
+
623
+
624
+	/**
625
+	 * Sets description
626
+	 *
627
+	 * @param string $description
628
+	 * @throws EE_Error
629
+	 * @throws ReflectionException
630
+	 */
631
+	public function set_description($description)
632
+	{
633
+		$this->set('TKT_description', $description);
634
+	}
635
+
636
+
637
+	/**
638
+	 * Gets start_date
639
+	 *
640
+	 * @param string $dt_frmt
641
+	 * @param string $tm_frmt
642
+	 * @return string
643
+	 * @throws EE_Error
644
+	 * @throws ReflectionException
645
+	 */
646
+	public function start_date($dt_frmt = '', $tm_frmt = '')
647
+	{
648
+		return $this->_get_datetime('TKT_start_date', $dt_frmt, $tm_frmt);
649
+	}
650
+
651
+
652
+	/**
653
+	 * Sets start_date
654
+	 *
655
+	 * @param string $start_date
656
+	 * @return void
657
+	 * @throws EE_Error
658
+	 * @throws ReflectionException
659
+	 */
660
+	public function set_start_date($start_date)
661
+	{
662
+		$this->_set_date_time('B', $start_date, 'TKT_start_date');
663
+	}
664
+
665
+
666
+	/**
667
+	 * Gets end_date
668
+	 *
669
+	 * @param string $dt_frmt
670
+	 * @param string $tm_frmt
671
+	 * @return string
672
+	 * @throws EE_Error
673
+	 * @throws ReflectionException
674
+	 */
675
+	public function end_date($dt_frmt = '', $tm_frmt = '')
676
+	{
677
+		return $this->_get_datetime('TKT_end_date', $dt_frmt, $tm_frmt);
678
+	}
679
+
680
+
681
+	/**
682
+	 * Sets end_date
683
+	 *
684
+	 * @param string $end_date
685
+	 * @return void
686
+	 * @throws EE_Error
687
+	 * @throws ReflectionException
688
+	 */
689
+	public function set_end_date($end_date)
690
+	{
691
+		$this->_set_date_time('B', $end_date, 'TKT_end_date');
692
+	}
693
+
694
+
695
+	/**
696
+	 * Sets sell until time
697
+	 *
698
+	 * @param string $time a string representation of the sell until time (ex 9am or 7:30pm)
699
+	 * @throws EE_Error*@throws ReflectionException
700
+	 * @since 4.5.0
701
+	 */
702
+	public function set_end_time($time)
703
+	{
704
+		$this->_set_time_for($time, 'TKT_end_date');
705
+	}
706
+
707
+
708
+	/**
709
+	 * Sets min
710
+	 *
711
+	 * @param int $min
712
+	 * @return void
713
+	 * @throws EE_Error
714
+	 * @throws ReflectionException
715
+	 */
716
+	public function set_min($min)
717
+	{
718
+		$this->set('TKT_min', $min);
719
+	}
720
+
721
+
722
+	/**
723
+	 * Gets max
724
+	 *
725
+	 * @return int
726
+	 * @throws EE_Error
727
+	 * @throws ReflectionException
728
+	 */
729
+	public function max()
730
+	{
731
+		return $this->get('TKT_max');
732
+	}
733
+
734
+
735
+	/**
736
+	 * Sets max
737
+	 *
738
+	 * @param int $max
739
+	 * @return void
740
+	 * @throws EE_Error
741
+	 * @throws ReflectionException
742
+	 */
743
+	public function set_max($max)
744
+	{
745
+		$this->set('TKT_max', $max);
746
+	}
747
+
748
+
749
+	/**
750
+	 * Sets price
751
+	 *
752
+	 * @param float $price
753
+	 * @return void
754
+	 * @throws EE_Error
755
+	 * @throws ReflectionException
756
+	 */
757
+	public function set_price($price)
758
+	{
759
+		$this->set('TKT_price', $price);
760
+	}
761
+
762
+
763
+	/**
764
+	 * Gets sold
765
+	 *
766
+	 * @return int
767
+	 * @throws EE_Error
768
+	 * @throws ReflectionException
769
+	 */
770
+	public function sold()
771
+	{
772
+		return $this->get_raw('TKT_sold');
773
+	}
774
+
775
+
776
+	/**
777
+	 * Sets sold
778
+	 *
779
+	 * @param int $sold
780
+	 * @return void
781
+	 * @throws EE_Error
782
+	 * @throws ReflectionException
783
+	 */
784
+	public function set_sold($sold)
785
+	{
786
+		// sold can not go below zero
787
+		$sold = max(0, $sold);
788
+		$this->set('TKT_sold', $sold);
789
+	}
790
+
791
+
792
+	/**
793
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
794
+	 * associated datetimes.
795
+	 *
796
+	 * @param int $qty
797
+	 * @return boolean
798
+	 * @throws EE_Error
799
+	 * @throws InvalidArgumentException
800
+	 * @throws InvalidDataTypeException
801
+	 * @throws InvalidInterfaceException
802
+	 * @throws ReflectionException
803
+	 * @since 4.9.80.p
804
+	 */
805
+	public function increaseSold($qty = 1)
806
+	{
807
+		$qty = absint($qty);
808
+		// increment sold and decrement reserved datetime quantities simultaneously
809
+		// don't worry about failures, because they must have already had a spot reserved
810
+		$this->increaseSoldForDatetimes($qty);
811
+		// Increment and decrement ticket quantities simultaneously
812
+		$success = $this->adjustNumericFieldsInDb(
813
+			[
814
+				'TKT_reserved' => $qty * -1,
815
+				'TKT_sold'     => $qty,
816
+			]
817
+		);
818
+		do_action(
819
+			'AHEE__EE_Ticket__increase_sold',
820
+			$this,
821
+			$qty,
822
+			$this->sold(),
823
+			$success
824
+		);
825
+		return $success;
826
+	}
827
+
828
+
829
+	/**
830
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
831
+	 *
832
+	 * @param int           $qty positive or negative. Positive means to increase sold counts (and decrease reserved
833
+	 *                           counts), Negative means to decreases old counts (and increase reserved counts).
834
+	 * @param EE_Datetime[] $datetimes
835
+	 * @throws EE_Error
836
+	 * @throws InvalidArgumentException
837
+	 * @throws InvalidDataTypeException
838
+	 * @throws InvalidInterfaceException
839
+	 * @throws ReflectionException
840
+	 * @since 4.9.80.p
841
+	 */
842
+	protected function increaseSoldForDatetimes($qty, array $datetimes = [])
843
+	{
844
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
845
+		foreach ($datetimes as $datetime) {
846
+			$datetime->increaseSold($qty);
847
+		}
848
+	}
849
+
850
+
851
+	/**
852
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
853
+	 * DB and then updates the model objects.
854
+	 * Does not affect the reserved counts.
855
+	 *
856
+	 * @param int $qty
857
+	 * @return boolean
858
+	 * @throws EE_Error
859
+	 * @throws InvalidArgumentException
860
+	 * @throws InvalidDataTypeException
861
+	 * @throws InvalidInterfaceException
862
+	 * @throws ReflectionException
863
+	 * @since 4.9.80.p
864
+	 */
865
+	public function decreaseSold($qty = 1)
866
+	{
867
+		$qty = absint($qty);
868
+		$this->decreaseSoldForDatetimes($qty);
869
+		$success = $this->adjustNumericFieldsInDb(
870
+			[
871
+				'TKT_sold' => $qty * -1,
872
+			]
873
+		);
874
+		do_action(
875
+			'AHEE__EE_Ticket__decrease_sold',
876
+			$this,
877
+			$qty,
878
+			$this->sold(),
879
+			$success
880
+		);
881
+		return $success;
882
+	}
883
+
884
+
885
+	/**
886
+	 * Decreases sold on related datetimes
887
+	 *
888
+	 * @param int           $qty
889
+	 * @param EE_Datetime[] $datetimes
890
+	 * @return void
891
+	 * @throws EE_Error
892
+	 * @throws InvalidArgumentException
893
+	 * @throws InvalidDataTypeException
894
+	 * @throws InvalidInterfaceException
895
+	 * @throws ReflectionException
896
+	 * @since 4.9.80.p
897
+	 */
898
+	protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = [])
899
+	{
900
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
901
+		if (is_array($datetimes)) {
902
+			foreach ($datetimes as $datetime) {
903
+				if ($datetime instanceof EE_Datetime) {
904
+					$datetime->decreaseSold($qty);
905
+				}
906
+			}
907
+		}
908
+	}
909
+
910
+
911
+	/**
912
+	 * Gets qty of reserved tickets
913
+	 *
914
+	 * @return int
915
+	 * @throws EE_Error
916
+	 * @throws ReflectionException
917
+	 */
918
+	public function reserved()
919
+	{
920
+		return $this->get_raw('TKT_reserved');
921
+	}
922
+
923
+
924
+	/**
925
+	 * Sets reserved
926
+	 *
927
+	 * @param int $reserved
928
+	 * @return void
929
+	 * @throws EE_Error
930
+	 * @throws ReflectionException
931
+	 */
932
+	public function set_reserved($reserved)
933
+	{
934
+		// reserved can not go below zero
935
+		$reserved = max(0, (int) $reserved);
936
+		$this->set('TKT_reserved', $reserved);
937
+	}
938
+
939
+
940
+	/**
941
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
942
+	 *
943
+	 * @param int    $qty
944
+	 * @param string $source
945
+	 * @return bool whether we successfully reserved the ticket or not.
946
+	 * @throws EE_Error
947
+	 * @throws InvalidArgumentException
948
+	 * @throws ReflectionException
949
+	 * @throws InvalidDataTypeException
950
+	 * @throws InvalidInterfaceException
951
+	 * @since 4.9.80.p
952
+	 */
953
+	public function increaseReserved($qty = 1, $source = 'unknown')
954
+	{
955
+		$qty = absint($qty);
956
+		do_action(
957
+			'AHEE__EE_Ticket__increase_reserved__begin',
958
+			$this,
959
+			$qty,
960
+			$source
961
+		);
962
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}");
963
+		$success                         = false;
964
+		$datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty);
965
+		if ($datetimes_adjusted_successfully) {
966
+			$success = $this->incrementFieldConditionallyInDb(
967
+				'TKT_reserved',
968
+				'TKT_sold',
969
+				'TKT_qty',
970
+				$qty
971
+			);
972
+			if (! $success) {
973
+				// The datetimes were successfully bumped, but not the
974
+				// ticket. So we need to manually rollback the datetimes.
975
+				$this->decreaseReservedForDatetimes($qty);
976
+			}
977
+		}
978
+		do_action(
979
+			'AHEE__EE_Ticket__increase_reserved',
980
+			$this,
981
+			$qty,
982
+			$this->reserved(),
983
+			$success
984
+		);
985
+		return $success;
986
+	}
987
+
988
+
989
+	/**
990
+	 * Increases reserved counts on related datetimes
991
+	 *
992
+	 * @param int           $qty
993
+	 * @param EE_Datetime[] $datetimes
994
+	 * @return boolean indicating success
995
+	 * @throws EE_Error
996
+	 * @throws InvalidArgumentException
997
+	 * @throws InvalidDataTypeException
998
+	 * @throws InvalidInterfaceException
999
+	 * @throws ReflectionException
1000
+	 * @since 4.9.80.p
1001
+	 */
1002
+	protected function increaseReservedForDatetimes($qty = 1, array $datetimes = [])
1003
+	{
1004
+		$datetimes         = ! empty($datetimes) ? $datetimes : $this->datetimes();
1005
+		$datetimes_updated = [];
1006
+		$limit_exceeded    = false;
1007
+		if (is_array($datetimes)) {
1008
+			foreach ($datetimes as $datetime) {
1009
+				if ($datetime instanceof EE_Datetime) {
1010
+					if ($datetime->increaseReserved($qty)) {
1011
+						$datetimes_updated[] = $datetime;
1012
+					} else {
1013
+						$limit_exceeded = true;
1014
+						break;
1015
+					}
1016
+				}
1017
+			}
1018
+			// If somewhere along the way we detected a datetime whose
1019
+			// limit was exceeded, do a manual rollback.
1020
+			if ($limit_exceeded) {
1021
+				$this->decreaseReservedForDatetimes($qty, $datetimes_updated);
1022
+				return false;
1023
+			}
1024
+		}
1025
+		return true;
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1031
+	 *
1032
+	 * @param int    $qty
1033
+	 * @param bool   $adjust_datetimes
1034
+	 * @param string $source
1035
+	 * @return boolean
1036
+	 * @throws EE_Error
1037
+	 * @throws InvalidArgumentException
1038
+	 * @throws ReflectionException
1039
+	 * @throws InvalidDataTypeException
1040
+	 * @throws InvalidInterfaceException
1041
+	 * @since 4.9.80.p
1042
+	 */
1043
+	public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1044
+	{
1045
+		$qty = absint($qty);
1046
+		$this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}");
1047
+		if ($adjust_datetimes) {
1048
+			$this->decreaseReservedForDatetimes($qty);
1049
+		}
1050
+		$success = $this->adjustNumericFieldsInDb(
1051
+			[
1052
+				'TKT_reserved' => $qty * -1,
1053
+			]
1054
+		);
1055
+		do_action(
1056
+			'AHEE__EE_Ticket__decrease_reserved',
1057
+			$this,
1058
+			$qty,
1059
+			$this->reserved(),
1060
+			$success
1061
+		);
1062
+		return $success;
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * Decreases the reserved count on the specified datetimes.
1068
+	 *
1069
+	 * @param int           $qty
1070
+	 * @param EE_Datetime[] $datetimes
1071
+	 * @throws EE_Error
1072
+	 * @throws InvalidArgumentException
1073
+	 * @throws ReflectionException
1074
+	 * @throws InvalidDataTypeException
1075
+	 * @throws InvalidInterfaceException
1076
+	 * @since 4.9.80.p
1077
+	 */
1078
+	protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = [])
1079
+	{
1080
+		$datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes();
1081
+		foreach ($datetimes as $datetime) {
1082
+			if ($datetime instanceof EE_Datetime) {
1083
+				$datetime->decreaseReserved($qty);
1084
+			}
1085
+		}
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 * Gets ticket quantity
1091
+	 *
1092
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1093
+	 *                            therefore $context can be one of three values: '', 'reg_limit', or 'saleable'
1094
+	 *                            '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects
1095
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1096
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1097
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1098
+	 * @return int
1099
+	 * @throws EE_Error
1100
+	 * @throws ReflectionException
1101
+	 */
1102
+	public function qty($context = '')
1103
+	{
1104
+		switch ($context) {
1105
+			case 'reg_limit':
1106
+				return $this->real_quantity_on_ticket();
1107
+			case 'saleable':
1108
+				return $this->real_quantity_on_ticket('saleable');
1109
+			default:
1110
+				return $this->get_raw('TKT_qty');
1111
+		}
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * Gets ticket quantity
1117
+	 *
1118
+	 * @param string $context     ticket quantity is somewhat subjective depending on the exact information sought
1119
+	 *                            therefore $context can be one of two values: 'reg_limit', or 'saleable'
1120
+	 *                            REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes
1121
+	 *                            SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and
1122
+	 *                            is therefore the truest measure of tickets that can be purchased at the moment
1123
+	 * @param int    $DTT_ID      the primary key for a particular datetime.
1124
+	 *                            set to 0 for all related datetimes
1125
+	 * @return int
1126
+	 * @throws EE_Error
1127
+	 * @throws ReflectionException
1128
+	 */
1129
+	public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0)
1130
+	{
1131
+		$raw = $this->get_raw('TKT_qty');
1132
+		// return immediately if it's zero
1133
+		if ($raw === 0) {
1134
+			return $raw;
1135
+		}
1136
+		// echo "\n\n<br />Ticket: " . $this->name() . '<br />';
1137
+		// ensure qty doesn't exceed raw value for THIS ticket
1138
+		$qty = min(EE_INF, $raw);
1139
+		// echo "\n . qty: " . $qty . '<br />';
1140
+		// calculate this ticket's total sales and reservations
1141
+		$sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved();
1142
+		// echo "\n . sold: " . $this->sold() . '<br />';
1143
+		// echo "\n . reserved: " . $this->reserved() . '<br />';
1144
+		// echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />';
1145
+		// first we need to calculate the maximum number of tickets available for the datetime
1146
+		// do we want data for one datetime or all of them ?
1147
+		$query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : [];
1148
+		$datetimes    = $this->datetimes($query_params);
1149
+		if (is_array($datetimes) && ! empty($datetimes)) {
1150
+			foreach ($datetimes as $datetime) {
1151
+				if ($datetime instanceof EE_Datetime) {
1152
+					$datetime->refresh_from_db();
1153
+					// echo "\n . . datetime name: " . $datetime->name() . '<br />';
1154
+					// echo "\n . . datetime ID: " . $datetime->ID() . '<br />';
1155
+					// initialize with no restrictions for each datetime
1156
+					// but adjust datetime qty based on datetime reg limit
1157
+					$datetime_qty = min(EE_INF, $datetime->reg_limit());
1158
+					// echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />';
1159
+					// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1160
+					// if we want the actual saleable amount, then we need to consider OTHER ticket sales
1161
+					// and reservations for this datetime, that do NOT include sales and reservations
1162
+					// for this ticket (so we add $this->sold() and $this->reserved() back in)
1163
+					if ($context === 'saleable') {
1164
+						$datetime_qty = max(
1165
+							$datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket,
1166
+							0
1167
+						);
1168
+						// echo "\n . . . datetime sold: " . $datetime->sold() . '<br />';
1169
+						// echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />';
1170
+						// echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />';
1171
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1172
+						$datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0;
1173
+						// echo "\n . . . datetime_qty: " . $datetime_qty . '<br />';
1174
+					}
1175
+					$qty = min($datetime_qty, $qty);
1176
+					// echo "\n . . qty: " . $qty . '<br />';
1177
+				}
1178
+			}
1179
+		}
1180
+		// NOW that we know the  maximum number of tickets available for the datetime
1181
+		// we can finally factor in the details for this specific ticket
1182
+		if ($qty > 0 && $context === 'saleable') {
1183
+			// and subtract the sales for THIS ticket
1184
+			$qty = max($qty - $sold_and_reserved_for_this_ticket, 0);
1185
+			// echo "\n . qty: " . $qty . '<br />';
1186
+		}
1187
+		// echo "\nFINAL QTY: " . $qty . "<br /><br />";
1188
+		return $qty;
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes
1194
+	 *
1195
+	 * @param int $qty
1196
+	 * @return void
1197
+	 * @throws EE_Error
1198
+	 * @throws ReflectionException
1199
+	 */
1200
+	public function set_qty($qty)
1201
+	{
1202
+		$datetimes = $this->datetimes();
1203
+		foreach ($datetimes as $datetime) {
1204
+			if ($datetime instanceof EE_Datetime) {
1205
+				$qty = min($qty, $datetime->reg_limit());
1206
+			}
1207
+		}
1208
+		$this->set('TKT_qty', $qty);
1209
+	}
1210
+
1211
+
1212
+	/**
1213
+	 * Gets uses
1214
+	 *
1215
+	 * @return int
1216
+	 * @throws EE_Error
1217
+	 * @throws ReflectionException
1218
+	 */
1219
+	public function uses()
1220
+	{
1221
+		return $this->get('TKT_uses');
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * Sets uses
1227
+	 *
1228
+	 * @param int $uses
1229
+	 * @return void
1230
+	 * @throws EE_Error
1231
+	 * @throws ReflectionException
1232
+	 */
1233
+	public function set_uses($uses)
1234
+	{
1235
+		$this->set('TKT_uses', $uses);
1236
+	}
1237
+
1238
+
1239
+	/**
1240
+	 * returns whether ticket is required or not.
1241
+	 *
1242
+	 * @return boolean
1243
+	 * @throws EE_Error
1244
+	 * @throws ReflectionException
1245
+	 */
1246
+	public function required()
1247
+	{
1248
+		return $this->get('TKT_required');
1249
+	}
1250
+
1251
+
1252
+	/**
1253
+	 * sets the TKT_required property
1254
+	 *
1255
+	 * @param boolean $required
1256
+	 * @return void
1257
+	 * @throws EE_Error
1258
+	 * @throws ReflectionException
1259
+	 */
1260
+	public function set_required($required)
1261
+	{
1262
+		$this->set('TKT_required', $required);
1263
+	}
1264
+
1265
+
1266
+	/**
1267
+	 * Gets taxable
1268
+	 *
1269
+	 * @return boolean
1270
+	 * @throws EE_Error
1271
+	 * @throws ReflectionException
1272
+	 */
1273
+	public function taxable()
1274
+	{
1275
+		return $this->get('TKT_taxable');
1276
+	}
1277
+
1278
+
1279
+	/**
1280
+	 * Sets taxable
1281
+	 *
1282
+	 * @param boolean $taxable
1283
+	 * @return void
1284
+	 * @throws EE_Error
1285
+	 * @throws ReflectionException
1286
+	 */
1287
+	public function set_taxable($taxable)
1288
+	{
1289
+		$this->set('TKT_taxable', $taxable);
1290
+	}
1291
+
1292
+
1293
+	/**
1294
+	 * Gets is_default
1295
+	 *
1296
+	 * @return boolean
1297
+	 * @throws EE_Error
1298
+	 * @throws ReflectionException
1299
+	 */
1300
+	public function is_default()
1301
+	{
1302
+		return $this->get('TKT_is_default');
1303
+	}
1304
+
1305
+
1306
+	/**
1307
+	 * Sets is_default
1308
+	 *
1309
+	 * @param boolean $is_default
1310
+	 * @return void
1311
+	 * @throws EE_Error
1312
+	 * @throws ReflectionException
1313
+	 */
1314
+	public function set_is_default($is_default)
1315
+	{
1316
+		$this->set('TKT_is_default', $is_default);
1317
+	}
1318
+
1319
+
1320
+	/**
1321
+	 * Gets order
1322
+	 *
1323
+	 * @return int
1324
+	 * @throws EE_Error
1325
+	 * @throws ReflectionException
1326
+	 */
1327
+	public function order()
1328
+	{
1329
+		return $this->get('TKT_order');
1330
+	}
1331
+
1332
+
1333
+	/**
1334
+	 * Sets order
1335
+	 *
1336
+	 * @param int $order
1337
+	 * @return void
1338
+	 * @throws EE_Error
1339
+	 * @throws ReflectionException
1340
+	 */
1341
+	public function set_order($order)
1342
+	{
1343
+		$this->set('TKT_order', $order);
1344
+	}
1345
+
1346
+
1347
+	/**
1348
+	 * Gets row
1349
+	 *
1350
+	 * @return int
1351
+	 * @throws EE_Error
1352
+	 * @throws ReflectionException
1353
+	 */
1354
+	public function row()
1355
+	{
1356
+		return $this->get('TKT_row');
1357
+	}
1358
+
1359
+
1360
+	/**
1361
+	 * Sets row
1362
+	 *
1363
+	 * @param int $row
1364
+	 * @return void
1365
+	 * @throws EE_Error
1366
+	 * @throws ReflectionException
1367
+	 */
1368
+	public function set_row($row)
1369
+	{
1370
+		$this->set('TKT_row', $row);
1371
+	}
1372
+
1373
+
1374
+	/**
1375
+	 * Gets deleted
1376
+	 *
1377
+	 * @return boolean
1378
+	 * @throws EE_Error
1379
+	 * @throws ReflectionException
1380
+	 */
1381
+	public function deleted()
1382
+	{
1383
+		return $this->get('TKT_deleted');
1384
+	}
1385
+
1386
+
1387
+	/**
1388
+	 * Sets deleted
1389
+	 *
1390
+	 * @param boolean $deleted
1391
+	 * @return void
1392
+	 * @throws EE_Error
1393
+	 * @throws ReflectionException
1394
+	 */
1395
+	public function set_deleted($deleted)
1396
+	{
1397
+		$this->set('TKT_deleted', $deleted);
1398
+	}
1399
+
1400
+
1401
+	/**
1402
+	 * Gets parent
1403
+	 *
1404
+	 * @return int
1405
+	 * @throws EE_Error
1406
+	 * @throws ReflectionException
1407
+	 */
1408
+	public function parent_ID()
1409
+	{
1410
+		return $this->get('TKT_parent');
1411
+	}
1412
+
1413
+
1414
+	/**
1415
+	 * Sets parent
1416
+	 *
1417
+	 * @param int $parent
1418
+	 * @return void
1419
+	 * @throws EE_Error
1420
+	 * @throws ReflectionException
1421
+	 */
1422
+	public function set_parent_ID($parent)
1423
+	{
1424
+		$this->set('TKT_parent', $parent);
1425
+	}
1426
+
1427
+
1428
+	/**
1429
+	 * Gets a string which is handy for showing in gateways etc that describes the ticket.
1430
+	 *
1431
+	 * @return string
1432
+	 * @throws EE_Error
1433
+	 * @throws ReflectionException
1434
+	 */
1435
+	public function name_and_info()
1436
+	{
1437
+		$times = [];
1438
+		foreach ($this->datetimes() as $datetime) {
1439
+			$times[] = $datetime->start_date_and_time();
1440
+		}
1441
+		return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price();
1442
+	}
1443
+
1444
+
1445
+	/**
1446
+	 * Gets name
1447
+	 *
1448
+	 * @return string
1449
+	 * @throws EE_Error
1450
+	 * @throws ReflectionException
1451
+	 */
1452
+	public function name()
1453
+	{
1454
+		return $this->get('TKT_name');
1455
+	}
1456
+
1457
+
1458
+	/**
1459
+	 * Gets price
1460
+	 *
1461
+	 * @return float
1462
+	 * @throws EE_Error
1463
+	 * @throws ReflectionException
1464
+	 */
1465
+	public function price()
1466
+	{
1467
+		return $this->get('TKT_price');
1468
+	}
1469
+
1470
+
1471
+	/**
1472
+	 * Gets all the registrations for this ticket
1473
+	 *
1474
+	 * @param array $query_params @see
1475
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1476
+	 * @return EE_Registration[]|EE_Base_Class[]
1477
+	 * @throws EE_Error
1478
+	 * @throws ReflectionException
1479
+	 */
1480
+	public function registrations($query_params = [])
1481
+	{
1482
+		return $this->get_many_related('Registration', $query_params);
1483
+	}
1484
+
1485
+
1486
+	/**
1487
+	 * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket.
1488
+	 *
1489
+	 * @return int
1490
+	 * @throws EE_Error
1491
+	 * @throws ReflectionException
1492
+	 */
1493
+	public function update_tickets_sold()
1494
+	{
1495
+		$count_regs_for_this_ticket = $this->count_registrations(
1496
+			[
1497
+				[
1498
+					'STS_ID'      => EEM_Registration::status_id_approved,
1499
+					'REG_deleted' => 0,
1500
+				],
1501
+			]
1502
+		);
1503
+		$this->set_sold($count_regs_for_this_ticket);
1504
+		$this->save();
1505
+		return $count_regs_for_this_ticket;
1506
+	}
1507
+
1508
+
1509
+	/**
1510
+	 * Counts the registrations for this ticket
1511
+	 *
1512
+	 * @param array $query_params @see
1513
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1514
+	 * @return int
1515
+	 */
1516
+	public function count_registrations($query_params = [])
1517
+	{
1518
+		return $this->count_related('Registration', $query_params);
1519
+	}
1520
+
1521
+
1522
+	/**
1523
+	 * Implementation for EEI_Has_Icon interface method.
1524
+	 *
1525
+	 * @return string
1526
+	 * @see EEI_Visual_Representation for comments
1527
+	 */
1528
+	public function get_icon()
1529
+	{
1530
+		return '<span class="dashicons dashicons-tickets-alt"></span>';
1531
+	}
1532
+
1533
+
1534
+	/**
1535
+	 * Implementation of the EEI_Event_Relation interface method
1536
+	 *
1537
+	 * @return EE_Event
1538
+	 * @throws EE_Error
1539
+	 * @throws UnexpectedEntityException*@throws ReflectionException
1540
+	 * @see EEI_Event_Relation for comments
1541
+	 */
1542
+	public function get_related_event()
1543
+	{
1544
+		// get one datetime to use for getting the event
1545
+		$datetime = $this->first_datetime();
1546
+		if (! $datetime instanceof \EE_Datetime) {
1547
+			throw new UnexpectedEntityException(
1548
+				$datetime,
1549
+				'EE_Datetime',
1550
+				sprintf(
1551
+					esc_html__('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'),
1552
+					$this->name()
1553
+				)
1554
+			);
1555
+		}
1556
+		$event = $datetime->event();
1557
+		if (! $event instanceof \EE_Event) {
1558
+			throw new UnexpectedEntityException(
1559
+				$event,
1560
+				'EE_Event',
1561
+				sprintf(
1562
+					esc_html__('The ticket (%s) is not associated with a valid event.', 'event_espresso'),
1563
+					$this->name()
1564
+				)
1565
+			);
1566
+		}
1567
+		return $event;
1568
+	}
1569
+
1570
+
1571
+	/**
1572
+	 * Implementation of the EEI_Event_Relation interface method
1573
+	 *
1574
+	 * @return string
1575
+	 * @throws UnexpectedEntityException
1576
+	 * @throws EE_Error*@throws ReflectionException
1577
+	 * @see EEI_Event_Relation for comments
1578
+	 */
1579
+	public function get_event_name()
1580
+	{
1581
+		$event = $this->get_related_event();
1582
+		return $event instanceof EE_Event ? $event->name() : '';
1583
+	}
1584
+
1585
+
1586
+	/**
1587
+	 * Implementation of the EEI_Event_Relation interface method
1588
+	 *
1589
+	 * @return int
1590
+	 * @throws UnexpectedEntityException
1591
+	 * @throws EE_Error*@throws ReflectionException
1592
+	 * @see EEI_Event_Relation for comments
1593
+	 */
1594
+	public function get_event_ID()
1595
+	{
1596
+		$event = $this->get_related_event();
1597
+		return $event instanceof EE_Event ? $event->ID() : 0;
1598
+	}
1599
+
1600
+
1601
+	/**
1602
+	 * This simply returns whether a ticket can be permanently deleted or not.
1603
+	 * The criteria for determining this is whether the ticket has any related registrations.
1604
+	 * If there are none then it can be permanently deleted.
1605
+	 *
1606
+	 * @return bool
1607
+	 */
1608
+	public function is_permanently_deleteable()
1609
+	{
1610
+		return $this->count_registrations() === 0;
1611
+	}
1612
+
1613
+
1614
+	/*******************************************************************
1615 1615
      ***********************  DEPRECATED METHODS  **********************
1616 1616
      *******************************************************************/
1617 1617
 
1618 1618
 
1619
-    /**
1620
-     * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1621
-     * associated datetimes.
1622
-     *
1623
-     * @param int $qty
1624
-     * @return void
1625
-     * @throws EE_Error
1626
-     * @throws InvalidArgumentException
1627
-     * @throws InvalidDataTypeException
1628
-     * @throws InvalidInterfaceException
1629
-     * @throws ReflectionException
1630
-     * @deprecated 4.9.80.p
1631
-     */
1632
-    public function increase_sold($qty = 1)
1633
-    {
1634
-        EE_Error::doing_it_wrong(
1635
-            __FUNCTION__,
1636
-            esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1637
-            '4.9.80.p',
1638
-            '5.0.0.p'
1639
-        );
1640
-        $this->increaseSold($qty);
1641
-    }
1642
-
1643
-
1644
-    /**
1645
-     * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1646
-     *
1647
-     * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1648
-     *                 Negative means to decreases old counts (and increase reserved counts).
1649
-     * @throws EE_Error
1650
-     * @throws InvalidArgumentException
1651
-     * @throws InvalidDataTypeException
1652
-     * @throws InvalidInterfaceException
1653
-     * @throws ReflectionException
1654
-     * @deprecated 4.9.80.p
1655
-     */
1656
-    protected function _increase_sold_for_datetimes($qty)
1657
-    {
1658
-        EE_Error::doing_it_wrong(
1659
-            __FUNCTION__,
1660
-            esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1661
-            '4.9.80.p',
1662
-            '5.0.0.p'
1663
-        );
1664
-        $this->increaseSoldForDatetimes($qty);
1665
-    }
1666
-
1667
-
1668
-    /**
1669
-     * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1670
-     * DB and then updates the model objects.
1671
-     * Does not affect the reserved counts.
1672
-     *
1673
-     * @param int $qty
1674
-     * @return void
1675
-     * @throws EE_Error
1676
-     * @throws InvalidArgumentException
1677
-     * @throws InvalidDataTypeException
1678
-     * @throws InvalidInterfaceException
1679
-     * @throws ReflectionException
1680
-     * @deprecated 4.9.80.p
1681
-     */
1682
-    public function decrease_sold($qty = 1)
1683
-    {
1684
-        EE_Error::doing_it_wrong(
1685
-            __FUNCTION__,
1686
-            esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1687
-            '4.9.80.p',
1688
-            '5.0.0.p'
1689
-        );
1690
-        $this->decreaseSold($qty);
1691
-    }
1692
-
1693
-
1694
-    /**
1695
-     * Decreases sold on related datetimes
1696
-     *
1697
-     * @param int $qty
1698
-     * @return void
1699
-     * @throws EE_Error
1700
-     * @throws InvalidArgumentException
1701
-     * @throws InvalidDataTypeException
1702
-     * @throws InvalidInterfaceException
1703
-     * @throws ReflectionException
1704
-     * @deprecated 4.9.80.p
1705
-     */
1706
-    protected function _decrease_sold_for_datetimes($qty = 1)
1707
-    {
1708
-        EE_Error::doing_it_wrong(
1709
-            __FUNCTION__,
1710
-            esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1711
-            '4.9.80.p',
1712
-            '5.0.0.p'
1713
-        );
1714
-        $this->decreaseSoldForDatetimes($qty);
1715
-    }
1716
-
1717
-
1718
-    /**
1719
-     * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1720
-     *
1721
-     * @param int    $qty
1722
-     * @param string $source
1723
-     * @return bool whether we successfully reserved the ticket or not.
1724
-     * @throws EE_Error
1725
-     * @throws InvalidArgumentException
1726
-     * @throws ReflectionException
1727
-     * @throws InvalidDataTypeException
1728
-     * @throws InvalidInterfaceException
1729
-     * @deprecated 4.9.80.p
1730
-     */
1731
-    public function increase_reserved($qty = 1, $source = 'unknown')
1732
-    {
1733
-        EE_Error::doing_it_wrong(
1734
-            __FUNCTION__,
1735
-            esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
1736
-            '4.9.80.p',
1737
-            '5.0.0.p'
1738
-        );
1739
-        return $this->increaseReserved($qty);
1740
-    }
1741
-
1742
-
1743
-    /**
1744
-     * Increases sold on related datetimes
1745
-     *
1746
-     * @param int $qty
1747
-     * @return boolean indicating success
1748
-     * @throws EE_Error
1749
-     * @throws InvalidArgumentException
1750
-     * @throws InvalidDataTypeException
1751
-     * @throws InvalidInterfaceException
1752
-     * @throws ReflectionException
1753
-     * @deprecated 4.9.80.p
1754
-     */
1755
-    protected function _increase_reserved_for_datetimes($qty = 1)
1756
-    {
1757
-        EE_Error::doing_it_wrong(
1758
-            __FUNCTION__,
1759
-            esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
1760
-            '4.9.80.p',
1761
-            '5.0.0.p'
1762
-        );
1763
-        return $this->increaseReservedForDatetimes($qty);
1764
-    }
1765
-
1766
-
1767
-    /**
1768
-     * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1769
-     *
1770
-     * @param int    $qty
1771
-     * @param bool   $adjust_datetimes
1772
-     * @param string $source
1773
-     * @return void
1774
-     * @throws EE_Error
1775
-     * @throws InvalidArgumentException
1776
-     * @throws ReflectionException
1777
-     * @throws InvalidDataTypeException
1778
-     * @throws InvalidInterfaceException
1779
-     * @deprecated 4.9.80.p
1780
-     */
1781
-    public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1782
-    {
1783
-        EE_Error::doing_it_wrong(
1784
-            __FUNCTION__,
1785
-            esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
1786
-            '4.9.80.p',
1787
-            '5.0.0.p'
1788
-        );
1789
-        $this->decreaseReserved($qty);
1790
-    }
1791
-
1792
-
1793
-    /**
1794
-     * Decreases reserved on related datetimes
1795
-     *
1796
-     * @param int $qty
1797
-     * @return void
1798
-     * @throws EE_Error
1799
-     * @throws InvalidArgumentException
1800
-     * @throws ReflectionException
1801
-     * @throws InvalidDataTypeException
1802
-     * @throws InvalidInterfaceException
1803
-     * @deprecated 4.9.80.p
1804
-     */
1805
-    protected function _decrease_reserved_for_datetimes($qty = 1)
1806
-    {
1807
-        EE_Error::doing_it_wrong(
1808
-            __FUNCTION__,
1809
-            esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
1810
-            '4.9.80.p',
1811
-            '5.0.0.p'
1812
-        );
1813
-        $this->decreaseReservedForDatetimes($qty);
1814
-    }
1619
+	/**
1620
+	 * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its
1621
+	 * associated datetimes.
1622
+	 *
1623
+	 * @param int $qty
1624
+	 * @return void
1625
+	 * @throws EE_Error
1626
+	 * @throws InvalidArgumentException
1627
+	 * @throws InvalidDataTypeException
1628
+	 * @throws InvalidInterfaceException
1629
+	 * @throws ReflectionException
1630
+	 * @deprecated 4.9.80.p
1631
+	 */
1632
+	public function increase_sold($qty = 1)
1633
+	{
1634
+		EE_Error::doing_it_wrong(
1635
+			__FUNCTION__,
1636
+			esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'),
1637
+			'4.9.80.p',
1638
+			'5.0.0.p'
1639
+		);
1640
+		$this->increaseSold($qty);
1641
+	}
1642
+
1643
+
1644
+	/**
1645
+	 * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty.
1646
+	 *
1647
+	 * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts),
1648
+	 *                 Negative means to decreases old counts (and increase reserved counts).
1649
+	 * @throws EE_Error
1650
+	 * @throws InvalidArgumentException
1651
+	 * @throws InvalidDataTypeException
1652
+	 * @throws InvalidInterfaceException
1653
+	 * @throws ReflectionException
1654
+	 * @deprecated 4.9.80.p
1655
+	 */
1656
+	protected function _increase_sold_for_datetimes($qty)
1657
+	{
1658
+		EE_Error::doing_it_wrong(
1659
+			__FUNCTION__,
1660
+			esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'),
1661
+			'4.9.80.p',
1662
+			'5.0.0.p'
1663
+		);
1664
+		$this->increaseSoldForDatetimes($qty);
1665
+	}
1666
+
1667
+
1668
+	/**
1669
+	 * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the
1670
+	 * DB and then updates the model objects.
1671
+	 * Does not affect the reserved counts.
1672
+	 *
1673
+	 * @param int $qty
1674
+	 * @return void
1675
+	 * @throws EE_Error
1676
+	 * @throws InvalidArgumentException
1677
+	 * @throws InvalidDataTypeException
1678
+	 * @throws InvalidInterfaceException
1679
+	 * @throws ReflectionException
1680
+	 * @deprecated 4.9.80.p
1681
+	 */
1682
+	public function decrease_sold($qty = 1)
1683
+	{
1684
+		EE_Error::doing_it_wrong(
1685
+			__FUNCTION__,
1686
+			esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'),
1687
+			'4.9.80.p',
1688
+			'5.0.0.p'
1689
+		);
1690
+		$this->decreaseSold($qty);
1691
+	}
1692
+
1693
+
1694
+	/**
1695
+	 * Decreases sold on related datetimes
1696
+	 *
1697
+	 * @param int $qty
1698
+	 * @return void
1699
+	 * @throws EE_Error
1700
+	 * @throws InvalidArgumentException
1701
+	 * @throws InvalidDataTypeException
1702
+	 * @throws InvalidInterfaceException
1703
+	 * @throws ReflectionException
1704
+	 * @deprecated 4.9.80.p
1705
+	 */
1706
+	protected function _decrease_sold_for_datetimes($qty = 1)
1707
+	{
1708
+		EE_Error::doing_it_wrong(
1709
+			__FUNCTION__,
1710
+			esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'),
1711
+			'4.9.80.p',
1712
+			'5.0.0.p'
1713
+		);
1714
+		$this->decreaseSoldForDatetimes($qty);
1715
+	}
1716
+
1717
+
1718
+	/**
1719
+	 * Increments reserved by amount passed by $qty, and persists it immediately to the database.
1720
+	 *
1721
+	 * @param int    $qty
1722
+	 * @param string $source
1723
+	 * @return bool whether we successfully reserved the ticket or not.
1724
+	 * @throws EE_Error
1725
+	 * @throws InvalidArgumentException
1726
+	 * @throws ReflectionException
1727
+	 * @throws InvalidDataTypeException
1728
+	 * @throws InvalidInterfaceException
1729
+	 * @deprecated 4.9.80.p
1730
+	 */
1731
+	public function increase_reserved($qty = 1, $source = 'unknown')
1732
+	{
1733
+		EE_Error::doing_it_wrong(
1734
+			__FUNCTION__,
1735
+			esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'),
1736
+			'4.9.80.p',
1737
+			'5.0.0.p'
1738
+		);
1739
+		return $this->increaseReserved($qty);
1740
+	}
1741
+
1742
+
1743
+	/**
1744
+	 * Increases sold on related datetimes
1745
+	 *
1746
+	 * @param int $qty
1747
+	 * @return boolean indicating success
1748
+	 * @throws EE_Error
1749
+	 * @throws InvalidArgumentException
1750
+	 * @throws InvalidDataTypeException
1751
+	 * @throws InvalidInterfaceException
1752
+	 * @throws ReflectionException
1753
+	 * @deprecated 4.9.80.p
1754
+	 */
1755
+	protected function _increase_reserved_for_datetimes($qty = 1)
1756
+	{
1757
+		EE_Error::doing_it_wrong(
1758
+			__FUNCTION__,
1759
+			esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'),
1760
+			'4.9.80.p',
1761
+			'5.0.0.p'
1762
+		);
1763
+		return $this->increaseReservedForDatetimes($qty);
1764
+	}
1765
+
1766
+
1767
+	/**
1768
+	 * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database.
1769
+	 *
1770
+	 * @param int    $qty
1771
+	 * @param bool   $adjust_datetimes
1772
+	 * @param string $source
1773
+	 * @return void
1774
+	 * @throws EE_Error
1775
+	 * @throws InvalidArgumentException
1776
+	 * @throws ReflectionException
1777
+	 * @throws InvalidDataTypeException
1778
+	 * @throws InvalidInterfaceException
1779
+	 * @deprecated 4.9.80.p
1780
+	 */
1781
+	public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown')
1782
+	{
1783
+		EE_Error::doing_it_wrong(
1784
+			__FUNCTION__,
1785
+			esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'),
1786
+			'4.9.80.p',
1787
+			'5.0.0.p'
1788
+		);
1789
+		$this->decreaseReserved($qty);
1790
+	}
1791
+
1792
+
1793
+	/**
1794
+	 * Decreases reserved on related datetimes
1795
+	 *
1796
+	 * @param int $qty
1797
+	 * @return void
1798
+	 * @throws EE_Error
1799
+	 * @throws InvalidArgumentException
1800
+	 * @throws ReflectionException
1801
+	 * @throws InvalidDataTypeException
1802
+	 * @throws InvalidInterfaceException
1803
+	 * @deprecated 4.9.80.p
1804
+	 */
1805
+	protected function _decrease_reserved_for_datetimes($qty = 1)
1806
+	{
1807
+		EE_Error::doing_it_wrong(
1808
+			__FUNCTION__,
1809
+			esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'),
1810
+			'4.9.80.p',
1811
+			'5.0.0.p'
1812
+		);
1813
+		$this->decreaseReservedForDatetimes($qty);
1814
+	}
1815 1815
 }
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelector.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
     public function cancelTicketSelections()
120 120
     {
121 121
         // check nonce
122
-        if (! $this->processTicketSelectorNonce()) {
122
+        if ( ! $this->processTicketSelectorNonce()) {
123 123
             return false;
124 124
         }
125 125
         $this->session->clear_session(__CLASS__, __FUNCTION__);
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
             );
132 132
         }
133 133
         EEH_URL::safeRedirectAndExit(
134
-            site_url('/' . $this->core_config->event_cpt_slug . '/')
134
+            site_url('/'.$this->core_config->event_cpt_slug.'/')
135 135
         );
136 136
         return true;
137 137
     }
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
             EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
213 213
         }
214 214
         // check total tickets ordered vs max number of attendees that can register
215
-        if (! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
215
+        if ( ! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
216 216
             $this->maxAttendeesViolation($valid);
217 217
         } else {
218 218
             // all data appears to be valid
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
         if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
226 226
             return false;
227 227
         }
228
-        if (! empty($valid['return_url'])) {
228
+        if ( ! empty($valid['return_url'])) {
229 229
             EEH_URL::safeRedirectAndExit($valid['return_url']);
230 230
         }
231 231
         // do we have an event id?
@@ -262,7 +262,7 @@  discard block
 block discarded – undo
262 262
             )
263 263
         );
264 264
         $limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
265
-        EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
265
+        EE_Error::add_error($limit_error_1.'<br/>'.$limit_error_2, __FILE__, __FUNCTION__, __LINE__);
266 266
     }
267 267
 
268 268
 
@@ -278,7 +278,7 @@  discard block
 block discarded – undo
278 278
     {
279 279
         $tickets_added = 0;
280 280
         $tickets_selected = false;
281
-        if (! empty($valid['ticket-selections']) && $valid['total_tickets'] > 0) {
281
+        if ( ! empty($valid['ticket-selections']) && $valid['total_tickets'] > 0) {
282 282
             // load cart using factory because we don't want to do so until actually needed
283 283
             $this->cart = CartFactory::getCart();
284 284
             // if the user is an admin that can edit registrations,
@@ -293,7 +293,7 @@  discard block
 block discarded – undo
293 293
                     // get ticket via the ticket id we put in the form
294 294
                     $ticket = $this->ticket_model->get_one_by_ID($ticket_id);
295 295
                     if ($ticket instanceof EE_Ticket && ($ticket->is_on_sale() || $current_user_is_admin)) {
296
-                        $valid_ticket  = true;
296
+                        $valid_ticket = true;
297 297
                         $tickets_added += $this->addTicketToCart($ticket, $qty);
298 298
                     }
299 299
                     if ($valid_ticket !== true) {
@@ -322,7 +322,7 @@  discard block
 block discarded – undo
322 322
             $this->cart,
323 323
             $this
324 324
         );
325
-        if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
325
+        if ( ! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
326 326
             // no ticket quantities were selected
327 327
             EE_Error::add_error(
328 328
                 esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
@@ -390,7 +390,7 @@  discard block
 block discarded – undo
390 390
         // exit('KILL REDIRECT BEFORE CART UPDATE'); // <<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
391 391
         if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
392 392
             // make sure cart is loaded
393
-            if (! $this->cart instanceof EE_Cart) {
393
+            if ( ! $this->cart instanceof EE_Cart) {
394 394
                 $this->cart = CartFactory::getCart();
395 395
             }
396 396
             do_action(
@@ -412,7 +412,7 @@  discard block
 block discarded – undo
412 412
                 )
413 413
             );
414 414
         }
415
-        if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
415
+        if ( ! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
416 416
             // nothing added to cart
417 417
             EE_Error::add_attention(
418 418
                 esc_html__('No tickets were added for the event', 'event_espresso'),
Please login to merge, or discard this patch.
Indentation   +368 added lines, -368 removed lines patch added patch discarded remove patch
@@ -33,393 +33,393 @@
 block discarded – undo
33 33
  */
34 34
 class ProcessTicketSelector
35 35
 {
36
-    /**
37
-     * @var EE_Cart $cart
38
-     */
39
-    private $cart;
36
+	/**
37
+	 * @var EE_Cart $cart
38
+	 */
39
+	private $cart;
40 40
 
41
-    /**
42
-     * @var EE_Core_Config $core_config
43
-     */
44
-    private $core_config;
41
+	/**
42
+	 * @var EE_Core_Config $core_config
43
+	 */
44
+	private $core_config;
45 45
 
46
-    /**
47
-     * @var RequestInterface $request
48
-     */
49
-    private $request;
46
+	/**
47
+	 * @var RequestInterface $request
48
+	 */
49
+	private $request;
50 50
 
51
-    /**
52
-     * @var EE_Session $session
53
-     */
54
-    private $session;
51
+	/**
52
+	 * @var EE_Session $session
53
+	 */
54
+	private $session;
55 55
 
56
-    /**
57
-     * @var EEM_Ticket $ticket_model
58
-     */
59
-    private $ticket_model;
56
+	/**
57
+	 * @var EEM_Ticket $ticket_model
58
+	 */
59
+	private $ticket_model;
60 60
 
61
-    /**
62
-     * @var TicketDatetimeAvailabilityTracker $tracker
63
-     */
64
-    private $tracker;
61
+	/**
62
+	 * @var TicketDatetimeAvailabilityTracker $tracker
63
+	 */
64
+	private $tracker;
65 65
 
66 66
 
67
-    /**
68
-     * ProcessTicketSelector constructor.
69
-     * NOTE: PLZ use the Loader to instantiate this class if need be
70
-     * so that all dependencies get injected correctly (which will happen automatically)
71
-     * Null values for parameters are only for backwards compatibility but will be removed later on.
72
-     *
73
-     * @param EE_Core_Config                    $core_config
74
-     * @param RequestInterface                           $request
75
-     * @param EE_Session                        $session
76
-     * @param EEM_Ticket                        $ticket_model
77
-     * @param TicketDatetimeAvailabilityTracker $tracker
78
-     * @throws InvalidArgumentException
79
-     * @throws InvalidDataTypeException
80
-     * @throws InvalidInterfaceException
81
-     */
82
-    public function __construct(
83
-        EE_Core_Config $core_config = null,
84
-        RequestInterface $request = null,
85
-        EE_Session $session = null,
86
-        EEM_Ticket $ticket_model = null,
87
-        TicketDatetimeAvailabilityTracker $tracker = null
88
-    ) {
89
-        $loader = LoaderFactory::getLoader();
90
-        $this->core_config = $core_config instanceof EE_Core_Config
91
-            ? $core_config
92
-            : $loader->getShared('EE_Core_Config');
93
-        $this->request = $request instanceof RequestInterface
94
-            ? $request
95
-            : $loader->getShared('EventEspresso\core\services\request\Request');
96
-        $this->session = $session instanceof EE_Session
97
-            ? $session
98
-            : $loader->getShared('EE_Session');
99
-        $this->ticket_model = $ticket_model instanceof EEM_Ticket
100
-            ? $ticket_model
101
-            : $loader->getShared('EEM_Ticket');
102
-        $this->tracker = $tracker instanceof TicketDatetimeAvailabilityTracker
103
-            ? $tracker
104
-            : $loader->getShared('EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker');
105
-    }
67
+	/**
68
+	 * ProcessTicketSelector constructor.
69
+	 * NOTE: PLZ use the Loader to instantiate this class if need be
70
+	 * so that all dependencies get injected correctly (which will happen automatically)
71
+	 * Null values for parameters are only for backwards compatibility but will be removed later on.
72
+	 *
73
+	 * @param EE_Core_Config                    $core_config
74
+	 * @param RequestInterface                           $request
75
+	 * @param EE_Session                        $session
76
+	 * @param EEM_Ticket                        $ticket_model
77
+	 * @param TicketDatetimeAvailabilityTracker $tracker
78
+	 * @throws InvalidArgumentException
79
+	 * @throws InvalidDataTypeException
80
+	 * @throws InvalidInterfaceException
81
+	 */
82
+	public function __construct(
83
+		EE_Core_Config $core_config = null,
84
+		RequestInterface $request = null,
85
+		EE_Session $session = null,
86
+		EEM_Ticket $ticket_model = null,
87
+		TicketDatetimeAvailabilityTracker $tracker = null
88
+	) {
89
+		$loader = LoaderFactory::getLoader();
90
+		$this->core_config = $core_config instanceof EE_Core_Config
91
+			? $core_config
92
+			: $loader->getShared('EE_Core_Config');
93
+		$this->request = $request instanceof RequestInterface
94
+			? $request
95
+			: $loader->getShared('EventEspresso\core\services\request\Request');
96
+		$this->session = $session instanceof EE_Session
97
+			? $session
98
+			: $loader->getShared('EE_Session');
99
+		$this->ticket_model = $ticket_model instanceof EEM_Ticket
100
+			? $ticket_model
101
+			: $loader->getShared('EEM_Ticket');
102
+		$this->tracker = $tracker instanceof TicketDatetimeAvailabilityTracker
103
+			? $tracker
104
+			: $loader->getShared('EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker');
105
+	}
106 106
 
107 107
 
108
-    /**
109
-     * cancelTicketSelections
110
-     *
111
-     * @return bool
112
-     * @throws EE_Error
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidInterfaceException
115
-     * @throws InvalidDataTypeException
116
-     * @throws ReflectionException
117
-     */
118
-    public function cancelTicketSelections()
119
-    {
120
-        // check nonce
121
-        if (! $this->processTicketSelectorNonce()) {
122
-            return false;
123
-        }
124
-        $this->session->clear_session(__CLASS__, __FUNCTION__);
125
-        if ($this->request->requestParamIsSet('event_id')) {
126
-            EEH_URL::safeRedirectAndExit(
127
-                EEH_Event_View::event_link_url(
128
-                    $this->request->getRequestParam('event_id', 0, 'int')
129
-                )
130
-            );
131
-        }
132
-        EEH_URL::safeRedirectAndExit(
133
-            site_url('/' . $this->core_config->event_cpt_slug . '/')
134
-        );
135
-        return true;
136
-    }
108
+	/**
109
+	 * cancelTicketSelections
110
+	 *
111
+	 * @return bool
112
+	 * @throws EE_Error
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws InvalidDataTypeException
116
+	 * @throws ReflectionException
117
+	 */
118
+	public function cancelTicketSelections()
119
+	{
120
+		// check nonce
121
+		if (! $this->processTicketSelectorNonce()) {
122
+			return false;
123
+		}
124
+		$this->session->clear_session(__CLASS__, __FUNCTION__);
125
+		if ($this->request->requestParamIsSet('event_id')) {
126
+			EEH_URL::safeRedirectAndExit(
127
+				EEH_Event_View::event_link_url(
128
+					$this->request->getRequestParam('event_id', 0, 'int')
129
+				)
130
+			);
131
+		}
132
+		EEH_URL::safeRedirectAndExit(
133
+			site_url('/' . $this->core_config->event_cpt_slug . '/')
134
+		);
135
+		return true;
136
+	}
137 137
 
138 138
 
139
-    /**
140
-     * processTicketSelectorNonce
141
-     *
142
-     * @return bool
143
-     */
144
-    private function processTicketSelectorNonce()
145
-    {
146
-        if (
147
-            ! $this->request->isAdmin()
148
-            && (
149
-                ! $this->request->requestParamIsSet('cancel_ticket_selections_nonce')
150
-                || ! wp_verify_nonce(
151
-                    $this->request->getRequestParam('cancel_ticket_selections_nonce'),
152
-                    'cancel_ticket_selections'
153
-                )
154
-            )
155
-        ) {
156
-            EE_Error::add_error(
157
-                sprintf(
158
-                    esc_html__(
159
-                        'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
160
-                        'event_espresso'
161
-                    ),
162
-                    '<br/>'
163
-                ),
164
-                __FILE__,
165
-                __FUNCTION__,
166
-                __LINE__
167
-            );
168
-            return false;
169
-        }
170
-        return true;
171
-    }
139
+	/**
140
+	 * processTicketSelectorNonce
141
+	 *
142
+	 * @return bool
143
+	 */
144
+	private function processTicketSelectorNonce()
145
+	{
146
+		if (
147
+			! $this->request->isAdmin()
148
+			&& (
149
+				! $this->request->requestParamIsSet('cancel_ticket_selections_nonce')
150
+				|| ! wp_verify_nonce(
151
+					$this->request->getRequestParam('cancel_ticket_selections_nonce'),
152
+					'cancel_ticket_selections'
153
+				)
154
+			)
155
+		) {
156
+			EE_Error::add_error(
157
+				sprintf(
158
+					esc_html__(
159
+						'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
160
+						'event_espresso'
161
+					),
162
+					'<br/>'
163
+				),
164
+				__FILE__,
165
+				__FUNCTION__,
166
+				__LINE__
167
+			);
168
+			return false;
169
+		}
170
+		return true;
171
+	}
172 172
 
173 173
 
174
-    /**
175
-     * process_ticket_selections
176
-     *
177
-     * @return bool
178
-     * @throws EE_Error
179
-     * @throws InvalidArgumentException
180
-     * @throws InvalidDataTypeException
181
-     * @throws InvalidInterfaceException
182
-     * @throws ReflectionException
183
-     */
184
-    public function processTicketSelections()
185
-    {
186
-        do_action('EED_Ticket_Selector__process_ticket_selections__before');
187
-        if ($this->request->isBot()) {
188
-            EEH_URL::safeRedirectAndExit(
189
-                apply_filters(
190
-                    'FHEE__EE_Ticket_Selector__process_ticket_selections__bot_redirect_url',
191
-                    site_url()
192
-                )
193
-            );
194
-        }
195
-        // we should really only have 1 registration in the works now
196
-        // (ie, no MER) so unless otherwise requested, clear the session
197
-        if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
198
-            $this->session->clear_session(__CLASS__, __FUNCTION__);
199
-        }
200
-        // validate/sanitize/filter data
201
-        $id = null;
202
-        $valid = [];
203
-        try {
204
-            $post_data_validator = new ProcessTicketSelectorPostData($this->request);
205
-            $id = $post_data_validator->getEventId();
206
-            $valid               = apply_filters(
207
-                'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data',
208
-                $post_data_validator->validatePostData()
209
-            );
210
-        } catch (Exception $exception) {
211
-            EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
212
-        }
213
-        // check total tickets ordered vs max number of attendees that can register
214
-        if (! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
215
-            $this->maxAttendeesViolation($valid);
216
-        } else {
217
-            // all data appears to be valid
218
-            if ($this->processSuccessfulCart($this->addTicketsToCart($valid))) {
219
-                return true;
220
-            }
221
-        }
222
-        // die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
223
-        // at this point, just return if registration is being made from admin
224
-        if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
225
-            return false;
226
-        }
227
-        if (! empty($valid['return_url'])) {
228
-            EEH_URL::safeRedirectAndExit($valid['return_url']);
229
-        }
230
-        // do we have an event id?
231
-        if ($id) {
232
-            EEH_URL::safeRedirectAndExit(get_permalink($id));
233
-        }
234
-        echo EE_Error::get_notices(); // already escaped
235
-        return false;
236
-    }
174
+	/**
175
+	 * process_ticket_selections
176
+	 *
177
+	 * @return bool
178
+	 * @throws EE_Error
179
+	 * @throws InvalidArgumentException
180
+	 * @throws InvalidDataTypeException
181
+	 * @throws InvalidInterfaceException
182
+	 * @throws ReflectionException
183
+	 */
184
+	public function processTicketSelections()
185
+	{
186
+		do_action('EED_Ticket_Selector__process_ticket_selections__before');
187
+		if ($this->request->isBot()) {
188
+			EEH_URL::safeRedirectAndExit(
189
+				apply_filters(
190
+					'FHEE__EE_Ticket_Selector__process_ticket_selections__bot_redirect_url',
191
+					site_url()
192
+				)
193
+			);
194
+		}
195
+		// we should really only have 1 registration in the works now
196
+		// (ie, no MER) so unless otherwise requested, clear the session
197
+		if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
198
+			$this->session->clear_session(__CLASS__, __FUNCTION__);
199
+		}
200
+		// validate/sanitize/filter data
201
+		$id = null;
202
+		$valid = [];
203
+		try {
204
+			$post_data_validator = new ProcessTicketSelectorPostData($this->request);
205
+			$id = $post_data_validator->getEventId();
206
+			$valid               = apply_filters(
207
+				'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data',
208
+				$post_data_validator->validatePostData()
209
+			);
210
+		} catch (Exception $exception) {
211
+			EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
212
+		}
213
+		// check total tickets ordered vs max number of attendees that can register
214
+		if (! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
215
+			$this->maxAttendeesViolation($valid);
216
+		} else {
217
+			// all data appears to be valid
218
+			if ($this->processSuccessfulCart($this->addTicketsToCart($valid))) {
219
+				return true;
220
+			}
221
+		}
222
+		// die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
223
+		// at this point, just return if registration is being made from admin
224
+		if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
225
+			return false;
226
+		}
227
+		if (! empty($valid['return_url'])) {
228
+			EEH_URL::safeRedirectAndExit($valid['return_url']);
229
+		}
230
+		// do we have an event id?
231
+		if ($id) {
232
+			EEH_URL::safeRedirectAndExit(get_permalink($id));
233
+		}
234
+		echo EE_Error::get_notices(); // already escaped
235
+		return false;
236
+	}
237 237
 
238 238
 
239
-    /**
240
-     * @param array $valid
241
-     */
242
-    private function maxAttendeesViolation(array $valid)
243
-    {
244
-        // ordering too many tickets !!!
245
-        $total_tickets_string = esc_html(
246
-            _n(
247
-                'You have attempted to purchase %s ticket.',
248
-                'You have attempted to purchase %s tickets.',
249
-                $valid['total_tickets'],
250
-                'event_espresso'
251
-            )
252
-        );
253
-        $limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
254
-        // dev only message
255
-        $max_attendees_string = esc_html(
256
-            _n(
257
-                'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
258
-                'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
259
-                $valid['max_atndz'],
260
-                'event_espresso'
261
-            )
262
-        );
263
-        $limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
264
-        EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
265
-    }
239
+	/**
240
+	 * @param array $valid
241
+	 */
242
+	private function maxAttendeesViolation(array $valid)
243
+	{
244
+		// ordering too many tickets !!!
245
+		$total_tickets_string = esc_html(
246
+			_n(
247
+				'You have attempted to purchase %s ticket.',
248
+				'You have attempted to purchase %s tickets.',
249
+				$valid['total_tickets'],
250
+				'event_espresso'
251
+			)
252
+		);
253
+		$limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
254
+		// dev only message
255
+		$max_attendees_string = esc_html(
256
+			_n(
257
+				'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
258
+				'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
259
+				$valid['max_atndz'],
260
+				'event_espresso'
261
+			)
262
+		);
263
+		$limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
264
+		EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
265
+	}
266 266
 
267 267
 
268
-    /**
269
-     * @param array $valid
270
-     * @return int
271
-     * @throws EE_Error
272
-     * @throws InvalidArgumentException
273
-     * @throws InvalidDataTypeException
274
-     * @throws InvalidInterfaceException
275
-     */
276
-    private function addTicketsToCart(array $valid)
277
-    {
278
-        $tickets_added = 0;
279
-        $tickets_selected = false;
280
-        if (! empty($valid['ticket-selections']) && $valid['total_tickets'] > 0) {
281
-            // load cart using factory because we don't want to do so until actually needed
282
-            $this->cart = CartFactory::getCart();
283
-            // if the user is an admin that can edit registrations,
284
-            // then we'll also allow them to add any tickets, even if they are expired
285
-            $current_user_is_admin = current_user_can('ee_edit_registrations');
286
-            // cycle thru the number of data rows sent from the event listing
287
-            foreach ($valid['ticket-selections'] as $ticket_id => $qty) {
288
-                if ($qty) {
289
-                    // YES we have a ticket quantity
290
-                    $tickets_selected = true;
291
-                    $valid_ticket     = false;
292
-                    // get ticket via the ticket id we put in the form
293
-                    $ticket = $this->ticket_model->get_one_by_ID($ticket_id);
294
-                    if ($ticket instanceof EE_Ticket && ($ticket->is_on_sale() || $current_user_is_admin)) {
295
-                        $valid_ticket  = true;
296
-                        $tickets_added += $this->addTicketToCart($ticket, $qty);
297
-                    }
298
-                    if ($valid_ticket !== true) {
299
-                        // nothing added to cart retrieved
300
-                        EE_Error::add_error(
301
-                            sprintf(
302
-                                esc_html__(
303
-                                    'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
304
-                                    'event_espresso'
305
-                                ),
306
-                                '<br/>'
307
-                            ),
308
-                            __FILE__,
309
-                            __FUNCTION__,
310
-                            __LINE__
311
-                        );
312
-                    }
313
-                    if (EE_Error::has_error()) {
314
-                        break;
315
-                    }
316
-                }
317
-            }
318
-        }
319
-        do_action(
320
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
321
-            $this->cart,
322
-            $this
323
-        );
324
-        if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
325
-            // no ticket quantities were selected
326
-            EE_Error::add_error(
327
-                esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
328
-                __FILE__,
329
-                __FUNCTION__,
330
-                __LINE__
331
-            );
332
-        }
333
-        return $tickets_added;
334
-    }
268
+	/**
269
+	 * @param array $valid
270
+	 * @return int
271
+	 * @throws EE_Error
272
+	 * @throws InvalidArgumentException
273
+	 * @throws InvalidDataTypeException
274
+	 * @throws InvalidInterfaceException
275
+	 */
276
+	private function addTicketsToCart(array $valid)
277
+	{
278
+		$tickets_added = 0;
279
+		$tickets_selected = false;
280
+		if (! empty($valid['ticket-selections']) && $valid['total_tickets'] > 0) {
281
+			// load cart using factory because we don't want to do so until actually needed
282
+			$this->cart = CartFactory::getCart();
283
+			// if the user is an admin that can edit registrations,
284
+			// then we'll also allow them to add any tickets, even if they are expired
285
+			$current_user_is_admin = current_user_can('ee_edit_registrations');
286
+			// cycle thru the number of data rows sent from the event listing
287
+			foreach ($valid['ticket-selections'] as $ticket_id => $qty) {
288
+				if ($qty) {
289
+					// YES we have a ticket quantity
290
+					$tickets_selected = true;
291
+					$valid_ticket     = false;
292
+					// get ticket via the ticket id we put in the form
293
+					$ticket = $this->ticket_model->get_one_by_ID($ticket_id);
294
+					if ($ticket instanceof EE_Ticket && ($ticket->is_on_sale() || $current_user_is_admin)) {
295
+						$valid_ticket  = true;
296
+						$tickets_added += $this->addTicketToCart($ticket, $qty);
297
+					}
298
+					if ($valid_ticket !== true) {
299
+						// nothing added to cart retrieved
300
+						EE_Error::add_error(
301
+							sprintf(
302
+								esc_html__(
303
+									'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
304
+									'event_espresso'
305
+								),
306
+								'<br/>'
307
+							),
308
+							__FILE__,
309
+							__FUNCTION__,
310
+							__LINE__
311
+						);
312
+					}
313
+					if (EE_Error::has_error()) {
314
+						break;
315
+					}
316
+				}
317
+			}
318
+		}
319
+		do_action(
320
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
321
+			$this->cart,
322
+			$this
323
+		);
324
+		if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
325
+			// no ticket quantities were selected
326
+			EE_Error::add_error(
327
+				esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
328
+				__FILE__,
329
+				__FUNCTION__,
330
+				__LINE__
331
+			);
332
+		}
333
+		return $tickets_added;
334
+	}
335 335
 
336 336
 
337
-    /**
338
-     * adds a ticket to the cart
339
-     *
340
-     * @param EE_Ticket $ticket
341
-     * @param int       $qty
342
-     * @return bool TRUE on success, FALSE on fail
343
-     * @throws InvalidArgumentException
344
-     * @throws InvalidInterfaceException
345
-     * @throws InvalidDataTypeException
346
-     * @throws EE_Error
347
-     */
348
-    private function addTicketToCart(EE_Ticket $ticket, $qty = 1)
349
-    {
350
-        // get the number of spaces left for this datetime ticket
351
-        $available_spaces = $this->tracker->ticketDatetimeAvailability($ticket);
352
-        // compare available spaces against the number of tickets being purchased
353
-        if ($available_spaces >= $qty) {
354
-            // allow addons to prevent a ticket from being added to cart
355
-            if (
356
-                ! apply_filters(
357
-                    'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
358
-                    true,
359
-                    $ticket,
360
-                    $qty,
361
-                    $available_spaces
362
-                )
363
-            ) {
364
-                return false;
365
-            }
366
-            $qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
367
-            // add event to cart
368
-            if ($this->cart->add_ticket_to_cart($ticket, $qty)) {
369
-                $this->tracker->recalculateTicketDatetimeAvailability($ticket, $qty);
370
-                return true;
371
-            }
372
-            return false;
373
-        }
374
-        $this->tracker->processAvailabilityError($ticket, $qty, $this->cart->all_ticket_quantity_count());
375
-        return false;
376
-    }
337
+	/**
338
+	 * adds a ticket to the cart
339
+	 *
340
+	 * @param EE_Ticket $ticket
341
+	 * @param int       $qty
342
+	 * @return bool TRUE on success, FALSE on fail
343
+	 * @throws InvalidArgumentException
344
+	 * @throws InvalidInterfaceException
345
+	 * @throws InvalidDataTypeException
346
+	 * @throws EE_Error
347
+	 */
348
+	private function addTicketToCart(EE_Ticket $ticket, $qty = 1)
349
+	{
350
+		// get the number of spaces left for this datetime ticket
351
+		$available_spaces = $this->tracker->ticketDatetimeAvailability($ticket);
352
+		// compare available spaces against the number of tickets being purchased
353
+		if ($available_spaces >= $qty) {
354
+			// allow addons to prevent a ticket from being added to cart
355
+			if (
356
+				! apply_filters(
357
+					'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
358
+					true,
359
+					$ticket,
360
+					$qty,
361
+					$available_spaces
362
+				)
363
+			) {
364
+				return false;
365
+			}
366
+			$qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
367
+			// add event to cart
368
+			if ($this->cart->add_ticket_to_cart($ticket, $qty)) {
369
+				$this->tracker->recalculateTicketDatetimeAvailability($ticket, $qty);
370
+				return true;
371
+			}
372
+			return false;
373
+		}
374
+		$this->tracker->processAvailabilityError($ticket, $qty, $this->cart->all_ticket_quantity_count());
375
+		return false;
376
+	}
377 377
 
378 378
 
379
-    /**
380
-     * @param $tickets_added
381
-     * @return bool
382
-     * @throws InvalidInterfaceException
383
-     * @throws InvalidDataTypeException
384
-     * @throws EE_Error
385
-     * @throws InvalidArgumentException
386
-     */
387
-    private function processSuccessfulCart($tickets_added)
388
-    {
389
-        // exit('KILL REDIRECT BEFORE CART UPDATE'); // <<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
390
-        if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
391
-            // make sure cart is loaded
392
-            if (! $this->cart instanceof EE_Cart) {
393
-                $this->cart = CartFactory::getCart();
394
-            }
395
-            do_action(
396
-                'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
397
-                $this->cart,
398
-                $this
399
-            );
400
-            $this->cart->recalculate_all_cart_totals();
401
-            $this->cart->save_cart(false);
402
-            // exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
403
-            // just return TRUE for registrations being made from admin
404
-            if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
405
-                return true;
406
-            }
407
-            EEH_URL::safeRedirectAndExit(
408
-                apply_filters(
409
-                    'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
410
-                    $this->core_config->reg_page_url()
411
-                )
412
-            );
413
-        }
414
-        if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
415
-            // nothing added to cart
416
-            EE_Error::add_attention(
417
-                esc_html__('No tickets were added for the event', 'event_espresso'),
418
-                __FILE__,
419
-                __FUNCTION__,
420
-                __LINE__
421
-            );
422
-        }
423
-        return false;
424
-    }
379
+	/**
380
+	 * @param $tickets_added
381
+	 * @return bool
382
+	 * @throws InvalidInterfaceException
383
+	 * @throws InvalidDataTypeException
384
+	 * @throws EE_Error
385
+	 * @throws InvalidArgumentException
386
+	 */
387
+	private function processSuccessfulCart($tickets_added)
388
+	{
389
+		// exit('KILL REDIRECT BEFORE CART UPDATE'); // <<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
390
+		if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
391
+			// make sure cart is loaded
392
+			if (! $this->cart instanceof EE_Cart) {
393
+				$this->cart = CartFactory::getCart();
394
+			}
395
+			do_action(
396
+				'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
397
+				$this->cart,
398
+				$this
399
+			);
400
+			$this->cart->recalculate_all_cart_totals();
401
+			$this->cart->save_cart(false);
402
+			// exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
403
+			// just return TRUE for registrations being made from admin
404
+			if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
405
+				return true;
406
+			}
407
+			EEH_URL::safeRedirectAndExit(
408
+				apply_filters(
409
+					'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
410
+					$this->core_config->reg_page_url()
411
+				)
412
+			);
413
+		}
414
+		if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
415
+			// nothing added to cart
416
+			EE_Error::add_attention(
417
+				esc_html__('No tickets were added for the event', 'event_espresso'),
418
+				__FILE__,
419
+				__FUNCTION__,
420
+				__LINE__
421
+			);
422
+		}
423
+		return false;
424
+	}
425 425
 }
Please login to merge, or discard this patch.
modules/ticket_selector/TicketSelectorRowStandard.php 2 patches
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
             '',
176 176
             'tckt-slctr-tbl-td-qty cntr',
177 177
             '',
178
-            'headers="quantity-' . $this->EVT_ID . '"'
178
+            'headers="quantity-'.$this->EVT_ID.'"'
179 179
         );
180 180
         $this->setTicketStatusDisplay($remaining);
181 181
         if (empty($this->ticket_status_display)) {
@@ -242,7 +242,7 @@  discard block
 block discarded – undo
242 242
             '',
243 243
             'tckt-slctr-tbl-td-name',
244 244
             '',
245
-            'headers="details-' . $this->EVT_ID . '"'
245
+            'headers="details-'.$this->EVT_ID.'"'
246 246
         );
247 247
         $html .= EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
248 248
         $html .= $this->ticket_details->getShowHideLinks();
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
                 '',
277 277
                 'tckt-slctr-tbl-td-price jst-rght',
278 278
                 '',
279
-                'headers="price-' . $this->EVT_ID . '"'
279
+                'headers="price-'.$this->EVT_ID.'"'
280 280
             );
281 281
             $html .= EEH_Template::format_currency($this->ticket_price);
282 282
             $html .= $this->ticket->taxable()
Please login to merge, or discard this patch.
Indentation   +360 added lines, -360 removed lines patch added patch discarded remove patch
@@ -19,364 +19,364 @@
 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
-
63
-    /**
64
-     * TicketDetails constructor.
65
-     *
66
-     * @param TicketDetails $ticket_details
67
-     * @param EE_Tax_Config $tax_settings
68
-     * @param int           $total_tickets
69
-     * @param int           $max_attendees
70
-     * @param int           $row
71
-     * @param int           $cols
72
-     * @param boolean       $required_ticket_sold_out
73
-     * @param string        $event_status
74
-     * @param string        $ticket_datetime_classes
75
-     * @throws EE_Error
76
-     * @throws UnexpectedEntityException
77
-     */
78
-    public function __construct(
79
-        TicketDetails $ticket_details,
80
-        EE_Tax_Config $tax_settings,
81
-        $total_tickets,
82
-        $max_attendees,
83
-        $row,
84
-        $cols,
85
-        $required_ticket_sold_out,
86
-        $event_status,
87
-        $ticket_datetime_classes
88
-    ) {
89
-        $this->ticket_details = $ticket_details;
90
-        $this->template_settings = $ticket_details->getTemplateSettings();
91
-        $this->tax_settings = $tax_settings;
92
-        $this->row = $row;
93
-        $this->cols = $cols;
94
-        $this->ticket_datetime_classes = $ticket_datetime_classes;
95
-        parent::__construct(
96
-            $ticket_details->getTicket(),
97
-            $max_attendees,
98
-            $ticket_details->getDateFormat(),
99
-            $event_status,
100
-            $required_ticket_sold_out,
101
-            $total_tickets
102
-        );
103
-    }
104
-
105
-
106
-    /**
107
-     * other ticket rows will need to know if a required ticket is sold out,
108
-     * so that they are not offered for sale
109
-     *
110
-     * @return boolean
111
-     */
112
-    public function getRequiredTicketSoldOut()
113
-    {
114
-        return $this->required_ticket_sold_out;
115
-    }
116
-
117
-
118
-    /**
119
-     * @return int
120
-     */
121
-    public function getCols()
122
-    {
123
-        return $this->cols;
124
-    }
125
-
126
-
127
-    /**
128
-     * getHtml
129
-     *
130
-     * @return string
131
-     * @throws EE_Error
132
-     * @throws ReflectionException
133
-     */
134
-    public function getHtml()
135
-    {
136
-        $this->min = 0;
137
-        $this->max = $this->ticket->max();
138
-        $remaining = $this->ticket->remaining();
139
-        $this->setTicketMinAndMax($remaining);
140
-        // set flag if ticket is required (flag is set to start date so that future tickets are not blocked)
141
-        $this->required_ticket_sold_out = $this->ticket->required() && ! $remaining
142
-            ? $this->ticket->start_date()
143
-            : $this->required_ticket_sold_out;
144
-        $this->setTicketPriceDetails();
145
-        $this->setTicketStatusClasses($remaining);
146
-        $filtered_row_html = $this->getFilteredRowHtml();
147
-        if ($filtered_row_html !== false) {
148
-            return $filtered_row_html;
149
-        }
150
-        $ticket_selector_row_html = EEH_HTML::tr(
151
-            '',
152
-            '',
153
-            "tckt-slctr-tbl-tr {$this->status_class}{$this->ticket_datetime_classes} "
154
-            . espresso_get_object_css_class($this->ticket)
155
-        );
156
-        $filtered_row_content = $this->getFilteredRowContents();
157
-        if ($filtered_row_content !== false) {
158
-            if ($this->max_attendees === 1) {
159
-                return $ticket_selector_row_html
160
-                       . $filtered_row_content
161
-                       . $this->ticketQtyAndIdHiddenInputs()
162
-                       . EEH_HTML::trx();
163
-            }
164
-            return $ticket_selector_row_html
165
-                   . $filtered_row_content
166
-                   . EEH_HTML::trx();
167
-        }
168
-        $this->hidden_input_qty = $this->max_attendees > 1;
169
-
170
-        $ticket_selector_row_html .= $this->ticketNameTableCell();
171
-        $ticket_selector_row_html .= $this->ticketPriceTableCell();
172
-        $ticket_selector_row_html .= EEH_HTML::td(
173
-            '',
174
-            '',
175
-            'tckt-slctr-tbl-td-qty cntr',
176
-            '',
177
-            'headers="quantity-' . $this->EVT_ID . '"'
178
-        );
179
-        $this->setTicketStatusDisplay($remaining);
180
-        if (empty($this->ticket_status_display)) {
181
-            if ($this->max_attendees === 1) {
182
-                // only ONE attendee is allowed to register at a time
183
-                $ticket_selector_row_html .= $this->onlyOneAttendeeCanRegister();
184
-            } elseif ($this->max > 0) {
185
-                $ticket_selector_row_html .= $this->ticketQuantitySelector();
186
-            }
187
-        }
188
-        $ticket_selector_row_html .= $this->ticket_status_display;
189
-        $ticket_selector_row_html .= $this->ticketQtyAndIdHiddenInputs();
190
-        $ticket_selector_row_html .= $this->ticket_details->display(
191
-            $this->ticket_price,
192
-            $remaining,
193
-            $this->cols
194
-        );
195
-        $ticket_selector_row_html .= EEH_HTML::tdx();
196
-        $ticket_selector_row_html .= EEH_HTML::trx();
197
-
198
-
199
-        $this->row++;
200
-        return $ticket_selector_row_html;
201
-    }
202
-
203
-
204
-    /**
205
-     * getTicketPriceDetails
206
-     *
207
-     * @return void
208
-     * @throws EE_Error
209
-     */
210
-    protected function setTicketPriceDetails()
211
-    {
212
-        $this->ticket_price = $this->tax_settings->prices_displayed_including_taxes
213
-            ? $this->ticket->get_ticket_total_with_taxes()
214
-            : $this->ticket->get_ticket_subtotal();
215
-        $this->ticket_bundle = false;
216
-        $ticket_min = $this->ticket->min();
217
-        // for ticket bundles, set min and max qty the same
218
-        if ($ticket_min !== 0 && $ticket_min === $this->ticket->max()) {
219
-            $this->ticket_price *= $ticket_min;
220
-            $this->ticket_bundle = true;
221
-        }
222
-        $this->ticket_price = apply_filters(
223
-            'FHEE__ticket_selector_chart_template__ticket_price',
224
-            $this->ticket_price,
225
-            $this->ticket
226
-        );
227
-    }
228
-
229
-
230
-    /**
231
-     * ticketNameTableCell
232
-     *
233
-     * @return string
234
-     * @throws EE_Error
235
-     * @throws ReflectionException
236
-     */
237
-    protected function ticketNameTableCell()
238
-    {
239
-        $html = EEH_HTML::td(
240
-            '',
241
-            '',
242
-            'tckt-slctr-tbl-td-name',
243
-            '',
244
-            'headers="details-' . $this->EVT_ID . '"'
245
-        );
246
-        $html .= EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
247
-        $html .= $this->ticket_details->getShowHideLinks();
248
-        if ($this->ticket->required()) {
249
-            $html .= EEH_HTML::p(
250
-                apply_filters(
251
-                    'FHEE__ticket_selector_chart_template__ticket_required_message',
252
-                    esc_html__('This ticket is required and must be purchased.', 'event_espresso')
253
-                ),
254
-                '',
255
-                'ticket-required-pg'
256
-            );
257
-        }
258
-        $html .= EEH_HTML::tdx();
259
-        return $html;
260
-    }
261
-
262
-
263
-    /**
264
-     * ticketPriceTableCell
265
-     *
266
-     * @return string
267
-     * @throws EE_Error
268
-     */
269
-    protected function ticketPriceTableCell()
270
-    {
271
-        $html = '';
272
-        if (apply_filters('FHEE__ticket_selector_chart_template__display_ticket_price_details', true)) {
273
-            $html .= EEH_HTML::td(
274
-                '',
275
-                '',
276
-                'tckt-slctr-tbl-td-price jst-rght',
277
-                '',
278
-                'headers="price-' . $this->EVT_ID . '"'
279
-            );
280
-            $html .= EEH_Template::format_currency($this->ticket_price);
281
-            $html .= $this->ticket->taxable()
282
-                ? EEH_HTML::span('*', '', 'taxable-tickets-asterisk grey-text')
283
-                : '';
284
-            $html .= '&nbsp;';
285
-            // phpcs:disable WordPress.WP.I18n.NoEmptyStrings
286
-            $html .= EEH_HTML::span(
287
-                $this->ticket_bundle
288
-                    ? apply_filters(
289
-                        'FHEE__ticket_selector_chart_template__per_ticket_bundle_text',
290
-                        esc_html__(' / bundle', 'event_espresso')
291
-                    )
292
-                    : apply_filters(
293
-                        'FHEE__ticket_selector_chart_template__per_ticket_text',
294
-                        esc_html__('', 'event_espresso')
295
-                    ),
296
-                '',
297
-                'smaller-text no-bold'
298
-            );
299
-            $html .= '&nbsp;';
300
-            $html .= EEH_HTML::tdx();
301
-            $this->cols++;
302
-        }
303
-        return $html;
304
-    }
305
-
306
-
307
-    /**
308
-     * onlyOneAttendeeCanRegister
309
-     *
310
-     * @return string
311
-     * @throws EE_Error
312
-     */
313
-    protected function onlyOneAttendeeCanRegister()
314
-    {
315
-        $this->hidden_input_qty = false;
316
-        // display submit button since we have tickets available
317
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
318
-
319
-        $TKT   = $this->ticket->ID();
320
-        $label = esc_html__('Select this ticket', 'event_espresso');
321
-        $name  = "tkt-slctr-qty-{$this->EVT_ID}";
322
-        $class = "ticket-selector-tbl-qty-slct";
323
-        $id    = "{$class}-{$this->EVT_ID}-{$this->row}";
324
-        $checked = $this->total_tickets === 1 ? ' checked' : '';
325
-
326
-        $html = "<label class='ee-a11y-screen-reader-text' for='{$id}' >{$label}</label>";
327
-        $html .= "<input type='radio'{$checked} name='{$name}' id='{$id}' class='{$class}' value='{$TKT}-1' title='' />";
328
-        return $html;
329
-    }
330
-
331
-
332
-    /**
333
-     * ticketQuantitySelector
334
-     *
335
-     * @return string
336
-     * @throws EE_Error
337
-     */
338
-    protected function ticketQuantitySelector()
339
-    {
340
-        $this->hidden_input_qty = false;
341
-        // display submit button since we have tickets available
342
-        add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
343
-
344
-        $TKT = $this->ticket->ID();
345
-        $label = esc_html__('Quantity', 'event_espresso');
346
-        $class = 'ticket-selector-tbl-qty-slct';
347
-        $id = "{$class}-{$this->EVT_ID}-{$this->row}";
348
-
349
-        $html = "<label class='ee-a11y-screen-reader-text' for='{$id}' >{$label}</label>";
350
-        $html .= "<select name='tkt-slctr-qty-{$this->EVT_ID}[{$TKT}]' id='{$id}' class='{$class}'>";
351
-        // this ensures that non-required tickets with non-zero MIN QTYs don't HAVE to be purchased
352
-        if ($this->min !== 0 && ! $this->ticket->required()) {
353
-            $html .= "<option value='0'>&nbsp;0&nbsp;</option>";
354
-        }
355
-        // offer ticket quantities from the min to the max
356
-        for ($i = $this->min; $i <= $this->max; $i++) {
357
-            $html .= "<option value='{$i}'>&nbsp;{$i}&nbsp;</option>";
358
-        }
359
-        $html .= "</select>";
360
-        return $html;
361
-    }
362
-
363
-
364
-    /**
365
-     * getHiddenInputs
366
-     *
367
-     * @return string
368
-     * @throws EE_Error
369
-     */
370
-    protected function ticketQtyAndIdHiddenInputs()
371
-    {
372
-        $html = '';
373
-        $EVT = $this->EVT_ID;
374
-        $TKT = $this->ticket->ID();
375
-        // depending on group reg we need to change the format for qty
376
-        if ($this->hidden_input_qty) {
377
-            $html .= "<input type='hidden' name='tkt-slctr-qty-{$EVT}[]' value='0' />";
378
-        }
379
-        $html .= "<input type='hidden' name='tkt-slctr-ticket-id-{$EVT}[]' value='{$TKT}' />";
380
-        return $html;
381
-    }
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
+
63
+	/**
64
+	 * TicketDetails constructor.
65
+	 *
66
+	 * @param TicketDetails $ticket_details
67
+	 * @param EE_Tax_Config $tax_settings
68
+	 * @param int           $total_tickets
69
+	 * @param int           $max_attendees
70
+	 * @param int           $row
71
+	 * @param int           $cols
72
+	 * @param boolean       $required_ticket_sold_out
73
+	 * @param string        $event_status
74
+	 * @param string        $ticket_datetime_classes
75
+	 * @throws EE_Error
76
+	 * @throws UnexpectedEntityException
77
+	 */
78
+	public function __construct(
79
+		TicketDetails $ticket_details,
80
+		EE_Tax_Config $tax_settings,
81
+		$total_tickets,
82
+		$max_attendees,
83
+		$row,
84
+		$cols,
85
+		$required_ticket_sold_out,
86
+		$event_status,
87
+		$ticket_datetime_classes
88
+	) {
89
+		$this->ticket_details = $ticket_details;
90
+		$this->template_settings = $ticket_details->getTemplateSettings();
91
+		$this->tax_settings = $tax_settings;
92
+		$this->row = $row;
93
+		$this->cols = $cols;
94
+		$this->ticket_datetime_classes = $ticket_datetime_classes;
95
+		parent::__construct(
96
+			$ticket_details->getTicket(),
97
+			$max_attendees,
98
+			$ticket_details->getDateFormat(),
99
+			$event_status,
100
+			$required_ticket_sold_out,
101
+			$total_tickets
102
+		);
103
+	}
104
+
105
+
106
+	/**
107
+	 * other ticket rows will need to know if a required ticket is sold out,
108
+	 * so that they are not offered for sale
109
+	 *
110
+	 * @return boolean
111
+	 */
112
+	public function getRequiredTicketSoldOut()
113
+	{
114
+		return $this->required_ticket_sold_out;
115
+	}
116
+
117
+
118
+	/**
119
+	 * @return int
120
+	 */
121
+	public function getCols()
122
+	{
123
+		return $this->cols;
124
+	}
125
+
126
+
127
+	/**
128
+	 * getHtml
129
+	 *
130
+	 * @return string
131
+	 * @throws EE_Error
132
+	 * @throws ReflectionException
133
+	 */
134
+	public function getHtml()
135
+	{
136
+		$this->min = 0;
137
+		$this->max = $this->ticket->max();
138
+		$remaining = $this->ticket->remaining();
139
+		$this->setTicketMinAndMax($remaining);
140
+		// set flag if ticket is required (flag is set to start date so that future tickets are not blocked)
141
+		$this->required_ticket_sold_out = $this->ticket->required() && ! $remaining
142
+			? $this->ticket->start_date()
143
+			: $this->required_ticket_sold_out;
144
+		$this->setTicketPriceDetails();
145
+		$this->setTicketStatusClasses($remaining);
146
+		$filtered_row_html = $this->getFilteredRowHtml();
147
+		if ($filtered_row_html !== false) {
148
+			return $filtered_row_html;
149
+		}
150
+		$ticket_selector_row_html = EEH_HTML::tr(
151
+			'',
152
+			'',
153
+			"tckt-slctr-tbl-tr {$this->status_class}{$this->ticket_datetime_classes} "
154
+			. espresso_get_object_css_class($this->ticket)
155
+		);
156
+		$filtered_row_content = $this->getFilteredRowContents();
157
+		if ($filtered_row_content !== false) {
158
+			if ($this->max_attendees === 1) {
159
+				return $ticket_selector_row_html
160
+					   . $filtered_row_content
161
+					   . $this->ticketQtyAndIdHiddenInputs()
162
+					   . EEH_HTML::trx();
163
+			}
164
+			return $ticket_selector_row_html
165
+				   . $filtered_row_content
166
+				   . EEH_HTML::trx();
167
+		}
168
+		$this->hidden_input_qty = $this->max_attendees > 1;
169
+
170
+		$ticket_selector_row_html .= $this->ticketNameTableCell();
171
+		$ticket_selector_row_html .= $this->ticketPriceTableCell();
172
+		$ticket_selector_row_html .= EEH_HTML::td(
173
+			'',
174
+			'',
175
+			'tckt-slctr-tbl-td-qty cntr',
176
+			'',
177
+			'headers="quantity-' . $this->EVT_ID . '"'
178
+		);
179
+		$this->setTicketStatusDisplay($remaining);
180
+		if (empty($this->ticket_status_display)) {
181
+			if ($this->max_attendees === 1) {
182
+				// only ONE attendee is allowed to register at a time
183
+				$ticket_selector_row_html .= $this->onlyOneAttendeeCanRegister();
184
+			} elseif ($this->max > 0) {
185
+				$ticket_selector_row_html .= $this->ticketQuantitySelector();
186
+			}
187
+		}
188
+		$ticket_selector_row_html .= $this->ticket_status_display;
189
+		$ticket_selector_row_html .= $this->ticketQtyAndIdHiddenInputs();
190
+		$ticket_selector_row_html .= $this->ticket_details->display(
191
+			$this->ticket_price,
192
+			$remaining,
193
+			$this->cols
194
+		);
195
+		$ticket_selector_row_html .= EEH_HTML::tdx();
196
+		$ticket_selector_row_html .= EEH_HTML::trx();
197
+
198
+
199
+		$this->row++;
200
+		return $ticket_selector_row_html;
201
+	}
202
+
203
+
204
+	/**
205
+	 * getTicketPriceDetails
206
+	 *
207
+	 * @return void
208
+	 * @throws EE_Error
209
+	 */
210
+	protected function setTicketPriceDetails()
211
+	{
212
+		$this->ticket_price = $this->tax_settings->prices_displayed_including_taxes
213
+			? $this->ticket->get_ticket_total_with_taxes()
214
+			: $this->ticket->get_ticket_subtotal();
215
+		$this->ticket_bundle = false;
216
+		$ticket_min = $this->ticket->min();
217
+		// for ticket bundles, set min and max qty the same
218
+		if ($ticket_min !== 0 && $ticket_min === $this->ticket->max()) {
219
+			$this->ticket_price *= $ticket_min;
220
+			$this->ticket_bundle = true;
221
+		}
222
+		$this->ticket_price = apply_filters(
223
+			'FHEE__ticket_selector_chart_template__ticket_price',
224
+			$this->ticket_price,
225
+			$this->ticket
226
+		);
227
+	}
228
+
229
+
230
+	/**
231
+	 * ticketNameTableCell
232
+	 *
233
+	 * @return string
234
+	 * @throws EE_Error
235
+	 * @throws ReflectionException
236
+	 */
237
+	protected function ticketNameTableCell()
238
+	{
239
+		$html = EEH_HTML::td(
240
+			'',
241
+			'',
242
+			'tckt-slctr-tbl-td-name',
243
+			'',
244
+			'headers="details-' . $this->EVT_ID . '"'
245
+		);
246
+		$html .= EEH_HTML::strong($this->ticket->get_pretty('TKT_name'));
247
+		$html .= $this->ticket_details->getShowHideLinks();
248
+		if ($this->ticket->required()) {
249
+			$html .= EEH_HTML::p(
250
+				apply_filters(
251
+					'FHEE__ticket_selector_chart_template__ticket_required_message',
252
+					esc_html__('This ticket is required and must be purchased.', 'event_espresso')
253
+				),
254
+				'',
255
+				'ticket-required-pg'
256
+			);
257
+		}
258
+		$html .= EEH_HTML::tdx();
259
+		return $html;
260
+	}
261
+
262
+
263
+	/**
264
+	 * ticketPriceTableCell
265
+	 *
266
+	 * @return string
267
+	 * @throws EE_Error
268
+	 */
269
+	protected function ticketPriceTableCell()
270
+	{
271
+		$html = '';
272
+		if (apply_filters('FHEE__ticket_selector_chart_template__display_ticket_price_details', true)) {
273
+			$html .= EEH_HTML::td(
274
+				'',
275
+				'',
276
+				'tckt-slctr-tbl-td-price jst-rght',
277
+				'',
278
+				'headers="price-' . $this->EVT_ID . '"'
279
+			);
280
+			$html .= EEH_Template::format_currency($this->ticket_price);
281
+			$html .= $this->ticket->taxable()
282
+				? EEH_HTML::span('*', '', 'taxable-tickets-asterisk grey-text')
283
+				: '';
284
+			$html .= '&nbsp;';
285
+			// phpcs:disable WordPress.WP.I18n.NoEmptyStrings
286
+			$html .= EEH_HTML::span(
287
+				$this->ticket_bundle
288
+					? apply_filters(
289
+						'FHEE__ticket_selector_chart_template__per_ticket_bundle_text',
290
+						esc_html__(' / bundle', 'event_espresso')
291
+					)
292
+					: apply_filters(
293
+						'FHEE__ticket_selector_chart_template__per_ticket_text',
294
+						esc_html__('', 'event_espresso')
295
+					),
296
+				'',
297
+				'smaller-text no-bold'
298
+			);
299
+			$html .= '&nbsp;';
300
+			$html .= EEH_HTML::tdx();
301
+			$this->cols++;
302
+		}
303
+		return $html;
304
+	}
305
+
306
+
307
+	/**
308
+	 * onlyOneAttendeeCanRegister
309
+	 *
310
+	 * @return string
311
+	 * @throws EE_Error
312
+	 */
313
+	protected function onlyOneAttendeeCanRegister()
314
+	{
315
+		$this->hidden_input_qty = false;
316
+		// display submit button since we have tickets available
317
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
318
+
319
+		$TKT   = $this->ticket->ID();
320
+		$label = esc_html__('Select this ticket', 'event_espresso');
321
+		$name  = "tkt-slctr-qty-{$this->EVT_ID}";
322
+		$class = "ticket-selector-tbl-qty-slct";
323
+		$id    = "{$class}-{$this->EVT_ID}-{$this->row}";
324
+		$checked = $this->total_tickets === 1 ? ' checked' : '';
325
+
326
+		$html = "<label class='ee-a11y-screen-reader-text' for='{$id}' >{$label}</label>";
327
+		$html .= "<input type='radio'{$checked} name='{$name}' id='{$id}' class='{$class}' value='{$TKT}-1' title='' />";
328
+		return $html;
329
+	}
330
+
331
+
332
+	/**
333
+	 * ticketQuantitySelector
334
+	 *
335
+	 * @return string
336
+	 * @throws EE_Error
337
+	 */
338
+	protected function ticketQuantitySelector()
339
+	{
340
+		$this->hidden_input_qty = false;
341
+		// display submit button since we have tickets available
342
+		add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true');
343
+
344
+		$TKT = $this->ticket->ID();
345
+		$label = esc_html__('Quantity', 'event_espresso');
346
+		$class = 'ticket-selector-tbl-qty-slct';
347
+		$id = "{$class}-{$this->EVT_ID}-{$this->row}";
348
+
349
+		$html = "<label class='ee-a11y-screen-reader-text' for='{$id}' >{$label}</label>";
350
+		$html .= "<select name='tkt-slctr-qty-{$this->EVT_ID}[{$TKT}]' id='{$id}' class='{$class}'>";
351
+		// this ensures that non-required tickets with non-zero MIN QTYs don't HAVE to be purchased
352
+		if ($this->min !== 0 && ! $this->ticket->required()) {
353
+			$html .= "<option value='0'>&nbsp;0&nbsp;</option>";
354
+		}
355
+		// offer ticket quantities from the min to the max
356
+		for ($i = $this->min; $i <= $this->max; $i++) {
357
+			$html .= "<option value='{$i}'>&nbsp;{$i}&nbsp;</option>";
358
+		}
359
+		$html .= "</select>";
360
+		return $html;
361
+	}
362
+
363
+
364
+	/**
365
+	 * getHiddenInputs
366
+	 *
367
+	 * @return string
368
+	 * @throws EE_Error
369
+	 */
370
+	protected function ticketQtyAndIdHiddenInputs()
371
+	{
372
+		$html = '';
373
+		$EVT = $this->EVT_ID;
374
+		$TKT = $this->ticket->ID();
375
+		// depending on group reg we need to change the format for qty
376
+		if ($this->hidden_input_qty) {
377
+			$html .= "<input type='hidden' name='tkt-slctr-qty-{$EVT}[]' value='0' />";
378
+		}
379
+		$html .= "<input type='hidden' name='tkt-slctr-ticket-id-{$EVT}[]' value='{$TKT}' />";
380
+		return $html;
381
+	}
382 382
 }
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelectorPostData.php 2 patches
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
         // do we have an event id?
90 90
         if ($this->event_id === null) {
91 91
             $this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, 'int');
92
-            if (! $this->event_id) {
92
+            if ( ! $this->event_id) {
93 93
                 // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
94 94
                 throw new DomainException(
95 95
                     sprintf(
@@ -114,9 +114,9 @@  discard block
 block discarded – undo
114 114
     public function validatePostData()
115 115
     {
116 116
         // grab valid id
117
-        $this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
117
+        $this->valid_data[self::DATA_KEY_EVENT_ID] = $this->getEventId();
118 118
         // let's track the total number of tickets ordered.'
119
-        $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
119
+        $this->valid_data[self:: DATA_KEY_TOTAL_TICKETS] = 0;
120 120
         // cycle through $inputs_to_clean array
121 121
         foreach ($this->inputs_to_clean as $what => $input_to_clean) {
122 122
             $input_key = "{$input_to_clean}{$this->event_id}";
@@ -152,7 +152,7 @@  discard block
 block discarded – undo
152 152
      */
153 153
     protected function processInteger($what, $input_key)
154 154
     {
155
-        $this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, 'int');
155
+        $this->valid_data[$what] = $this->request->getRequestParam($input_key, 0, 'int');
156 156
     }
157 157
 
158 158
 
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
                 )
176 176
             );
177 177
         }
178
-        $max_atndz = $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ];
178
+        $max_atndz = $this->valid_data[self::DATA_KEY_MAX_ATNDZ];
179 179
         // if max attendees is 1 then the incoming row qty array
180 180
         // will only have one element and the value will be the ticket ID
181 181
         // ex: row qty = [ 0 => TKT_ID ]
@@ -193,10 +193,10 @@  discard block
 block discarded – undo
193 193
             // ex: row qty = [ TKT_ID => 1 ]
194 194
             $row_qty = [$ticket_id => 1];
195 195
         }
196
-        foreach ($this->valid_data[ self::DATA_KEY_TICKET_ID ] as $ticket_id) {
197
-            $qty = isset($row_qty[ $ticket_id ]) ? $row_qty[ $ticket_id ] : 0;
198
-            $this->valid_data[ self::DATA_KEY_QUANTITY ][ $ticket_id ]     = $qty;
199
-            $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] += $qty;
196
+        foreach ($this->valid_data[self::DATA_KEY_TICKET_ID] as $ticket_id) {
197
+            $qty = isset($row_qty[$ticket_id]) ? $row_qty[$ticket_id] : 0;
198
+            $this->valid_data[self::DATA_KEY_QUANTITY][$ticket_id] = $qty;
199
+            $this->valid_data[self:: DATA_KEY_TOTAL_TICKETS] += $qty;
200 200
         }
201 201
     }
202 202
 
@@ -214,9 +214,9 @@  discard block
 block discarded – undo
214 214
             $input_value = explode('#', $input_value);
215 215
             $input_value = end($input_value);
216 216
             // use event list url instead, but append anchor
217
-            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
217
+            $input_value = EEH_Event_View::event_archive_url().'#'.$input_value;
218 218
         }
219
-        $this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
219
+        $this->valid_data[self::DATA_KEY_RETURN_URL] = $input_value;
220 220
     }
221 221
 
222 222
 
@@ -242,7 +242,7 @@  discard block
 block discarded – undo
242 242
         // cycle thru values
243 243
         foreach ($ticket_ids as $key => $value) {
244 244
             // allow only integers
245
-            $this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
245
+            $this->valid_data[self::DATA_KEY_TICKET_ID][$key] = absint($value);
246 246
         }
247 247
     }
248 248
 }
Please login to merge, or discard this patch.
Indentation   +229 added lines, -229 removed lines patch added patch discarded remove patch
@@ -15,233 +15,233 @@
 block discarded – undo
15 15
  */
16 16
 class ProcessTicketSelectorPostData
17 17
 {
18
-    const DATA_KEY_EVENT_ID      = 'id';
19
-
20
-    const DATA_KEY_MAX_ATNDZ     = 'max_atndz';
21
-
22
-    const DATA_KEY_QUANTITY      = 'ticket-selections';
23
-
24
-    const DATA_KEY_RETURN_URL    = 'return_url';
25
-
26
-    const DATA_KEY_ROWS          = 'rows';
27
-
28
-    const DATA_KEY_TICKET_ID     = 'ticket_id';
29
-
30
-    const DATA_KEY_TOTAL_TICKETS = 'total_tickets';
31
-
32
-    const INPUT_KEY_EVENT_ID     = 'tkt-slctr-event-id';
33
-
34
-    const INPUT_KEY_MAX_ATNDZ    = 'tkt-slctr-max-atndz-';
35
-
36
-    const INPUT_KEY_ROWS         = 'tkt-slctr-rows-';
37
-
38
-    const INPUT_KEY_QTY          = 'tkt-slctr-qty-';
39
-
40
-    const INPUT_KEY_TICKET_ID    = 'tkt-slctr-ticket-id-';
41
-
42
-    const INPUT_KEY_RETURN_URL   = 'tkt-slctr-return-url-';
43
-
44
-
45
-    /**
46
-     * @var int
47
-     */
48
-    protected $event_id;
49
-
50
-    /**
51
-     * @var array
52
-     */
53
-    protected $inputs_to_clean = [];
54
-
55
-    /**
56
-     * @var array
57
-     */
58
-    protected $valid_data = [];
59
-
60
-    /**
61
-     * @var RequestInterface
62
-     */
63
-    protected $request;
64
-
65
-
66
-    /**
67
-     * @param RequestInterface $request
68
-     */
69
-    public function __construct(RequestInterface $request)
70
-    {
71
-        $this->request         = $request;
72
-        $this->inputs_to_clean = [
73
-            self::DATA_KEY_MAX_ATNDZ     => self::INPUT_KEY_MAX_ATNDZ,
74
-            self::DATA_KEY_RETURN_URL    => self::INPUT_KEY_RETURN_URL,
75
-            self::DATA_KEY_ROWS          => self::INPUT_KEY_ROWS,
76
-            self::DATA_KEY_TOTAL_TICKETS => self::INPUT_KEY_TICKET_ID,
77
-            self::DATA_KEY_QUANTITY      => self::INPUT_KEY_QTY,
78
-        ];
79
-    }
80
-
81
-
82
-    /**
83
-     * @return int
84
-     * @throws DomainException
85
-     */
86
-    public function getEventId()
87
-    {
88
-        // do we have an event id?
89
-        if ($this->event_id === null) {
90
-            $this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, 'int');
91
-            if (! $this->event_id) {
92
-                // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
93
-                throw new DomainException(
94
-                    sprintf(
95
-                        esc_html__(
96
-                            'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
97
-                            'event_espresso'
98
-                        ),
99
-                        '<br/>'
100
-                    )
101
-                );
102
-            }
103
-        }
104
-        // event id is valid
105
-        return $this->event_id;
106
-    }
107
-
108
-
109
-    /**
110
-     * @return array
111
-     * @throws DomainException
112
-     */
113
-    public function validatePostData()
114
-    {
115
-        // grab valid id
116
-        $this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
117
-        // let's track the total number of tickets ordered.'
118
-        $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
119
-        // cycle through $inputs_to_clean array
120
-        foreach ($this->inputs_to_clean as $what => $input_to_clean) {
121
-            $input_key = "{$input_to_clean}{$this->event_id}";
122
-            // check for POST data
123
-            if ($this->request->requestParamIsSet($input_key)) {
124
-                switch ($what) {
125
-                    // integers
126
-                    case self::DATA_KEY_ROWS:
127
-                    case self::DATA_KEY_MAX_ATNDZ:
128
-                        $this->processInteger($what, $input_key);
129
-                        break;
130
-                    // arrays of integers
131
-                    case self::DATA_KEY_QUANTITY:
132
-                        $this->processQuantity($input_key);
133
-                        break;
134
-                    // array of integers
135
-                    case self::DATA_KEY_TOTAL_TICKETS:
136
-                        $this->processTicketIDs($input_key);
137
-                        break;
138
-                    case self::DATA_KEY_RETURN_URL:
139
-                        $this->processReturnURL($input_key);
140
-                        break;
141
-                }
142
-            }
143
-        }
144
-        return $this->valid_data;
145
-    }
146
-
147
-
148
-    /**
149
-     * @param string $what
150
-     * @param string $input_key
151
-     */
152
-    protected function processInteger($what, $input_key)
153
-    {
154
-        $this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, 'int');
155
-    }
156
-
157
-
158
-    /**
159
-     * @param string $input_key
160
-     * @throws DomainException
161
-     */
162
-    protected function processQuantity($input_key)
163
-    {
164
-        /** @var array $row_qty */
165
-        $row_qty = $this->request->getRequestParam($input_key, [], 'int', true);
166
-        if (empty($row_qty) || ! is_array($row_qty)) {
167
-            throw new DomainException(
168
-                sprintf(
169
-                    esc_html__(
170
-                        'An error occurred while trying to retrieve the ticket selections for the event.%sPlease click the back button on your browser and try again.',
171
-                        'event_espresso'
172
-                    ),
173
-                    '<br/>'
174
-                )
175
-            );
176
-        }
177
-        $max_atndz = $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ];
178
-        // if max attendees is 1 then the incoming row qty array
179
-        // will only have one element and the value will be the ticket ID
180
-        // ex: row qty = [ 0 => TKT_ID ]
181
-        if ($max_atndz === 1 && count($row_qty) === 1) {
182
-            // if the TS used radio buttons, then the ticket ID is stored differently in the request data
183
-            $raw_qty = $this->request->getRequestParam($input_key);
184
-            // explode integers by the dash if qty is a string
185
-            $delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
186
-            if ($delimiter !== '') {
187
-                $row_qty = explode($delimiter, $raw_qty);
188
-            }
189
-            // grab that ticket ID regardless of where it is
190
-            $ticket_id = isset($row_qty[0]) ? $row_qty[0] : key($row_qty);
191
-            // use it as the key, and set the value to 1
192
-            // ex: row qty = [ TKT_ID => 1 ]
193
-            $row_qty = [$ticket_id => 1];
194
-        }
195
-        foreach ($this->valid_data[ self::DATA_KEY_TICKET_ID ] as $ticket_id) {
196
-            $qty = isset($row_qty[ $ticket_id ]) ? $row_qty[ $ticket_id ] : 0;
197
-            $this->valid_data[ self::DATA_KEY_QUANTITY ][ $ticket_id ]     = $qty;
198
-            $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] += $qty;
199
-        }
200
-    }
201
-
202
-
203
-    /**
204
-     * @param string $input_key
205
-     */
206
-    protected function processReturnURL($input_key)
207
-    {
208
-        // grab and sanitize return-url
209
-        $input_value = $this->request->getRequestParam($input_key, '', 'url');
210
-        // was the request coming from an iframe ? if so, then:
211
-        if (strpos($input_value, 'event_list=iframe')) {
212
-            // get anchor fragment
213
-            $input_value = explode('#', $input_value);
214
-            $input_value = end($input_value);
215
-            // use event list url instead, but append anchor
216
-            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
217
-        }
218
-        $this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
219
-    }
220
-
221
-
222
-    /**
223
-     * @param string $input_key
224
-     * @throws DomainException
225
-     */
226
-    protected function processTicketIDs($input_key)
227
-    {
228
-        $ticket_ids          = (array) $this->request->getRequestParam($input_key, [], 'int', true);
229
-        $filtered_ticket_ids = array_filter($ticket_ids);
230
-        if (empty($filtered_ticket_ids)) {
231
-            throw new DomainException(
232
-                sprintf(
233
-                    esc_html__(
234
-                        'An error occurred while trying to retrieve the ticket IDs for the event.%sPlease click the back button on your browser and try again.',
235
-                        'event_espresso'
236
-                    ),
237
-                    '<br/>'
238
-                )
239
-            );
240
-        }
241
-        // cycle thru values
242
-        foreach ($ticket_ids as $key => $value) {
243
-            // allow only integers
244
-            $this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
245
-        }
246
-    }
18
+	const DATA_KEY_EVENT_ID      = 'id';
19
+
20
+	const DATA_KEY_MAX_ATNDZ     = 'max_atndz';
21
+
22
+	const DATA_KEY_QUANTITY      = 'ticket-selections';
23
+
24
+	const DATA_KEY_RETURN_URL    = 'return_url';
25
+
26
+	const DATA_KEY_ROWS          = 'rows';
27
+
28
+	const DATA_KEY_TICKET_ID     = 'ticket_id';
29
+
30
+	const DATA_KEY_TOTAL_TICKETS = 'total_tickets';
31
+
32
+	const INPUT_KEY_EVENT_ID     = 'tkt-slctr-event-id';
33
+
34
+	const INPUT_KEY_MAX_ATNDZ    = 'tkt-slctr-max-atndz-';
35
+
36
+	const INPUT_KEY_ROWS         = 'tkt-slctr-rows-';
37
+
38
+	const INPUT_KEY_QTY          = 'tkt-slctr-qty-';
39
+
40
+	const INPUT_KEY_TICKET_ID    = 'tkt-slctr-ticket-id-';
41
+
42
+	const INPUT_KEY_RETURN_URL   = 'tkt-slctr-return-url-';
43
+
44
+
45
+	/**
46
+	 * @var int
47
+	 */
48
+	protected $event_id;
49
+
50
+	/**
51
+	 * @var array
52
+	 */
53
+	protected $inputs_to_clean = [];
54
+
55
+	/**
56
+	 * @var array
57
+	 */
58
+	protected $valid_data = [];
59
+
60
+	/**
61
+	 * @var RequestInterface
62
+	 */
63
+	protected $request;
64
+
65
+
66
+	/**
67
+	 * @param RequestInterface $request
68
+	 */
69
+	public function __construct(RequestInterface $request)
70
+	{
71
+		$this->request         = $request;
72
+		$this->inputs_to_clean = [
73
+			self::DATA_KEY_MAX_ATNDZ     => self::INPUT_KEY_MAX_ATNDZ,
74
+			self::DATA_KEY_RETURN_URL    => self::INPUT_KEY_RETURN_URL,
75
+			self::DATA_KEY_ROWS          => self::INPUT_KEY_ROWS,
76
+			self::DATA_KEY_TOTAL_TICKETS => self::INPUT_KEY_TICKET_ID,
77
+			self::DATA_KEY_QUANTITY      => self::INPUT_KEY_QTY,
78
+		];
79
+	}
80
+
81
+
82
+	/**
83
+	 * @return int
84
+	 * @throws DomainException
85
+	 */
86
+	public function getEventId()
87
+	{
88
+		// do we have an event id?
89
+		if ($this->event_id === null) {
90
+			$this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, 'int');
91
+			if (! $this->event_id) {
92
+				// $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
93
+				throw new DomainException(
94
+					sprintf(
95
+						esc_html__(
96
+							'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
97
+							'event_espresso'
98
+						),
99
+						'<br/>'
100
+					)
101
+				);
102
+			}
103
+		}
104
+		// event id is valid
105
+		return $this->event_id;
106
+	}
107
+
108
+
109
+	/**
110
+	 * @return array
111
+	 * @throws DomainException
112
+	 */
113
+	public function validatePostData()
114
+	{
115
+		// grab valid id
116
+		$this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
117
+		// let's track the total number of tickets ordered.'
118
+		$this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
119
+		// cycle through $inputs_to_clean array
120
+		foreach ($this->inputs_to_clean as $what => $input_to_clean) {
121
+			$input_key = "{$input_to_clean}{$this->event_id}";
122
+			// check for POST data
123
+			if ($this->request->requestParamIsSet($input_key)) {
124
+				switch ($what) {
125
+					// integers
126
+					case self::DATA_KEY_ROWS:
127
+					case self::DATA_KEY_MAX_ATNDZ:
128
+						$this->processInteger($what, $input_key);
129
+						break;
130
+					// arrays of integers
131
+					case self::DATA_KEY_QUANTITY:
132
+						$this->processQuantity($input_key);
133
+						break;
134
+					// array of integers
135
+					case self::DATA_KEY_TOTAL_TICKETS:
136
+						$this->processTicketIDs($input_key);
137
+						break;
138
+					case self::DATA_KEY_RETURN_URL:
139
+						$this->processReturnURL($input_key);
140
+						break;
141
+				}
142
+			}
143
+		}
144
+		return $this->valid_data;
145
+	}
146
+
147
+
148
+	/**
149
+	 * @param string $what
150
+	 * @param string $input_key
151
+	 */
152
+	protected function processInteger($what, $input_key)
153
+	{
154
+		$this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, 'int');
155
+	}
156
+
157
+
158
+	/**
159
+	 * @param string $input_key
160
+	 * @throws DomainException
161
+	 */
162
+	protected function processQuantity($input_key)
163
+	{
164
+		/** @var array $row_qty */
165
+		$row_qty = $this->request->getRequestParam($input_key, [], 'int', true);
166
+		if (empty($row_qty) || ! is_array($row_qty)) {
167
+			throw new DomainException(
168
+				sprintf(
169
+					esc_html__(
170
+						'An error occurred while trying to retrieve the ticket selections for the event.%sPlease click the back button on your browser and try again.',
171
+						'event_espresso'
172
+					),
173
+					'<br/>'
174
+				)
175
+			);
176
+		}
177
+		$max_atndz = $this->valid_data[ self::DATA_KEY_MAX_ATNDZ ];
178
+		// if max attendees is 1 then the incoming row qty array
179
+		// will only have one element and the value will be the ticket ID
180
+		// ex: row qty = [ 0 => TKT_ID ]
181
+		if ($max_atndz === 1 && count($row_qty) === 1) {
182
+			// if the TS used radio buttons, then the ticket ID is stored differently in the request data
183
+			$raw_qty = $this->request->getRequestParam($input_key);
184
+			// explode integers by the dash if qty is a string
185
+			$delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
186
+			if ($delimiter !== '') {
187
+				$row_qty = explode($delimiter, $raw_qty);
188
+			}
189
+			// grab that ticket ID regardless of where it is
190
+			$ticket_id = isset($row_qty[0]) ? $row_qty[0] : key($row_qty);
191
+			// use it as the key, and set the value to 1
192
+			// ex: row qty = [ TKT_ID => 1 ]
193
+			$row_qty = [$ticket_id => 1];
194
+		}
195
+		foreach ($this->valid_data[ self::DATA_KEY_TICKET_ID ] as $ticket_id) {
196
+			$qty = isset($row_qty[ $ticket_id ]) ? $row_qty[ $ticket_id ] : 0;
197
+			$this->valid_data[ self::DATA_KEY_QUANTITY ][ $ticket_id ]     = $qty;
198
+			$this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] += $qty;
199
+		}
200
+	}
201
+
202
+
203
+	/**
204
+	 * @param string $input_key
205
+	 */
206
+	protected function processReturnURL($input_key)
207
+	{
208
+		// grab and sanitize return-url
209
+		$input_value = $this->request->getRequestParam($input_key, '', 'url');
210
+		// was the request coming from an iframe ? if so, then:
211
+		if (strpos($input_value, 'event_list=iframe')) {
212
+			// get anchor fragment
213
+			$input_value = explode('#', $input_value);
214
+			$input_value = end($input_value);
215
+			// use event list url instead, but append anchor
216
+			$input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
217
+		}
218
+		$this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
219
+	}
220
+
221
+
222
+	/**
223
+	 * @param string $input_key
224
+	 * @throws DomainException
225
+	 */
226
+	protected function processTicketIDs($input_key)
227
+	{
228
+		$ticket_ids          = (array) $this->request->getRequestParam($input_key, [], 'int', true);
229
+		$filtered_ticket_ids = array_filter($ticket_ids);
230
+		if (empty($filtered_ticket_ids)) {
231
+			throw new DomainException(
232
+				sprintf(
233
+					esc_html__(
234
+						'An error occurred while trying to retrieve the ticket IDs for the event.%sPlease click the back button on your browser and try again.',
235
+						'event_espresso'
236
+					),
237
+					'<br/>'
238
+				)
239
+			);
240
+		}
241
+		// cycle thru values
242
+		foreach ($ticket_ids as $key => $value) {
243
+			// allow only integers
244
+			$this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
245
+		}
246
+	}
247 247
 }
Please login to merge, or discard this patch.
core/services/request/DataType.php 1 patch
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -12,58 +12,58 @@
 block discarded – undo
12 12
  */
13 13
 class DataType
14 14
 {
15
-    // can't use ARRAY as name until we switch to PHP 7+
16
-    // const ARRAY   = 'array';
15
+	// can't use ARRAY as name until we switch to PHP 7+
16
+	// const ARRAY   = 'array';
17 17
 
18
-    const BOOL    = 'bool';
19
-    const BOOLEAN = 'bool';
18
+	const BOOL    = 'bool';
19
+	const BOOLEAN = 'bool';
20 20
 
21
-    const DOUBLE  = 'float';
22
-    const FLOAT   = 'float';
21
+	const DOUBLE  = 'float';
22
+	const FLOAT   = 'float';
23 23
 
24
-    const FQCN    = 'fqcn';
24
+	const FQCN    = 'fqcn';
25 25
 
26
-    const HTML    = 'html';
26
+	const HTML    = 'html';
27 27
 
28
-    const INT     = 'int';
29
-    const INTEGER = 'int';
28
+	const INT     = 'int';
29
+	const INTEGER = 'int';
30 30
 
31
-    const KEY     = 'key';
31
+	const KEY     = 'key';
32 32
 
33
-    const OBJECT  = 'object';
33
+	const OBJECT  = 'object';
34 34
 
35
-    const NULL    = 'null';
35
+	const NULL    = 'null';
36 36
 
37
-    const TITLE   = 'title';
37
+	const TITLE   = 'title';
38 38
 
39
-    const URL     = 'url';
39
+	const URL     = 'url';
40 40
 
41
-    const STRING  = 'string';
41
+	const STRING  = 'string';
42 42
 
43 43
 
44
-    /**
45
-     * @param mixed  $param
46
-     * @param string $type
47
-     * @return mixed
48
-     */
49
-    public static function setDataType($param, $type)
50
-    {
51
-        switch ($type) {
52
-            case DataType::NULL:
53
-                return null;
54
-            case DataType::OBJECT:
55
-                return $param;
56
-            case DataType::FQCN:
57
-            case DataType::HTML:
58
-            case DataType::KEY:
59
-            case DataType::STRING:
60
-            case DataType::TITLE:
61
-            case DataType::URL:
62
-                settype($param, DataType::STRING);
63
-                break;
64
-            default:
65
-                settype($param, $type);
66
-        }
67
-        return $param;
68
-    }
44
+	/**
45
+	 * @param mixed  $param
46
+	 * @param string $type
47
+	 * @return mixed
48
+	 */
49
+	public static function setDataType($param, $type)
50
+	{
51
+		switch ($type) {
52
+			case DataType::NULL:
53
+				return null;
54
+			case DataType::OBJECT:
55
+				return $param;
56
+			case DataType::FQCN:
57
+			case DataType::HTML:
58
+			case DataType::KEY:
59
+			case DataType::STRING:
60
+			case DataType::TITLE:
61
+			case DataType::URL:
62
+				settype($param, DataType::STRING);
63
+				break;
64
+			default:
65
+				settype($param, $type);
66
+		}
67
+		return $param;
68
+	}
69 69
 }
Please login to merge, or discard this patch.
core/services/request/RequestParams.php 2 patches
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -17,13 +17,13 @@  discard block
 block discarded – undo
17 17
      * Used for matches() and parameterDrillDown()
18 18
      * 'bool' will return true or false if match is found or not
19 19
      */
20
-    const RETURN_BOOL  = 'bool';
20
+    const RETURN_BOOL = 'bool';
21 21
 
22 22
     /**
23 23
      * Used for matches() and parameterDrillDown()
24 24
      * 'key' will return the first key found that matches the supplied pattern
25 25
      */
26
-    const RETURN_KEY   = 'key';
26
+    const RETURN_KEY = 'key';
27 27
 
28 28
     /**
29 29
      * Used for matches() and parameterDrillDown()
@@ -113,7 +113,7 @@  discard block
 block discarded – undo
113 113
     {
114 114
         // don't allow "ee" to be overwritten unless explicitly instructed to do so
115 115
         if ($override_ee || $key !== 'ee' || empty($this->request['ee'])) {
116
-            $this->request[ $key ] = $value;
116
+            $this->request[$key] = $value;
117 117
         }
118 118
     }
119 119
 
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
             preg_quote($pattern, '/')
238 238
         );
239 239
         foreach ($request_params as $key => $request_param) {
240
-            if (preg_match('/^' . $pattern . '$/is', $key)) {
240
+            if (preg_match('/^'.$pattern.'$/is', $key)) {
241 241
                 // return value for request param
242 242
                 if ($return === self::RETURN_VALUE) {
243 243
                     return $request_param;
@@ -299,30 +299,30 @@  discard block
 block discarded – undo
299 299
                 $key      = $real_key ?: $key;
300 300
             }
301 301
             // check if top level key exists
302
-            if (isset($request_params[ $key ])) {
302
+            if (isset($request_params[$key])) {
303 303
                 // build a new key to pass along like: 'second[third]'
304 304
                 // or just 'second' depending on depth of keys
305 305
                 $key_string = array_shift($keys);
306
-                if (! empty($keys)) {
307
-                    $key_string .= '[' . implode('][', $keys) . ']';
306
+                if ( ! empty($keys)) {
307
+                    $key_string .= '['.implode('][', $keys).']';
308 308
                 }
309 309
                 return $this->parameterDrillDown(
310 310
                     $key_string,
311 311
                     $default,
312 312
                     $callback,
313 313
                     $return,
314
-                    $request_params[ $key ]
314
+                    $request_params[$key]
315 315
                 );
316 316
             }
317 317
         }
318 318
         if ($callback === 'is_set') {
319
-            return isset($request_params[ $key ]);
319
+            return isset($request_params[$key]);
320 320
         }
321 321
         if ($callback === 'match') {
322 322
             return $this->match($key, $request_params, $default, $return);
323 323
         }
324
-        return isset($request_params[ $key ])
325
-            ? $request_params[ $key ]
324
+        return isset($request_params[$key])
325
+            ? $request_params[$key]
326 326
             : $default;
327 327
     }
328 328
 
@@ -336,12 +336,12 @@  discard block
 block discarded – undo
336 336
     public function unSetRequestParam($key, $unset_from_global_too = false)
337 337
     {
338 338
         // because unset may not actually remove var
339
-        $this->get[ $key ]     = null;
340
-        $this->post[ $key ]    = null;
341
-        $this->request[ $key ] = null;
342
-        unset($this->get[ $key ], $this->post[ $key ], $this->request[ $key ]);
339
+        $this->get[$key]     = null;
340
+        $this->post[$key]    = null;
341
+        $this->request[$key] = null;
342
+        unset($this->get[$key], $this->post[$key], $this->request[$key]);
343 343
         if ($unset_from_global_too) {
344
-            unset($_GET[ $key ], $_POST[ $key ], $_REQUEST[ $key ]);
344
+            unset($_GET[$key], $_POST[$key], $_REQUEST[$key]);
345 345
         }
346 346
     }
347 347
 
Please login to merge, or discard this patch.
Indentation   +345 added lines, -345 removed lines patch added patch discarded remove patch
@@ -13,349 +13,349 @@
 block discarded – undo
13 13
  */
14 14
 class RequestParams
15 15
 {
16
-    /**
17
-     * Used for matches() and parameterDrillDown()
18
-     * 'bool' will return true or false if match is found or not
19
-     */
20
-    const RETURN_BOOL  = 'bool';
21
-
22
-    /**
23
-     * Used for matches() and parameterDrillDown()
24
-     * 'key' will return the first key found that matches the supplied pattern
25
-     */
26
-    const RETURN_KEY   = 'key';
27
-
28
-    /**
29
-     * Used for matches() and parameterDrillDown()
30
-     * 'value' will return the value for the first request parameter
31
-     */
32
-    const RETURN_VALUE = 'value';
33
-
34
-    /**
35
-     * $_GET parameters
36
-     *
37
-     * @var array
38
-     */
39
-    protected $get;
40
-
41
-    /**
42
-     * $_POST parameters
43
-     *
44
-     * @var array
45
-     */
46
-    protected $post;
47
-
48
-    /**
49
-     * $_REQUEST parameters
50
-     *
51
-     * @var array
52
-     */
53
-    protected $request;
54
-
55
-    /**
56
-     * @var RequestSanitizer
57
-     */
58
-    protected $sanitizer;
59
-
60
-
61
-    /**
62
-     * RequestParams constructor.
63
-     *
64
-     * @param RequestSanitizer $sanitizer
65
-     * @param array            $get
66
-     * @param array            $post
67
-     */
68
-    public function __construct(RequestSanitizer $sanitizer, array $get = [], array $post = [])
69
-    {
70
-        $this->sanitizer = $sanitizer;
71
-        $this->get       = ! empty($get) ? $get : $_GET;
72
-        $this->post      = ! empty($post) ? $post : $_POST;
73
-        $this->request   = array_merge($this->get, $this->post);
74
-    }
75
-
76
-
77
-    /**
78
-     * @return array
79
-     */
80
-    public function getParams()
81
-    {
82
-        return $this->get;
83
-    }
84
-
85
-
86
-    /**
87
-     * @return array
88
-     */
89
-    public function postParams()
90
-    {
91
-        return $this->post;
92
-    }
93
-
94
-
95
-    /**
96
-     * returns contents of $_REQUEST
97
-     *
98
-     * @return array
99
-     */
100
-    public function requestParams()
101
-    {
102
-        return $this->request;
103
-    }
104
-
105
-
106
-    /**
107
-     * @param string     $key
108
-     * @param mixed|null $value
109
-     * @param bool       $override_ee
110
-     * @return    void
111
-     */
112
-    public function setRequestParam($key, $value, $override_ee = false)
113
-    {
114
-        // don't allow "ee" to be overwritten unless explicitly instructed to do so
115
-        if ($override_ee || $key !== 'ee' || empty($this->request['ee'])) {
116
-            $this->request[ $key ] = $value;
117
-        }
118
-    }
119
-
120
-
121
-    /**
122
-     * merges the incoming array of parameters into the existing request parameters
123
-     *
124
-     * @param array $request_params
125
-     * @return void
126
-     * @since   4.10.24.p
127
-     */
128
-    public function mergeRequestParams(array $request_params)
129
-    {
130
-        $this->request = array_merge($this->request, $request_params);
131
-    }
132
-
133
-
134
-    /**
135
-     * returns   the value for a request param if the given key exists
136
-     *
137
-     * @param string     $key
138
-     * @param mixed|null $default
139
-     * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc
140
-     * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
141
-     * @param string     $delimiter for CSV type strings that should be returned as an array
142
-     * @return array|bool|float|int|string
143
-     */
144
-    public function getRequestParam($key, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
145
-    {
146
-        $param = $this->sanitizer->clean(
147
-            $this->parameterDrillDown($key, $default, 'get'),
148
-            $type,
149
-            $is_array,
150
-            $delimiter
151
-        );
152
-        $type = $is_array ? 'array' : $type;
153
-        return DataType::setDataType($param, $type);
154
-    }
155
-
156
-
157
-    /**
158
-     * check if param exists
159
-     *
160
-     * @param string $key
161
-     * @return bool
162
-     */
163
-    public function requestParamIsSet($key)
164
-    {
165
-        return (bool) $this->parameterDrillDown($key);
166
-    }
167
-
168
-
169
-    /**
170
-     * check if a request parameter exists whose key that matches the supplied wildcard pattern
171
-     * and return the value for the first match found
172
-     * wildcards can be either of the following:
173
-     *      ? to represent a single character of any type
174
-     *      * to represent one or more characters of any type
175
-     *
176
-     * @param string     $pattern
177
-     * @param mixed|null $default
178
-     * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc
179
-     * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
180
-     * @param string     $delimiter for CSV type strings that should be returned as an array
181
-     * @return array|bool|float|int|string
182
-     */
183
-    public function getMatch($pattern, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
184
-    {
185
-        $param = $this->sanitizer->clean(
186
-            $this->parameterDrillDown($pattern, $default, 'match'),
187
-            $type,
188
-            $is_array,
189
-            $delimiter
190
-        );
191
-        $type = $is_array ? 'array' : $type;
192
-        return DataType::setDataType($param, $type);
193
-    }
194
-
195
-
196
-    /**
197
-     * check if a request parameter exists whose key matches the supplied wildcard pattern
198
-     * wildcards can be either of the following:
199
-     *      ? to represent a single character of any type
200
-     *      * to represent one or more characters of any type
201
-     * returns true if a match is found or false if not
202
-     *
203
-     * @param string $pattern
204
-     * @return bool
205
-     */
206
-    public function matches($pattern)
207
-    {
208
-        return (bool) $this->parameterDrillDown($pattern, false, 'match', self::RETURN_BOOL);
209
-    }
210
-
211
-
212
-    /**
213
-     * @see https://stackoverflow.com/questions/6163055/php-string-matching-with-wildcard
214
-     * @param string $pattern               A string including wildcards to be converted to a regex pattern
215
-     *                                      and used to search through the current request's parameter keys
216
-     * @param array  $request_params        The array of request parameters to search through
217
-     * @param mixed  $default               [optional] The value to be returned if no match is found.
218
-     *                                      Default is null
219
-     * @param string $return                [optional] Controls what kind of value is returned.
220
-     *                                      Options are the RETURN_* constants:
221
-     *                                      RETURN_BOOL will return true or false if match is found or not
222
-     *                                      RETURN_KEY will return the first key found that matches the supplied pattern
223
-     *                                      RETURN_VALUE will return the value for the first request parameter
224
-     *                                      whose key matches the supplied pattern
225
-     *                                      Default is 'value'
226
-     * @return boolean|string
227
-     */
228
-    private function match($pattern, array $request_params, $default = null, $return = self::RETURN_VALUE)
229
-    {
230
-        $return = in_array($return, [self::RETURN_BOOL, self::RETURN_KEY, self::RETURN_VALUE], true)
231
-            ? $return
232
-            : 'is_set';
233
-        // replace wildcard chars with regex chars
234
-        $pattern = str_replace(
235
-            ['\*', '\?'],
236
-            ['.*', '.'],
237
-            preg_quote($pattern, '/')
238
-        );
239
-        foreach ($request_params as $key => $request_param) {
240
-            if (preg_match('/^' . $pattern . '$/is', $key)) {
241
-                // return value for request param
242
-                if ($return === self::RETURN_VALUE) {
243
-                    return $request_param;
244
-                }
245
-                // or actual key or true just to indicate it was found
246
-                return $return === self::RETURN_KEY ? $key : true;
247
-            }
248
-        }
249
-        // match not found so return default value or false
250
-        return $return === self::RETURN_VALUE ? $default : false;
251
-    }
252
-
253
-
254
-    /**
255
-     * the supplied key can be a simple string to represent a "top-level" request parameter
256
-     * or represent a key for a request parameter that is nested deeper within the request parameter array,
257
-     * by using square brackets to surround keys for deeper array elements.
258
-     * For example :
259
-     * if the supplied $key was: "first[second][third]"
260
-     * then this will attempt to drill down into the request parameter array to find a value.
261
-     * Given the following request parameters:
262
-     *  array(
263
-     *      'first' => array(
264
-     *          'second' => array(
265
-     *              'third' => 'has a value'
266
-     *          )
267
-     *      )
268
-     *  )
269
-     * would return true if default parameters were set
270
-     *
271
-     * @param string $callback
272
-     * @param        $key
273
-     * @param null   $default
274
-     * @param string $return
275
-     * @param mixed  $request_params
276
-     * @return bool|mixed|null
277
-     */
278
-    private function parameterDrillDown(
279
-        $key,
280
-        $default = null,
281
-        $callback = 'is_set',
282
-        $return = self::RETURN_VALUE,
283
-        $request_params = []
284
-    ) {
285
-        $callback       = in_array($callback, ['is_set', 'get', 'match'], true)
286
-            ? $callback
287
-            : 'is_set';
288
-        $request_params = ! empty($request_params)
289
-            ? $request_params
290
-            : $this->request;
291
-        // does incoming key represent an array like 'first[second][third]'  ?
292
-        if (strpos($key, '[') !== false) {
293
-            // turn it into an actual array
294
-            $key  = str_replace(']', '', $key);
295
-            $keys = explode('[', $key);
296
-            $key  = array_shift($keys);
297
-            if ($callback === 'match') {
298
-                $real_key = $this->match($key, $request_params, $default, self::RETURN_KEY);
299
-                $key      = $real_key ?: $key;
300
-            }
301
-            // check if top level key exists
302
-            if (isset($request_params[ $key ])) {
303
-                // build a new key to pass along like: 'second[third]'
304
-                // or just 'second' depending on depth of keys
305
-                $key_string = array_shift($keys);
306
-                if (! empty($keys)) {
307
-                    $key_string .= '[' . implode('][', $keys) . ']';
308
-                }
309
-                return $this->parameterDrillDown(
310
-                    $key_string,
311
-                    $default,
312
-                    $callback,
313
-                    $return,
314
-                    $request_params[ $key ]
315
-                );
316
-            }
317
-        }
318
-        if ($callback === 'is_set') {
319
-            return isset($request_params[ $key ]);
320
-        }
321
-        if ($callback === 'match') {
322
-            return $this->match($key, $request_params, $default, $return);
323
-        }
324
-        return isset($request_params[ $key ])
325
-            ? $request_params[ $key ]
326
-            : $default;
327
-    }
328
-
329
-
330
-    /**
331
-     * remove param
332
-     *
333
-     * @param      $key
334
-     * @param bool $unset_from_global_too
335
-     */
336
-    public function unSetRequestParam($key, $unset_from_global_too = false)
337
-    {
338
-        // because unset may not actually remove var
339
-        $this->get[ $key ]     = null;
340
-        $this->post[ $key ]    = null;
341
-        $this->request[ $key ] = null;
342
-        unset($this->get[ $key ], $this->post[ $key ], $this->request[ $key ]);
343
-        if ($unset_from_global_too) {
344
-            unset($_GET[ $key ], $_POST[ $key ], $_REQUEST[ $key ]);
345
-        }
346
-    }
347
-
348
-
349
-    /**
350
-     * remove params
351
-     *
352
-     * @param array $keys
353
-     * @param bool  $unset_from_global_too
354
-     */
355
-    public function unSetRequestParams(array $keys, $unset_from_global_too = false)
356
-    {
357
-        foreach ($keys as $key) {
358
-            $this->unSetRequestParam($key, $unset_from_global_too);
359
-        }
360
-    }
16
+	/**
17
+	 * Used for matches() and parameterDrillDown()
18
+	 * 'bool' will return true or false if match is found or not
19
+	 */
20
+	const RETURN_BOOL  = 'bool';
21
+
22
+	/**
23
+	 * Used for matches() and parameterDrillDown()
24
+	 * 'key' will return the first key found that matches the supplied pattern
25
+	 */
26
+	const RETURN_KEY   = 'key';
27
+
28
+	/**
29
+	 * Used for matches() and parameterDrillDown()
30
+	 * 'value' will return the value for the first request parameter
31
+	 */
32
+	const RETURN_VALUE = 'value';
33
+
34
+	/**
35
+	 * $_GET parameters
36
+	 *
37
+	 * @var array
38
+	 */
39
+	protected $get;
40
+
41
+	/**
42
+	 * $_POST parameters
43
+	 *
44
+	 * @var array
45
+	 */
46
+	protected $post;
47
+
48
+	/**
49
+	 * $_REQUEST parameters
50
+	 *
51
+	 * @var array
52
+	 */
53
+	protected $request;
54
+
55
+	/**
56
+	 * @var RequestSanitizer
57
+	 */
58
+	protected $sanitizer;
59
+
60
+
61
+	/**
62
+	 * RequestParams constructor.
63
+	 *
64
+	 * @param RequestSanitizer $sanitizer
65
+	 * @param array            $get
66
+	 * @param array            $post
67
+	 */
68
+	public function __construct(RequestSanitizer $sanitizer, array $get = [], array $post = [])
69
+	{
70
+		$this->sanitizer = $sanitizer;
71
+		$this->get       = ! empty($get) ? $get : $_GET;
72
+		$this->post      = ! empty($post) ? $post : $_POST;
73
+		$this->request   = array_merge($this->get, $this->post);
74
+	}
75
+
76
+
77
+	/**
78
+	 * @return array
79
+	 */
80
+	public function getParams()
81
+	{
82
+		return $this->get;
83
+	}
84
+
85
+
86
+	/**
87
+	 * @return array
88
+	 */
89
+	public function postParams()
90
+	{
91
+		return $this->post;
92
+	}
93
+
94
+
95
+	/**
96
+	 * returns contents of $_REQUEST
97
+	 *
98
+	 * @return array
99
+	 */
100
+	public function requestParams()
101
+	{
102
+		return $this->request;
103
+	}
104
+
105
+
106
+	/**
107
+	 * @param string     $key
108
+	 * @param mixed|null $value
109
+	 * @param bool       $override_ee
110
+	 * @return    void
111
+	 */
112
+	public function setRequestParam($key, $value, $override_ee = false)
113
+	{
114
+		// don't allow "ee" to be overwritten unless explicitly instructed to do so
115
+		if ($override_ee || $key !== 'ee' || empty($this->request['ee'])) {
116
+			$this->request[ $key ] = $value;
117
+		}
118
+	}
119
+
120
+
121
+	/**
122
+	 * merges the incoming array of parameters into the existing request parameters
123
+	 *
124
+	 * @param array $request_params
125
+	 * @return void
126
+	 * @since   4.10.24.p
127
+	 */
128
+	public function mergeRequestParams(array $request_params)
129
+	{
130
+		$this->request = array_merge($this->request, $request_params);
131
+	}
132
+
133
+
134
+	/**
135
+	 * returns   the value for a request param if the given key exists
136
+	 *
137
+	 * @param string     $key
138
+	 * @param mixed|null $default
139
+	 * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc
140
+	 * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
141
+	 * @param string     $delimiter for CSV type strings that should be returned as an array
142
+	 * @return array|bool|float|int|string
143
+	 */
144
+	public function getRequestParam($key, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
145
+	{
146
+		$param = $this->sanitizer->clean(
147
+			$this->parameterDrillDown($key, $default, 'get'),
148
+			$type,
149
+			$is_array,
150
+			$delimiter
151
+		);
152
+		$type = $is_array ? 'array' : $type;
153
+		return DataType::setDataType($param, $type);
154
+	}
155
+
156
+
157
+	/**
158
+	 * check if param exists
159
+	 *
160
+	 * @param string $key
161
+	 * @return bool
162
+	 */
163
+	public function requestParamIsSet($key)
164
+	{
165
+		return (bool) $this->parameterDrillDown($key);
166
+	}
167
+
168
+
169
+	/**
170
+	 * check if a request parameter exists whose key that matches the supplied wildcard pattern
171
+	 * and return the value for the first match found
172
+	 * wildcards can be either of the following:
173
+	 *      ? to represent a single character of any type
174
+	 *      * to represent one or more characters of any type
175
+	 *
176
+	 * @param string     $pattern
177
+	 * @param mixed|null $default
178
+	 * @param string     $type      the expected data type for the parameter's value, ie: string, int, bool, etc
179
+	 * @param bool       $is_array  if true, then parameter value will be treated as an array of $type
180
+	 * @param string     $delimiter for CSV type strings that should be returned as an array
181
+	 * @return array|bool|float|int|string
182
+	 */
183
+	public function getMatch($pattern, $default = null, $type = DataType::STRING, $is_array = false, $delimiter = '')
184
+	{
185
+		$param = $this->sanitizer->clean(
186
+			$this->parameterDrillDown($pattern, $default, 'match'),
187
+			$type,
188
+			$is_array,
189
+			$delimiter
190
+		);
191
+		$type = $is_array ? 'array' : $type;
192
+		return DataType::setDataType($param, $type);
193
+	}
194
+
195
+
196
+	/**
197
+	 * check if a request parameter exists whose key matches the supplied wildcard pattern
198
+	 * wildcards can be either of the following:
199
+	 *      ? to represent a single character of any type
200
+	 *      * to represent one or more characters of any type
201
+	 * returns true if a match is found or false if not
202
+	 *
203
+	 * @param string $pattern
204
+	 * @return bool
205
+	 */
206
+	public function matches($pattern)
207
+	{
208
+		return (bool) $this->parameterDrillDown($pattern, false, 'match', self::RETURN_BOOL);
209
+	}
210
+
211
+
212
+	/**
213
+	 * @see https://stackoverflow.com/questions/6163055/php-string-matching-with-wildcard
214
+	 * @param string $pattern               A string including wildcards to be converted to a regex pattern
215
+	 *                                      and used to search through the current request's parameter keys
216
+	 * @param array  $request_params        The array of request parameters to search through
217
+	 * @param mixed  $default               [optional] The value to be returned if no match is found.
218
+	 *                                      Default is null
219
+	 * @param string $return                [optional] Controls what kind of value is returned.
220
+	 *                                      Options are the RETURN_* constants:
221
+	 *                                      RETURN_BOOL will return true or false if match is found or not
222
+	 *                                      RETURN_KEY will return the first key found that matches the supplied pattern
223
+	 *                                      RETURN_VALUE will return the value for the first request parameter
224
+	 *                                      whose key matches the supplied pattern
225
+	 *                                      Default is 'value'
226
+	 * @return boolean|string
227
+	 */
228
+	private function match($pattern, array $request_params, $default = null, $return = self::RETURN_VALUE)
229
+	{
230
+		$return = in_array($return, [self::RETURN_BOOL, self::RETURN_KEY, self::RETURN_VALUE], true)
231
+			? $return
232
+			: 'is_set';
233
+		// replace wildcard chars with regex chars
234
+		$pattern = str_replace(
235
+			['\*', '\?'],
236
+			['.*', '.'],
237
+			preg_quote($pattern, '/')
238
+		);
239
+		foreach ($request_params as $key => $request_param) {
240
+			if (preg_match('/^' . $pattern . '$/is', $key)) {
241
+				// return value for request param
242
+				if ($return === self::RETURN_VALUE) {
243
+					return $request_param;
244
+				}
245
+				// or actual key or true just to indicate it was found
246
+				return $return === self::RETURN_KEY ? $key : true;
247
+			}
248
+		}
249
+		// match not found so return default value or false
250
+		return $return === self::RETURN_VALUE ? $default : false;
251
+	}
252
+
253
+
254
+	/**
255
+	 * the supplied key can be a simple string to represent a "top-level" request parameter
256
+	 * or represent a key for a request parameter that is nested deeper within the request parameter array,
257
+	 * by using square brackets to surround keys for deeper array elements.
258
+	 * For example :
259
+	 * if the supplied $key was: "first[second][third]"
260
+	 * then this will attempt to drill down into the request parameter array to find a value.
261
+	 * Given the following request parameters:
262
+	 *  array(
263
+	 *      'first' => array(
264
+	 *          'second' => array(
265
+	 *              'third' => 'has a value'
266
+	 *          )
267
+	 *      )
268
+	 *  )
269
+	 * would return true if default parameters were set
270
+	 *
271
+	 * @param string $callback
272
+	 * @param        $key
273
+	 * @param null   $default
274
+	 * @param string $return
275
+	 * @param mixed  $request_params
276
+	 * @return bool|mixed|null
277
+	 */
278
+	private function parameterDrillDown(
279
+		$key,
280
+		$default = null,
281
+		$callback = 'is_set',
282
+		$return = self::RETURN_VALUE,
283
+		$request_params = []
284
+	) {
285
+		$callback       = in_array($callback, ['is_set', 'get', 'match'], true)
286
+			? $callback
287
+			: 'is_set';
288
+		$request_params = ! empty($request_params)
289
+			? $request_params
290
+			: $this->request;
291
+		// does incoming key represent an array like 'first[second][third]'  ?
292
+		if (strpos($key, '[') !== false) {
293
+			// turn it into an actual array
294
+			$key  = str_replace(']', '', $key);
295
+			$keys = explode('[', $key);
296
+			$key  = array_shift($keys);
297
+			if ($callback === 'match') {
298
+				$real_key = $this->match($key, $request_params, $default, self::RETURN_KEY);
299
+				$key      = $real_key ?: $key;
300
+			}
301
+			// check if top level key exists
302
+			if (isset($request_params[ $key ])) {
303
+				// build a new key to pass along like: 'second[third]'
304
+				// or just 'second' depending on depth of keys
305
+				$key_string = array_shift($keys);
306
+				if (! empty($keys)) {
307
+					$key_string .= '[' . implode('][', $keys) . ']';
308
+				}
309
+				return $this->parameterDrillDown(
310
+					$key_string,
311
+					$default,
312
+					$callback,
313
+					$return,
314
+					$request_params[ $key ]
315
+				);
316
+			}
317
+		}
318
+		if ($callback === 'is_set') {
319
+			return isset($request_params[ $key ]);
320
+		}
321
+		if ($callback === 'match') {
322
+			return $this->match($key, $request_params, $default, $return);
323
+		}
324
+		return isset($request_params[ $key ])
325
+			? $request_params[ $key ]
326
+			: $default;
327
+	}
328
+
329
+
330
+	/**
331
+	 * remove param
332
+	 *
333
+	 * @param      $key
334
+	 * @param bool $unset_from_global_too
335
+	 */
336
+	public function unSetRequestParam($key, $unset_from_global_too = false)
337
+	{
338
+		// because unset may not actually remove var
339
+		$this->get[ $key ]     = null;
340
+		$this->post[ $key ]    = null;
341
+		$this->request[ $key ] = null;
342
+		unset($this->get[ $key ], $this->post[ $key ], $this->request[ $key ]);
343
+		if ($unset_from_global_too) {
344
+			unset($_GET[ $key ], $_POST[ $key ], $_REQUEST[ $key ]);
345
+		}
346
+	}
347
+
348
+
349
+	/**
350
+	 * remove params
351
+	 *
352
+	 * @param array $keys
353
+	 * @param bool  $unset_from_global_too
354
+	 */
355
+	public function unSetRequestParams(array $keys, $unset_from_global_too = false)
356
+	{
357
+		foreach ($keys as $key) {
358
+			$this->unSetRequestParam($key, $unset_from_global_too);
359
+		}
360
+	}
361 361
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Array.helper.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
      */
83 83
     public static function is_set($arr, $index, $default)
84 84
     {
85
-        return isset($arr[ $index ]) ? $arr[ $index ] : $default;
85
+        return isset($arr[$index]) ? $arr[$index] : $default;
86 86
     }
87 87
 
88 88
     /**
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
     public static function merge_arrays_and_overwrite_keys(array $array1, array $array2)
171 171
     {
172 172
         foreach ($array2 as $key => $value) {
173
-            $array1[ $key ] = $value;
173
+            $array1[$key] = $value;
174 174
         }
175 175
         return $array1;
176 176
     }
@@ -192,8 +192,8 @@  discard block
 block discarded – undo
192 192
         $multidimensional = array();
193 193
         $reference = &$multidimensional;
194 194
         foreach ($flat_array as $key) {
195
-            $reference[ $key ] = array();
196
-            $reference = &$reference[ $key ];
195
+            $reference[$key] = array();
196
+            $reference = &$reference[$key];
197 197
         }
198 198
         if ($final_value !== null) {
199 199
             $reference = $final_value;
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
     {
225 225
         if (is_array($element)) {
226 226
             foreach ($element as $key => $value) {
227
-                $element[ $key ] = EEH_Array::addSlashesRecursively($value);
227
+                $element[$key] = EEH_Array::addSlashesRecursively($value);
228 228
             }
229 229
             return $element;
230 230
         }
Please login to merge, or discard this patch.
Indentation   +217 added lines, -217 removed lines patch added patch discarded remove patch
@@ -11,221 +11,221 @@
 block discarded – undo
11 11
  */
12 12
 class EEH_Array extends EEH_Base
13 13
 {
14
-    /**
15
-     * This method basically works the same as the PHP core function array_diff except it allows you to compare arrays
16
-     * of EE_Base_Class objects NOTE: This will ONLY work on an array of EE_Base_Class objects
17
-     *
18
-     * @uses array_udiff core php function for setting up our own array comparison
19
-     * @uses self::_compare_objects as the custom method for array_udiff
20
-     * @param  array $array1 an array of objects
21
-     * @param  array $array2 an array of objects
22
-     * @return array         an array of objects found in array 1 that aren't found in array 2.
23
-     */
24
-    public static function object_array_diff($array1, $array2)
25
-    {
26
-        return array_udiff($array1, $array2, array('self', '_compare_objects'));
27
-    }
28
-
29
-    /**
30
-     * Given that $arr is an array, determines if it's associative or numerically AND sequentially indexed
31
-     *
32
-     * @param array $array
33
-     * @return boolean
34
-     */
35
-    public static function is_associative_array(array $array)
36
-    {
37
-        return array_keys($array) !== range(0, count($array) - 1);
38
-    }
39
-
40
-    /**
41
-     * Gets an item from the array and leave the array intact. Use in place of end()
42
-     * when you don't want to change the array
43
-     *
44
-     * @param array $arr
45
-     * @return mixed what ever is in the array
46
-     */
47
-    public static function get_one_item_from_array($arr)
48
-    {
49
-        $item = end($arr);
50
-        reset($arr);
51
-        return $item;
52
-    }
53
-
54
-    /**
55
-     * Detects if this is a multi-dimensional array
56
-     * meaning that at least one top-level value is an array. Eg [ [], ...]
57
-     *
58
-     * @param mixed $arr
59
-     * @return boolean
60
-     */
61
-    public static function is_multi_dimensional_array($arr)
62
-    {
63
-        if (is_array($arr)) {
64
-            foreach ($arr as $item) {
65
-                if (is_array($item)) {
66
-                    return true; // yep, there's at least 2 levels to this array
67
-                }
68
-            }
69
-        }
70
-        return false; // there's only 1 level, or it's not an array at all!
71
-    }
72
-
73
-    /**
74
-     * Shorthand for isset( $arr[ $index ] ) ? $arr[ $index ] : $default
75
-     *
76
-     * @param array $arr
77
-     * @param mixed $index
78
-     * @param mixed $default
79
-     * @return mixed
80
-     */
81
-    public static function is_set($arr, $index, $default)
82
-    {
83
-        return isset($arr[ $index ]) ? $arr[ $index ] : $default;
84
-    }
85
-
86
-    /**
87
-     * Exactly like `maybe_unserialize`, but also accounts for a WP bug: http://core.trac.wordpress.org/ticket/26118
88
-     *
89
-     * @param mixed $value usually a string, but could be an array or object
90
-     * @return mixed the UN-serialized data
91
-     */
92
-    public static function maybe_unserialize($value)
93
-    {
94
-        $data = maybe_unserialize($value);
95
-        // it's possible that this still has serialized data if it's the session.
96
-        //  WP has a bug, http://core.trac.wordpress.org/ticket/26118 that doesn't unserialize this automatically.
97
-        $token = 'C';
98
-        $data = is_string($data) ? trim($data) : $data;
99
-        if (is_string($data) && strlen($data) > 1 && $data[0] == $token && preg_match("/^{$token}:[0-9]+:/s", $data)) {
100
-            return unserialize($data);
101
-        } else {
102
-            return $data;
103
-        }
104
-    }
105
-
106
-
107
-    /**
108
-     * insert_into_array
109
-     *
110
-     * @param array        $target_array the array to insert new data into
111
-     * @param array        $array_to_insert the new data to be inserted
112
-     * @param int | string $offset a known key within $target_array where new data will be inserted
113
-     * @param bool         $add_before whether to add new data before or after the offset key
114
-     * @param bool         $preserve_keys whether or not to reset numerically indexed arrays
115
-     * @return array
116
-     */
117
-    public static function insert_into_array(
118
-        $target_array = array(),
119
-        $array_to_insert = array(),
120
-        $offset = null,
121
-        $add_before = true,
122
-        $preserve_keys = true
123
-    ) {
124
-        // ensure incoming arrays are actually arrays
125
-        $target_array = (array) $target_array;
126
-        $array_to_insert = (array) $array_to_insert;
127
-        // if no offset key was supplied
128
-        if (empty($offset)) {
129
-            // use start or end of $target_array based on whether we are adding before or not
130
-            $offset = $add_before ? 0 : count($target_array);
131
-        }
132
-        // if offset key is a string, then find the corresponding numeric location for that element
133
-        $offset = is_int($offset) ? $offset : array_search($offset, array_keys($target_array));
134
-        // add one to the offset if adding after
135
-        $offset = $add_before ? $offset : $offset + 1;
136
-        // but ensure offset does not exceed the length of the array
137
-        $offset = $offset > count($target_array) ? count($target_array) : $offset;
138
-        // reindex array ???
139
-        if ($preserve_keys) {
140
-            // take a slice of the target array from the beginning till the offset,
141
-            // then add the new data
142
-            // then add another slice that starts at the offset and goes till the end
143
-            return array_slice($target_array, 0, $offset, true) + $array_to_insert + array_slice(
144
-                $target_array,
145
-                $offset,
146
-                null,
147
-                true
148
-            );
149
-        } else {
150
-            // since we don't want to preserve keys, we can use array_splice
151
-            array_splice($target_array, $offset, 0, $array_to_insert);
152
-            return $target_array;
153
-        }
154
-    }
155
-
156
-
157
-    /**
158
-     * array_merge() is slow and should never be used while looping over data
159
-     * if you don't need to preserve keys from all arrays, then using a foreach loop is much faster
160
-     * so really this acts more like array_replace( $array1, $array2 )
161
-     * or a union with the arrays flipped ( $array2 + $array1 )
162
-     * this saves a few lines of code and improves readability
163
-     *
164
-     * @param array $array1
165
-     * @param array $array2
166
-     * @return array
167
-     */
168
-    public static function merge_arrays_and_overwrite_keys(array $array1, array $array2)
169
-    {
170
-        foreach ($array2 as $key => $value) {
171
-            $array1[ $key ] = $value;
172
-        }
173
-        return $array1;
174
-    }
175
-
176
-
177
-    /**
178
-     * given a flat array like $array = array('A', 'B', 'C')
179
-     * will convert into a multidimensional array like $array[A][B][C]
180
-     * if $final_value is provided and is anything other than null,
181
-     * then that will be set as the value for the innermost array key
182
-     * like so: $array[A][B][C] = $final_value
183
-     *
184
-     * @param array $flat_array
185
-     * @param mixed $final_value
186
-     * @return array
187
-     */
188
-    public static function convert_array_values_to_keys(array $flat_array, $final_value = null)
189
-    {
190
-        $multidimensional = array();
191
-        $reference = &$multidimensional;
192
-        foreach ($flat_array as $key) {
193
-            $reference[ $key ] = array();
194
-            $reference = &$reference[ $key ];
195
-        }
196
-        if ($final_value !== null) {
197
-            $reference = $final_value;
198
-        }
199
-        return $multidimensional;
200
-    }
201
-
202
-
203
-    /**
204
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
205
-     * @param array $array
206
-     * @return bool
207
-     */
208
-    public static function is_array_numerically_and_sequentially_indexed(array $array)
209
-    {
210
-        return empty($array) || array_keys($array) === range(0, count($array) - 1);
211
-    }
212
-
213
-
214
-    /**
215
-     * recursively walks through an array and adds slashes to all no array elements
216
-     *
217
-     * @param mixed $element
218
-     * @return array|string
219
-     * @since   4.10.29.p
220
-     */
221
-    public static function addSlashesRecursively($element)
222
-    {
223
-        if (is_array($element)) {
224
-            foreach ($element as $key => $value) {
225
-                $element[ $key ] = EEH_Array::addSlashesRecursively($value);
226
-            }
227
-            return $element;
228
-        }
229
-        return is_string($element) ? addslashes($element) : $element;
230
-    }
14
+	/**
15
+	 * This method basically works the same as the PHP core function array_diff except it allows you to compare arrays
16
+	 * of EE_Base_Class objects NOTE: This will ONLY work on an array of EE_Base_Class objects
17
+	 *
18
+	 * @uses array_udiff core php function for setting up our own array comparison
19
+	 * @uses self::_compare_objects as the custom method for array_udiff
20
+	 * @param  array $array1 an array of objects
21
+	 * @param  array $array2 an array of objects
22
+	 * @return array         an array of objects found in array 1 that aren't found in array 2.
23
+	 */
24
+	public static function object_array_diff($array1, $array2)
25
+	{
26
+		return array_udiff($array1, $array2, array('self', '_compare_objects'));
27
+	}
28
+
29
+	/**
30
+	 * Given that $arr is an array, determines if it's associative or numerically AND sequentially indexed
31
+	 *
32
+	 * @param array $array
33
+	 * @return boolean
34
+	 */
35
+	public static function is_associative_array(array $array)
36
+	{
37
+		return array_keys($array) !== range(0, count($array) - 1);
38
+	}
39
+
40
+	/**
41
+	 * Gets an item from the array and leave the array intact. Use in place of end()
42
+	 * when you don't want to change the array
43
+	 *
44
+	 * @param array $arr
45
+	 * @return mixed what ever is in the array
46
+	 */
47
+	public static function get_one_item_from_array($arr)
48
+	{
49
+		$item = end($arr);
50
+		reset($arr);
51
+		return $item;
52
+	}
53
+
54
+	/**
55
+	 * Detects if this is a multi-dimensional array
56
+	 * meaning that at least one top-level value is an array. Eg [ [], ...]
57
+	 *
58
+	 * @param mixed $arr
59
+	 * @return boolean
60
+	 */
61
+	public static function is_multi_dimensional_array($arr)
62
+	{
63
+		if (is_array($arr)) {
64
+			foreach ($arr as $item) {
65
+				if (is_array($item)) {
66
+					return true; // yep, there's at least 2 levels to this array
67
+				}
68
+			}
69
+		}
70
+		return false; // there's only 1 level, or it's not an array at all!
71
+	}
72
+
73
+	/**
74
+	 * Shorthand for isset( $arr[ $index ] ) ? $arr[ $index ] : $default
75
+	 *
76
+	 * @param array $arr
77
+	 * @param mixed $index
78
+	 * @param mixed $default
79
+	 * @return mixed
80
+	 */
81
+	public static function is_set($arr, $index, $default)
82
+	{
83
+		return isset($arr[ $index ]) ? $arr[ $index ] : $default;
84
+	}
85
+
86
+	/**
87
+	 * Exactly like `maybe_unserialize`, but also accounts for a WP bug: http://core.trac.wordpress.org/ticket/26118
88
+	 *
89
+	 * @param mixed $value usually a string, but could be an array or object
90
+	 * @return mixed the UN-serialized data
91
+	 */
92
+	public static function maybe_unserialize($value)
93
+	{
94
+		$data = maybe_unserialize($value);
95
+		// it's possible that this still has serialized data if it's the session.
96
+		//  WP has a bug, http://core.trac.wordpress.org/ticket/26118 that doesn't unserialize this automatically.
97
+		$token = 'C';
98
+		$data = is_string($data) ? trim($data) : $data;
99
+		if (is_string($data) && strlen($data) > 1 && $data[0] == $token && preg_match("/^{$token}:[0-9]+:/s", $data)) {
100
+			return unserialize($data);
101
+		} else {
102
+			return $data;
103
+		}
104
+	}
105
+
106
+
107
+	/**
108
+	 * insert_into_array
109
+	 *
110
+	 * @param array        $target_array the array to insert new data into
111
+	 * @param array        $array_to_insert the new data to be inserted
112
+	 * @param int | string $offset a known key within $target_array where new data will be inserted
113
+	 * @param bool         $add_before whether to add new data before or after the offset key
114
+	 * @param bool         $preserve_keys whether or not to reset numerically indexed arrays
115
+	 * @return array
116
+	 */
117
+	public static function insert_into_array(
118
+		$target_array = array(),
119
+		$array_to_insert = array(),
120
+		$offset = null,
121
+		$add_before = true,
122
+		$preserve_keys = true
123
+	) {
124
+		// ensure incoming arrays are actually arrays
125
+		$target_array = (array) $target_array;
126
+		$array_to_insert = (array) $array_to_insert;
127
+		// if no offset key was supplied
128
+		if (empty($offset)) {
129
+			// use start or end of $target_array based on whether we are adding before or not
130
+			$offset = $add_before ? 0 : count($target_array);
131
+		}
132
+		// if offset key is a string, then find the corresponding numeric location for that element
133
+		$offset = is_int($offset) ? $offset : array_search($offset, array_keys($target_array));
134
+		// add one to the offset if adding after
135
+		$offset = $add_before ? $offset : $offset + 1;
136
+		// but ensure offset does not exceed the length of the array
137
+		$offset = $offset > count($target_array) ? count($target_array) : $offset;
138
+		// reindex array ???
139
+		if ($preserve_keys) {
140
+			// take a slice of the target array from the beginning till the offset,
141
+			// then add the new data
142
+			// then add another slice that starts at the offset and goes till the end
143
+			return array_slice($target_array, 0, $offset, true) + $array_to_insert + array_slice(
144
+				$target_array,
145
+				$offset,
146
+				null,
147
+				true
148
+			);
149
+		} else {
150
+			// since we don't want to preserve keys, we can use array_splice
151
+			array_splice($target_array, $offset, 0, $array_to_insert);
152
+			return $target_array;
153
+		}
154
+	}
155
+
156
+
157
+	/**
158
+	 * array_merge() is slow and should never be used while looping over data
159
+	 * if you don't need to preserve keys from all arrays, then using a foreach loop is much faster
160
+	 * so really this acts more like array_replace( $array1, $array2 )
161
+	 * or a union with the arrays flipped ( $array2 + $array1 )
162
+	 * this saves a few lines of code and improves readability
163
+	 *
164
+	 * @param array $array1
165
+	 * @param array $array2
166
+	 * @return array
167
+	 */
168
+	public static function merge_arrays_and_overwrite_keys(array $array1, array $array2)
169
+	{
170
+		foreach ($array2 as $key => $value) {
171
+			$array1[ $key ] = $value;
172
+		}
173
+		return $array1;
174
+	}
175
+
176
+
177
+	/**
178
+	 * given a flat array like $array = array('A', 'B', 'C')
179
+	 * will convert into a multidimensional array like $array[A][B][C]
180
+	 * if $final_value is provided and is anything other than null,
181
+	 * then that will be set as the value for the innermost array key
182
+	 * like so: $array[A][B][C] = $final_value
183
+	 *
184
+	 * @param array $flat_array
185
+	 * @param mixed $final_value
186
+	 * @return array
187
+	 */
188
+	public static function convert_array_values_to_keys(array $flat_array, $final_value = null)
189
+	{
190
+		$multidimensional = array();
191
+		$reference = &$multidimensional;
192
+		foreach ($flat_array as $key) {
193
+			$reference[ $key ] = array();
194
+			$reference = &$reference[ $key ];
195
+		}
196
+		if ($final_value !== null) {
197
+			$reference = $final_value;
198
+		}
199
+		return $multidimensional;
200
+	}
201
+
202
+
203
+	/**
204
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
205
+	 * @param array $array
206
+	 * @return bool
207
+	 */
208
+	public static function is_array_numerically_and_sequentially_indexed(array $array)
209
+	{
210
+		return empty($array) || array_keys($array) === range(0, count($array) - 1);
211
+	}
212
+
213
+
214
+	/**
215
+	 * recursively walks through an array and adds slashes to all no array elements
216
+	 *
217
+	 * @param mixed $element
218
+	 * @return array|string
219
+	 * @since   4.10.29.p
220
+	 */
221
+	public static function addSlashesRecursively($element)
222
+	{
223
+		if (is_array($element)) {
224
+			foreach ($element as $key => $value) {
225
+				$element[ $key ] = EEH_Array::addSlashesRecursively($value);
226
+			}
227
+			return $element;
228
+		}
229
+		return is_string($element) ? addslashes($element) : $element;
230
+	}
231 231
 }
Please login to merge, or discard this patch.
admin_pages/messages/templates/shortcode_selector_skeleton.template.php 2 patches
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -28,14 +28,14 @@
 block discarded – undo
28 28
         </h6>
29 29
         <h4>
30 30
             <?php
31
-            printf(
32
-                esc_html__('"%1$s" field', 'event_espresso'),
33
-                esc_attr($fieldname)
34
-            ); ?>
31
+			printf(
32
+				esc_html__('"%1$s" field', 'event_espresso'),
33
+				esc_attr($fieldname)
34
+			); ?>
35 35
         </h4>
36 36
         <ul>
37 37
         <?php
38
-        foreach (array_keys($shortcodes) as $shortcode) : ?>
38
+		foreach (array_keys($shortcodes) as $shortcode) : ?>
39 39
             <li>
40 40
                 <span class="js-shortcode-selection"
41 41
                       data-linked-input-id="<?php echo esc_attr($linked_input_id); ?>"
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -10,7 +10,7 @@
 block discarded – undo
10 10
  * @type    string $linked_input_id The name of the input that the shortcode gets inserted to.
11 11
  */
12 12
 
13
-if (! empty($shortcodes)) : ?>
13
+if ( ! empty($shortcodes)) : ?>
14 14
 <div class="ee-messages-shortcodes-chooser-wrap">
15 15
     <button class="ee-messages-shortcodes-chooser js-open-list-trigger button button-secondary"
16 16
             aria-label="<?php echo esc_html__('open shortcode selector', 'event_espresso'); ?>"
Please login to merge, or discard this patch.