@@ -1,5 +1,5 @@ discard block |
||
| 1 | 1 | <?php if (!defined('EVENT_ESPRESSO_VERSION')) { |
| 2 | - exit('No direct script access allowed'); |
|
| 2 | + exit('No direct script access allowed'); |
|
| 3 | 3 | } |
| 4 | 4 | |
| 5 | 5 | /** |
@@ -23,1703 +23,1703 @@ discard block |
||
| 23 | 23 | class EEH_Line_Item |
| 24 | 24 | { |
| 25 | 25 | |
| 26 | - //other functions: cancel ticket purchase |
|
| 27 | - //delete ticket purchase |
|
| 28 | - //add promotion |
|
| 29 | - |
|
| 30 | - |
|
| 31 | - /** |
|
| 32 | - * Adds a simple item (unrelated to any other model object) to the provided PARENT line item. |
|
| 33 | - * Does NOT automatically re-calculate the line item totals or update the related transaction. |
|
| 34 | - * You should call recalculate_total_including_taxes() on the grant total line item after this |
|
| 35 | - * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 36 | - * to keep the registration final prices in-sync with the transaction's total. |
|
| 37 | - * |
|
| 38 | - * @param EE_Line_Item $parent_line_item |
|
| 39 | - * @param string $name |
|
| 40 | - * @param float $unit_price |
|
| 41 | - * @param string $description |
|
| 42 | - * @param int $quantity |
|
| 43 | - * @param boolean $taxable |
|
| 44 | - * @param boolean $code if set to a value, ensures there is only one line item with that code |
|
| 45 | - * @return boolean success |
|
| 46 | - * @throws \EE_Error |
|
| 47 | - */ |
|
| 48 | - public static function add_unrelated_item(EE_Line_Item $parent_line_item, $name, $unit_price, $description = '', $quantity = 1, $taxable = FALSE, $code = NULL) |
|
| 49 | - { |
|
| 50 | - $items_subtotal = self::get_pre_tax_subtotal($parent_line_item); |
|
| 51 | - $line_item = EE_Line_Item::new_instance(array( |
|
| 52 | - 'LIN_name' => $name, |
|
| 53 | - 'LIN_desc' => $description, |
|
| 54 | - 'LIN_unit_price' => $unit_price, |
|
| 55 | - 'LIN_quantity' => $quantity, |
|
| 56 | - 'LIN_percent' => null, |
|
| 57 | - 'LIN_is_taxable' => $taxable, |
|
| 58 | - 'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0, |
|
| 59 | - 'LIN_total' => (float)$unit_price * (int)$quantity, |
|
| 60 | - 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 61 | - 'LIN_code' => $code, |
|
| 62 | - )); |
|
| 63 | - $line_item = apply_filters( |
|
| 64 | - 'FHEE__EEH_Line_Item__add_unrelated_item__line_item', |
|
| 65 | - $line_item, |
|
| 66 | - $parent_line_item |
|
| 67 | - ); |
|
| 68 | - return self::add_item($parent_line_item, $line_item); |
|
| 69 | - } |
|
| 70 | - |
|
| 71 | - |
|
| 72 | - /** |
|
| 73 | - * Adds a simple item ( unrelated to any other model object) to the total line item, |
|
| 74 | - * in the correct spot in the line item tree. Automatically |
|
| 75 | - * re-calculates the line item totals and updates the related transaction. But |
|
| 76 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 77 | - * should probably change because of this). |
|
| 78 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 79 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 80 | - * |
|
| 81 | - * @param EE_Line_Item $parent_line_item |
|
| 82 | - * @param string $name |
|
| 83 | - * @param float $percentage_amount |
|
| 84 | - * @param string $description |
|
| 85 | - * @param boolean $taxable |
|
| 86 | - * @return boolean success |
|
| 87 | - * @throws \EE_Error |
|
| 88 | - */ |
|
| 89 | - public static function add_percentage_based_item(EE_Line_Item $parent_line_item, $name, $percentage_amount, $description = '', $taxable = FALSE) |
|
| 90 | - { |
|
| 91 | - $line_item = EE_Line_Item::new_instance(array( |
|
| 92 | - 'LIN_name' => $name, |
|
| 93 | - 'LIN_desc' => $description, |
|
| 94 | - 'LIN_unit_price' => 0, |
|
| 95 | - 'LIN_percent' => $percentage_amount, |
|
| 96 | - 'LIN_quantity' => 1, |
|
| 97 | - 'LIN_is_taxable' => $taxable, |
|
| 98 | - 'LIN_total' => (float)($percentage_amount * ($parent_line_item->total() / 100)), |
|
| 99 | - 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 100 | - 'LIN_parent' => $parent_line_item->ID() |
|
| 101 | - )); |
|
| 102 | - $line_item = apply_filters( |
|
| 103 | - 'FHEE__EEH_Line_Item__add_percentage_based_item__line_item', |
|
| 104 | - $line_item |
|
| 105 | - ); |
|
| 106 | - return $parent_line_item->add_child_line_item($line_item, false); |
|
| 107 | - } |
|
| 108 | - |
|
| 109 | - |
|
| 110 | - /** |
|
| 111 | - * Returns the new line item created by adding a purchase of the ticket |
|
| 112 | - * ensures that ticket line item is saved, and that cart total has been recalculated. |
|
| 113 | - * If this ticket has already been purchased, just increments its count. |
|
| 114 | - * Automatically re-calculates the line item totals and updates the related transaction. But |
|
| 115 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 116 | - * should probably change because of this). |
|
| 117 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 118 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 119 | - * |
|
| 120 | - * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total |
|
| 121 | - * @param EE_Ticket $ticket |
|
| 122 | - * @param int $qty |
|
| 123 | - * @return \EE_Line_Item |
|
| 124 | - * @throws \EE_Error |
|
| 125 | - */ |
|
| 126 | - public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 127 | - { |
|
| 128 | - if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) { |
|
| 129 | - throw new EE_Error(sprintf(__('A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', 'event_espresso'), $ticket->ID(), $total_line_item->ID())); |
|
| 130 | - } |
|
| 131 | - // either increment the qty for an existing ticket |
|
| 132 | - $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty); |
|
| 133 | - // or add a new one |
|
| 134 | - if (!$line_item instanceof EE_Line_Item) { |
|
| 135 | - $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty); |
|
| 136 | - } |
|
| 137 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 138 | - return $line_item; |
|
| 139 | - } |
|
| 140 | - |
|
| 141 | - |
|
| 142 | - /** |
|
| 143 | - * Returns the new line item created by adding a purchase of the ticket |
|
| 144 | - * @param \EE_Line_Item $total_line_item |
|
| 145 | - * @param EE_Ticket $ticket |
|
| 146 | - * @param int $qty |
|
| 147 | - * @return \EE_Line_Item |
|
| 148 | - * @throws \EE_Error |
|
| 149 | - */ |
|
| 150 | - public static function increment_ticket_qty_if_already_in_cart(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 151 | - { |
|
| 152 | - $line_item = null; |
|
| 153 | - if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) { |
|
| 154 | - $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item); |
|
| 155 | - foreach ((array)$ticket_line_items as $ticket_line_item) { |
|
| 156 | - if ( |
|
| 157 | - $ticket_line_item instanceof EE_Line_Item |
|
| 158 | - && (int)$ticket_line_item->OBJ_ID() === (int)$ticket->ID() |
|
| 159 | - ) { |
|
| 160 | - $line_item = $ticket_line_item; |
|
| 161 | - break; |
|
| 162 | - } |
|
| 163 | - } |
|
| 164 | - } |
|
| 165 | - if ($line_item instanceof EE_Line_Item) { |
|
| 166 | - EEH_Line_Item::increment_quantity($line_item, $qty); |
|
| 167 | - return $line_item; |
|
| 168 | - } |
|
| 169 | - return null; |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - |
|
| 173 | - /** |
|
| 174 | - * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 175 | - * Does NOT save or recalculate other line items totals |
|
| 176 | - * |
|
| 177 | - * @param EE_Line_Item $line_item |
|
| 178 | - * @param int $qty |
|
| 179 | - * @return void |
|
| 180 | - * @throws \EE_Error |
|
| 181 | - */ |
|
| 182 | - public static function increment_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 183 | - { |
|
| 184 | - if (!$line_item->is_percent()) { |
|
| 185 | - $qty += $line_item->quantity(); |
|
| 186 | - $line_item->set_quantity($qty); |
|
| 187 | - $line_item->set_total($line_item->unit_price() * $qty); |
|
| 188 | - $line_item->save(); |
|
| 189 | - } |
|
| 190 | - foreach ($line_item->children() as $child) { |
|
| 191 | - if ($child->is_sub_line_item()) { |
|
| 192 | - EEH_Line_Item::update_quantity($child, $qty); |
|
| 193 | - } |
|
| 194 | - } |
|
| 195 | - } |
|
| 196 | - |
|
| 197 | - |
|
| 198 | - /** |
|
| 199 | - * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 200 | - * Does NOT save or recalculate other line items totals |
|
| 201 | - * |
|
| 202 | - * @param EE_Line_Item $line_item |
|
| 203 | - * @param int $qty |
|
| 204 | - * @return void |
|
| 205 | - * @throws \EE_Error |
|
| 206 | - */ |
|
| 207 | - public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 208 | - { |
|
| 209 | - if (!$line_item->is_percent()) { |
|
| 210 | - $qty = $line_item->quantity() - $qty; |
|
| 211 | - $qty = max($qty, 0); |
|
| 212 | - $line_item->set_quantity($qty); |
|
| 213 | - $line_item->set_total($line_item->unit_price() * $qty); |
|
| 214 | - $line_item->save(); |
|
| 215 | - } |
|
| 216 | - foreach ($line_item->children() as $child) { |
|
| 217 | - if ($child->is_sub_line_item()) { |
|
| 218 | - EEH_Line_Item::update_quantity($child, $qty); |
|
| 219 | - } |
|
| 220 | - } |
|
| 221 | - } |
|
| 222 | - |
|
| 223 | - |
|
| 224 | - /** |
|
| 225 | - * Updates the line item and its children's quantities to the specified number. |
|
| 226 | - * Does NOT save them or recalculate totals. |
|
| 227 | - * |
|
| 228 | - * @param EE_Line_Item $line_item |
|
| 229 | - * @param int $new_quantity |
|
| 230 | - * @throws \EE_Error |
|
| 231 | - */ |
|
| 232 | - public static function update_quantity(EE_Line_Item $line_item, $new_quantity) |
|
| 233 | - { |
|
| 234 | - if (!$line_item->is_percent()) { |
|
| 235 | - $line_item->set_quantity($new_quantity); |
|
| 236 | - $line_item->set_total($line_item->unit_price() * $new_quantity); |
|
| 237 | - $line_item->save(); |
|
| 238 | - } |
|
| 239 | - foreach ($line_item->children() as $child) { |
|
| 240 | - if ($child->is_sub_line_item()) { |
|
| 241 | - EEH_Line_Item::update_quantity($child, $new_quantity); |
|
| 242 | - } |
|
| 243 | - } |
|
| 244 | - } |
|
| 245 | - |
|
| 246 | - |
|
| 247 | - /** |
|
| 248 | - * Returns the new line item created by adding a purchase of the ticket |
|
| 249 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 250 | - * @param EE_Ticket $ticket |
|
| 251 | - * @param int $qty |
|
| 252 | - * @return \EE_Line_Item |
|
| 253 | - * @throws \EE_Error |
|
| 254 | - */ |
|
| 255 | - public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 256 | - { |
|
| 257 | - $datetimes = $ticket->datetimes(); |
|
| 258 | - $first_datetime = reset($datetimes); |
|
| 259 | - if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) { |
|
| 260 | - $first_datetime_name = $first_datetime->event()->name(); |
|
| 261 | - } else { |
|
| 262 | - $first_datetime_name = __('Event', 'event_espresso'); |
|
| 263 | - } |
|
| 264 | - $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name); |
|
| 265 | - // get event subtotal line |
|
| 266 | - $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket); |
|
| 267 | - // add $ticket to cart |
|
| 268 | - $line_item = EE_Line_Item::new_instance(array( |
|
| 269 | - 'LIN_name' => $ticket->name(), |
|
| 270 | - 'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event, |
|
| 271 | - 'LIN_unit_price' => $ticket->price(), |
|
| 272 | - 'LIN_quantity' => $qty, |
|
| 273 | - 'LIN_is_taxable' => $ticket->taxable(), |
|
| 274 | - 'LIN_order' => count($events_sub_total->children()), |
|
| 275 | - 'LIN_total' => $ticket->price() * $qty, |
|
| 276 | - 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 277 | - 'OBJ_ID' => $ticket->ID(), |
|
| 278 | - 'OBJ_type' => 'Ticket' |
|
| 279 | - )); |
|
| 280 | - $line_item = apply_filters( |
|
| 281 | - 'FHEE__EEH_Line_Item__create_ticket_line_item__line_item', |
|
| 282 | - $line_item |
|
| 283 | - ); |
|
| 284 | - $events_sub_total->add_child_line_item($line_item); |
|
| 285 | - //now add the sub-line items |
|
| 286 | - $running_total_for_ticket = 0; |
|
| 287 | - foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) { |
|
| 288 | - $sign = $price->is_discount() ? -1 : 1; |
|
| 289 | - $price_total = $price->is_percent() |
|
| 290 | - ? $running_total_for_ticket * $price->amount() / 100 |
|
| 291 | - : $price->amount() * $qty; |
|
| 292 | - $sub_line_item = EE_Line_Item::new_instance(array( |
|
| 293 | - 'LIN_name' => $price->name(), |
|
| 294 | - 'LIN_desc' => $price->desc(), |
|
| 295 | - 'LIN_quantity' => $price->is_percent() ? null : $qty, |
|
| 296 | - 'LIN_is_taxable' => false, |
|
| 297 | - 'LIN_order' => $price->order(), |
|
| 298 | - 'LIN_total' => $sign * $price_total, |
|
| 299 | - 'LIN_type' => EEM_Line_Item::type_sub_line_item, |
|
| 300 | - 'OBJ_ID' => $price->ID(), |
|
| 301 | - 'OBJ_type' => 'Price' |
|
| 302 | - )); |
|
| 303 | - $sub_line_item = apply_filters( |
|
| 304 | - 'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item', |
|
| 305 | - $sub_line_item |
|
| 306 | - ); |
|
| 307 | - if ($price->is_percent()) { |
|
| 308 | - $sub_line_item->set_percent($sign * $price->amount()); |
|
| 309 | - } else { |
|
| 310 | - $sub_line_item->set_unit_price($sign * $price->amount()); |
|
| 311 | - } |
|
| 312 | - $running_total_for_ticket += $price_total; |
|
| 313 | - $line_item->add_child_line_item($sub_line_item); |
|
| 314 | - } |
|
| 315 | - return $line_item; |
|
| 316 | - } |
|
| 317 | - |
|
| 318 | - |
|
| 319 | - /** |
|
| 320 | - * Adds the specified item under the pre-tax-sub-total line item. Automatically |
|
| 321 | - * re-calculates the line item totals and updates the related transaction. But |
|
| 322 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 323 | - * should probably change because of this). |
|
| 324 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 325 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 326 | - * |
|
| 327 | - * @param EE_Line_Item $total_line_item |
|
| 328 | - * @param EE_Line_Item $item to be added |
|
| 329 | - * @return boolean |
|
| 330 | - * @throws \EE_Error |
|
| 331 | - */ |
|
| 332 | - public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item) |
|
| 333 | - { |
|
| 334 | - $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item); |
|
| 335 | - if ($pre_tax_subtotal instanceof EE_Line_Item) { |
|
| 336 | - $success = $pre_tax_subtotal->add_child_line_item($item); |
|
| 337 | - } else { |
|
| 338 | - return FALSE; |
|
| 339 | - } |
|
| 340 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 341 | - return $success; |
|
| 342 | - } |
|
| 343 | - |
|
| 344 | - |
|
| 345 | - /** |
|
| 346 | - * cancels an existing ticket line item, |
|
| 347 | - * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item. |
|
| 348 | - * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 349 | - * |
|
| 350 | - * @param EE_Line_Item $ticket_line_item |
|
| 351 | - * @param int $qty |
|
| 352 | - * @return bool success |
|
| 353 | - * @throws \EE_Error |
|
| 354 | - */ |
|
| 355 | - public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 356 | - { |
|
| 357 | - // validate incoming line_item |
|
| 358 | - if ($ticket_line_item->OBJ_type() !== 'Ticket') { |
|
| 359 | - throw new EE_Error( |
|
| 360 | - sprintf( |
|
| 361 | - __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'), |
|
| 362 | - $ticket_line_item->type() |
|
| 363 | - ) |
|
| 364 | - ); |
|
| 365 | - } |
|
| 366 | - if ($ticket_line_item->quantity() < $qty) { |
|
| 367 | - throw new EE_Error( |
|
| 368 | - sprintf( |
|
| 369 | - __('Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', 'event_espresso'), |
|
| 370 | - $qty, |
|
| 371 | - $ticket_line_item->quantity() |
|
| 372 | - ) |
|
| 373 | - ); |
|
| 374 | - } |
|
| 375 | - // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this |
|
| 376 | - $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty); |
|
| 377 | - foreach ($ticket_line_item->children() as $child_line_item) { |
|
| 378 | - if ( |
|
| 379 | - $child_line_item->is_sub_line_item() |
|
| 380 | - && !$child_line_item->is_percent() |
|
| 381 | - && !$child_line_item->is_cancellation() |
|
| 382 | - ) { |
|
| 383 | - $child_line_item->set_quantity($child_line_item->quantity() - $qty); |
|
| 384 | - } |
|
| 385 | - } |
|
| 386 | - // get cancellation sub line item |
|
| 387 | - $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 388 | - $ticket_line_item, |
|
| 389 | - EEM_Line_Item::type_cancellation |
|
| 390 | - ); |
|
| 391 | - $cancellation_line_item = reset($cancellation_line_item); |
|
| 392 | - // verify that this ticket was indeed previously cancelled |
|
| 393 | - if ($cancellation_line_item instanceof EE_Line_Item) { |
|
| 394 | - // increment cancelled quantity |
|
| 395 | - $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty); |
|
| 396 | - } else { |
|
| 397 | - // create cancellation sub line item |
|
| 398 | - $cancellation_line_item = EE_Line_Item::new_instance(array( |
|
| 399 | - 'LIN_name' => __('Cancellation', 'event_espresso'), |
|
| 400 | - 'LIN_desc' => sprintf( |
|
| 401 | - _x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'), |
|
| 402 | - $ticket_line_item->name(), |
|
| 403 | - current_time(get_option('date_format') . ' ' . get_option('time_format')) |
|
| 404 | - ), |
|
| 405 | - 'LIN_unit_price' => 0, // $ticket_line_item->unit_price() |
|
| 406 | - 'LIN_quantity' => $qty, |
|
| 407 | - 'LIN_is_taxable' => $ticket_line_item->is_taxable(), |
|
| 408 | - 'LIN_order' => count($ticket_line_item->children()), |
|
| 409 | - 'LIN_total' => 0, // $ticket_line_item->unit_price() |
|
| 410 | - 'LIN_type' => EEM_Line_Item::type_cancellation, |
|
| 411 | - )); |
|
| 412 | - $ticket_line_item->add_child_line_item($cancellation_line_item); |
|
| 413 | - } |
|
| 414 | - if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 415 | - // decrement parent line item quantity |
|
| 416 | - $event_line_item = $ticket_line_item->parent(); |
|
| 417 | - if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') { |
|
| 418 | - $event_line_item->set_quantity($event_line_item->quantity() - $qty); |
|
| 419 | - $event_line_item->save(); |
|
| 420 | - } |
|
| 421 | - EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 422 | - return true; |
|
| 423 | - } |
|
| 424 | - return false; |
|
| 425 | - } |
|
| 426 | - |
|
| 427 | - |
|
| 428 | - /** |
|
| 429 | - * reinstates (un-cancels?) a previously canceled ticket line item, |
|
| 430 | - * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item. |
|
| 431 | - * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 432 | - * |
|
| 433 | - * @param EE_Line_Item $ticket_line_item |
|
| 434 | - * @param int $qty |
|
| 435 | - * @return bool success |
|
| 436 | - * @throws \EE_Error |
|
| 437 | - */ |
|
| 438 | - public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 439 | - { |
|
| 440 | - // validate incoming line_item |
|
| 441 | - if ($ticket_line_item->OBJ_type() !== 'Ticket') { |
|
| 442 | - throw new EE_Error( |
|
| 443 | - sprintf( |
|
| 444 | - __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'), |
|
| 445 | - $ticket_line_item->type() |
|
| 446 | - ) |
|
| 447 | - ); |
|
| 448 | - } |
|
| 449 | - // get cancellation sub line item |
|
| 450 | - $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 451 | - $ticket_line_item, |
|
| 452 | - EEM_Line_Item::type_cancellation |
|
| 453 | - ); |
|
| 454 | - $cancellation_line_item = reset($cancellation_line_item); |
|
| 455 | - // verify that this ticket was indeed previously cancelled |
|
| 456 | - if (!$cancellation_line_item instanceof EE_Line_Item) { |
|
| 457 | - return false; |
|
| 458 | - } |
|
| 459 | - if ($cancellation_line_item->quantity() > $qty) { |
|
| 460 | - // decrement cancelled quantity |
|
| 461 | - $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 462 | - } else if ($cancellation_line_item->quantity() == $qty) { |
|
| 463 | - // decrement cancelled quantity in case anyone still has the object kicking around |
|
| 464 | - $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 465 | - // delete because quantity will end up as 0 |
|
| 466 | - $cancellation_line_item->delete(); |
|
| 467 | - // and attempt to destroy the object, |
|
| 468 | - // even though PHP won't actually destroy it until it needs the memory |
|
| 469 | - unset($cancellation_line_item); |
|
| 470 | - } else { |
|
| 471 | - // what ?!?! negative quantity ?!?! |
|
| 472 | - throw new EE_Error( |
|
| 473 | - sprintf( |
|
| 474 | - __('Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.', |
|
| 475 | - 'event_espresso'), |
|
| 476 | - $qty, |
|
| 477 | - $cancellation_line_item->quantity() |
|
| 478 | - ) |
|
| 479 | - ); |
|
| 480 | - } |
|
| 481 | - // increment ticket quantity |
|
| 482 | - $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty); |
|
| 483 | - if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 484 | - // increment parent line item quantity |
|
| 485 | - $event_line_item = $ticket_line_item->parent(); |
|
| 486 | - if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') { |
|
| 487 | - $event_line_item->set_quantity($event_line_item->quantity() + $qty); |
|
| 488 | - } |
|
| 489 | - EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 490 | - return true; |
|
| 491 | - } |
|
| 492 | - return false; |
|
| 493 | - } |
|
| 494 | - |
|
| 495 | - |
|
| 496 | - /** |
|
| 497 | - * calls EEH_Line_Item::find_transaction_grand_total_for_line_item() |
|
| 498 | - * then EE_Line_Item::recalculate_total_including_taxes() on the result |
|
| 499 | - * |
|
| 500 | - * @param EE_Line_Item $line_item |
|
| 501 | - * @return \EE_Line_Item |
|
| 502 | - */ |
|
| 503 | - public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item) |
|
| 504 | - { |
|
| 505 | - $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item); |
|
| 506 | - return $grand_total_line_item->recalculate_total_including_taxes(); |
|
| 507 | - } |
|
| 508 | - |
|
| 509 | - |
|
| 510 | - /** |
|
| 511 | - * Gets the line item which contains the subtotal of all the items |
|
| 512 | - * |
|
| 513 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 514 | - * @return \EE_Line_Item |
|
| 515 | - * @throws \EE_Error |
|
| 516 | - */ |
|
| 517 | - public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item) |
|
| 518 | - { |
|
| 519 | - $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal'); |
|
| 520 | - return $pre_tax_subtotal instanceof EE_Line_Item |
|
| 521 | - ? $pre_tax_subtotal |
|
| 522 | - : self::create_pre_tax_subtotal($total_line_item); |
|
| 523 | - } |
|
| 524 | - |
|
| 525 | - |
|
| 526 | - /** |
|
| 527 | - * Gets the line item for the taxes subtotal |
|
| 528 | - * |
|
| 529 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 530 | - * @return \EE_Line_Item |
|
| 531 | - * @throws \EE_Error |
|
| 532 | - */ |
|
| 533 | - public static function get_taxes_subtotal(EE_Line_Item $total_line_item) |
|
| 534 | - { |
|
| 535 | - $taxes = $total_line_item->get_child_line_item('taxes'); |
|
| 536 | - return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item); |
|
| 537 | - } |
|
| 538 | - |
|
| 539 | - |
|
| 540 | - /** |
|
| 541 | - * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object |
|
| 542 | - * |
|
| 543 | - * @param EE_Line_Item $line_item |
|
| 544 | - * @param EE_Transaction $transaction |
|
| 545 | - * @return void |
|
| 546 | - * @throws \EE_Error |
|
| 547 | - */ |
|
| 548 | - public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = NULL) |
|
| 549 | - { |
|
| 550 | - if ($transaction) { |
|
| 551 | - /** @type EEM_Transaction $EEM_Transaction */ |
|
| 552 | - $EEM_Transaction = EE_Registry::instance()->load_model('Transaction'); |
|
| 553 | - $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction); |
|
| 554 | - $line_item->set_TXN_ID($TXN_ID); |
|
| 555 | - } |
|
| 556 | - } |
|
| 557 | - |
|
| 558 | - |
|
| 559 | - /** |
|
| 560 | - * Creates a new default total line item for the transaction, |
|
| 561 | - * and its tickets subtotal and taxes subtotal line items (and adds the |
|
| 562 | - * existing taxes as children of the taxes subtotal line item) |
|
| 563 | - * |
|
| 564 | - * @param EE_Transaction $transaction |
|
| 565 | - * @return \EE_Line_Item of type total |
|
| 566 | - * @throws \EE_Error |
|
| 567 | - */ |
|
| 568 | - public static function create_total_line_item($transaction = NULL) |
|
| 569 | - { |
|
| 570 | - $total_line_item = EE_Line_Item::new_instance(array( |
|
| 571 | - 'LIN_code' => 'total', |
|
| 572 | - 'LIN_name' => __('Grand Total', 'event_espresso'), |
|
| 573 | - 'LIN_type' => EEM_Line_Item::type_total, |
|
| 574 | - 'OBJ_type' => 'Transaction' |
|
| 575 | - )); |
|
| 576 | - $total_line_item = apply_filters( |
|
| 577 | - 'FHEE__EEH_Line_Item__create_total_line_item__total_line_item', |
|
| 578 | - $total_line_item |
|
| 579 | - ); |
|
| 580 | - self::set_TXN_ID($total_line_item, $transaction); |
|
| 581 | - self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 582 | - self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 583 | - return $total_line_item; |
|
| 584 | - } |
|
| 585 | - |
|
| 586 | - |
|
| 587 | - /** |
|
| 588 | - * Creates a default items subtotal line item |
|
| 589 | - * |
|
| 590 | - * @param EE_Line_Item $total_line_item |
|
| 591 | - * @param EE_Transaction $transaction |
|
| 592 | - * @return EE_Line_Item |
|
| 593 | - * @throws \EE_Error |
|
| 594 | - */ |
|
| 595 | - protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 596 | - { |
|
| 597 | - $pre_tax_line_item = EE_Line_Item::new_instance(array( |
|
| 598 | - 'LIN_code' => 'pre-tax-subtotal', |
|
| 599 | - 'LIN_name' => __('Pre-Tax Subtotal', 'event_espresso'), |
|
| 600 | - 'LIN_type' => EEM_Line_Item::type_sub_total |
|
| 601 | - )); |
|
| 602 | - $pre_tax_line_item = apply_filters( |
|
| 603 | - 'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item', |
|
| 604 | - $pre_tax_line_item |
|
| 605 | - ); |
|
| 606 | - self::set_TXN_ID($pre_tax_line_item, $transaction); |
|
| 607 | - $total_line_item->add_child_line_item($pre_tax_line_item); |
|
| 608 | - self::create_event_subtotal($pre_tax_line_item, $transaction); |
|
| 609 | - return $pre_tax_line_item; |
|
| 610 | - } |
|
| 611 | - |
|
| 612 | - |
|
| 613 | - /** |
|
| 614 | - * Creates a line item for the taxes subtotal and finds all the tax prices |
|
| 615 | - * and applies taxes to it |
|
| 616 | - * |
|
| 617 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 618 | - * @param EE_Transaction $transaction |
|
| 619 | - * @return EE_Line_Item |
|
| 620 | - * @throws \EE_Error |
|
| 621 | - */ |
|
| 622 | - protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 623 | - { |
|
| 624 | - $tax_line_item = EE_Line_Item::new_instance(array( |
|
| 625 | - 'LIN_code' => 'taxes', |
|
| 626 | - 'LIN_name' => __('Taxes', 'event_espresso'), |
|
| 627 | - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, |
|
| 628 | - 'LIN_order' => 1000,//this should always come last |
|
| 629 | - )); |
|
| 630 | - $tax_line_item = apply_filters( |
|
| 631 | - 'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item', |
|
| 632 | - $tax_line_item |
|
| 633 | - ); |
|
| 634 | - self::set_TXN_ID($tax_line_item, $transaction); |
|
| 635 | - $total_line_item->add_child_line_item($tax_line_item); |
|
| 636 | - //and lastly, add the actual taxes |
|
| 637 | - self::apply_taxes($total_line_item); |
|
| 638 | - return $tax_line_item; |
|
| 639 | - } |
|
| 640 | - |
|
| 641 | - |
|
| 642 | - /** |
|
| 643 | - * Creates a default items subtotal line item |
|
| 644 | - * |
|
| 645 | - * @param EE_Line_Item $pre_tax_line_item |
|
| 646 | - * @param EE_Transaction $transaction |
|
| 647 | - * @param EE_Event $event |
|
| 648 | - * @return EE_Line_Item |
|
| 649 | - * @throws \EE_Error |
|
| 650 | - */ |
|
| 651 | - public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = NULL, $event = NULL) |
|
| 652 | - { |
|
| 653 | - $event_line_item = EE_Line_Item::new_instance(array( |
|
| 654 | - 'LIN_code' => self::get_event_code($event), |
|
| 655 | - 'LIN_name' => self::get_event_name($event), |
|
| 656 | - 'LIN_desc' => self::get_event_desc($event), |
|
| 657 | - 'LIN_type' => EEM_Line_Item::type_sub_total, |
|
| 658 | - 'OBJ_type' => 'Event', |
|
| 659 | - 'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0 |
|
| 660 | - )); |
|
| 661 | - $event_line_item = apply_filters( |
|
| 662 | - 'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item', |
|
| 663 | - $event_line_item |
|
| 664 | - ); |
|
| 665 | - self::set_TXN_ID($event_line_item, $transaction); |
|
| 666 | - $pre_tax_line_item->add_child_line_item($event_line_item); |
|
| 667 | - return $event_line_item; |
|
| 668 | - } |
|
| 669 | - |
|
| 670 | - |
|
| 671 | - /** |
|
| 672 | - * Gets what the event ticket's code SHOULD be |
|
| 673 | - * |
|
| 674 | - * @param EE_Event $event |
|
| 675 | - * @return string |
|
| 676 | - * @throws \EE_Error |
|
| 677 | - */ |
|
| 678 | - public static function get_event_code($event) |
|
| 679 | - { |
|
| 680 | - return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 681 | - } |
|
| 682 | - |
|
| 683 | - /** |
|
| 684 | - * Gets the event name |
|
| 685 | - * @param EE_Event $event |
|
| 686 | - * @return string |
|
| 687 | - */ |
|
| 688 | - public static function get_event_name($event) |
|
| 689 | - { |
|
| 690 | - return $event instanceof EE_Event ? $event->name() : __('Event', 'event_espresso'); |
|
| 691 | - } |
|
| 692 | - |
|
| 693 | - /** |
|
| 694 | - * Gets the event excerpt |
|
| 695 | - * @param EE_Event $event |
|
| 696 | - * @return string |
|
| 697 | - */ |
|
| 698 | - public static function get_event_desc($event) |
|
| 699 | - { |
|
| 700 | - return $event instanceof EE_Event ? $event->short_description() : ''; |
|
| 701 | - } |
|
| 702 | - |
|
| 703 | - /** |
|
| 704 | - * Given the grand total line item and a ticket, finds the event sub-total |
|
| 705 | - * line item the ticket's purchase should be added onto |
|
| 706 | - * |
|
| 707 | - * @access public |
|
| 708 | - * @param EE_Line_Item $grand_total the grand total line item |
|
| 709 | - * @param EE_Ticket $ticket |
|
| 710 | - * @throws \EE_Error |
|
| 711 | - * @return EE_Line_Item |
|
| 712 | - */ |
|
| 713 | - public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket) |
|
| 714 | - { |
|
| 715 | - $first_datetime = $ticket->first_datetime(); |
|
| 716 | - if (!$first_datetime instanceof EE_Datetime) { |
|
| 717 | - throw new EE_Error( |
|
| 718 | - sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID()) |
|
| 719 | - ); |
|
| 720 | - } |
|
| 721 | - $event = $first_datetime->event(); |
|
| 722 | - if (!$event instanceof EE_Event) { |
|
| 723 | - throw new EE_Error( |
|
| 724 | - sprintf( |
|
| 725 | - __('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'), |
|
| 726 | - $ticket->ID() |
|
| 727 | - ) |
|
| 728 | - ); |
|
| 729 | - } |
|
| 730 | - $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event); |
|
| 731 | - if (!$events_sub_total instanceof EE_Line_Item) { |
|
| 732 | - throw new EE_Error( |
|
| 733 | - sprintf( |
|
| 734 | - __('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'), |
|
| 735 | - $ticket->ID(), |
|
| 736 | - $grand_total->ID() |
|
| 737 | - ) |
|
| 738 | - ); |
|
| 739 | - } |
|
| 740 | - return $events_sub_total; |
|
| 741 | - } |
|
| 742 | - |
|
| 743 | - |
|
| 744 | - /** |
|
| 745 | - * Gets the event line item |
|
| 746 | - * |
|
| 747 | - * @param EE_Line_Item $grand_total |
|
| 748 | - * @param EE_Event $event |
|
| 749 | - * @return EE_Line_Item for the event subtotal which is a child of $grand_total |
|
| 750 | - * @throws \EE_Error |
|
| 751 | - */ |
|
| 752 | - public static function get_event_line_item(EE_Line_Item $grand_total, $event) |
|
| 753 | - { |
|
| 754 | - /** @type EE_Event $event */ |
|
| 755 | - $event = EEM_Event::instance()->ensure_is_obj($event, true); |
|
| 756 | - $event_line_item = NULL; |
|
| 757 | - $found = false; |
|
| 758 | - foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) { |
|
| 759 | - // default event subtotal, we should only ever find this the first time this method is called |
|
| 760 | - if (!$event_line_item->OBJ_ID()) { |
|
| 761 | - // let's use this! but first... set the event details |
|
| 762 | - EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 763 | - $found = true; |
|
| 764 | - break; |
|
| 765 | - } else if ($event_line_item->OBJ_ID() === $event->ID()) { |
|
| 766 | - // found existing line item for this event in the cart, so break out of loop and use this one |
|
| 767 | - $found = true; |
|
| 768 | - break; |
|
| 769 | - } |
|
| 770 | - } |
|
| 771 | - if (!$found) { |
|
| 772 | - //there is no event sub-total yet, so add it |
|
| 773 | - $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total); |
|
| 774 | - // create a new "event" subtotal below that |
|
| 775 | - $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event); |
|
| 776 | - // and set the event details |
|
| 777 | - EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 778 | - } |
|
| 779 | - return $event_line_item; |
|
| 780 | - } |
|
| 781 | - |
|
| 782 | - |
|
| 783 | - /** |
|
| 784 | - * Creates a default items subtotal line item |
|
| 785 | - * |
|
| 786 | - * @param EE_Line_Item $event_line_item |
|
| 787 | - * @param EE_Event $event |
|
| 788 | - * @param EE_Transaction $transaction |
|
| 789 | - * @return EE_Line_Item |
|
| 790 | - * @throws \EE_Error |
|
| 791 | - */ |
|
| 792 | - public static function set_event_subtotal_details( |
|
| 793 | - EE_Line_Item $event_line_item, |
|
| 794 | - EE_Event $event, |
|
| 795 | - $transaction = null |
|
| 796 | - ) |
|
| 797 | - { |
|
| 798 | - if ($event instanceof EE_Event) { |
|
| 799 | - $event_line_item->set_code(self::get_event_code($event)); |
|
| 800 | - $event_line_item->set_name(self::get_event_name($event)); |
|
| 801 | - $event_line_item->set_desc(self::get_event_desc($event)); |
|
| 802 | - $event_line_item->set_OBJ_ID($event->ID()); |
|
| 803 | - } |
|
| 804 | - self::set_TXN_ID($event_line_item, $transaction); |
|
| 805 | - } |
|
| 806 | - |
|
| 807 | - |
|
| 808 | - /** |
|
| 809 | - * Finds what taxes should apply, adds them as tax line items under the taxes sub-total, |
|
| 810 | - * and recalculates the taxes sub-total and the grand total. Resets the taxes, so |
|
| 811 | - * any old taxes are removed |
|
| 812 | - * |
|
| 813 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 814 | - * @throws \EE_Error |
|
| 815 | - */ |
|
| 816 | - public static function apply_taxes(EE_Line_Item $total_line_item) |
|
| 817 | - { |
|
| 818 | - /** @type EEM_Price $EEM_Price */ |
|
| 819 | - $EEM_Price = EE_Registry::instance()->load_model('Price'); |
|
| 820 | - // get array of taxes via Price Model |
|
| 821 | - $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes(); |
|
| 822 | - ksort($ordered_taxes); |
|
| 823 | - $taxes_line_item = self::get_taxes_subtotal($total_line_item); |
|
| 824 | - //just to be safe, remove its old tax line items |
|
| 825 | - $taxes_line_item->delete_children_line_items(); |
|
| 826 | - //loop thru taxes |
|
| 827 | - foreach ($ordered_taxes as $order => $taxes) { |
|
| 828 | - foreach ($taxes as $tax) { |
|
| 829 | - if ($tax instanceof EE_Price) { |
|
| 830 | - $tax_line_item = EE_Line_Item::new_instance( |
|
| 831 | - array( |
|
| 832 | - 'LIN_name' => $tax->name(), |
|
| 833 | - 'LIN_desc' => $tax->desc(), |
|
| 834 | - 'LIN_percent' => $tax->amount(), |
|
| 835 | - 'LIN_is_taxable' => false, |
|
| 836 | - 'LIN_order' => $order, |
|
| 837 | - 'LIN_total' => 0, |
|
| 838 | - 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 839 | - 'OBJ_type' => 'Price', |
|
| 840 | - 'OBJ_ID' => $tax->ID() |
|
| 841 | - ) |
|
| 842 | - ); |
|
| 843 | - $tax_line_item = apply_filters( |
|
| 844 | - 'FHEE__EEH_Line_Item__apply_taxes__tax_line_item', |
|
| 845 | - $tax_line_item |
|
| 846 | - ); |
|
| 847 | - $taxes_line_item->add_child_line_item($tax_line_item); |
|
| 848 | - } |
|
| 849 | - } |
|
| 850 | - } |
|
| 851 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 852 | - } |
|
| 853 | - |
|
| 854 | - |
|
| 855 | - /** |
|
| 856 | - * Ensures that taxes have been applied to the order, if not applies them. |
|
| 857 | - * Returns the total amount of tax |
|
| 858 | - * |
|
| 859 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 860 | - * @return float |
|
| 861 | - * @throws \EE_Error |
|
| 862 | - */ |
|
| 863 | - public static function ensure_taxes_applied($total_line_item) |
|
| 864 | - { |
|
| 865 | - $taxes_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 866 | - if (!$taxes_subtotal->children()) { |
|
| 867 | - self::apply_taxes($total_line_item); |
|
| 868 | - } |
|
| 869 | - return $taxes_subtotal->total(); |
|
| 870 | - } |
|
| 871 | - |
|
| 872 | - |
|
| 873 | - /** |
|
| 874 | - * Deletes ALL children of the passed line item |
|
| 875 | - * |
|
| 876 | - * @param EE_Line_Item $parent_line_item |
|
| 877 | - * @return bool |
|
| 878 | - * @throws \EE_Error |
|
| 879 | - */ |
|
| 880 | - public static function delete_all_child_items(EE_Line_Item $parent_line_item) |
|
| 881 | - { |
|
| 882 | - $deleted = 0; |
|
| 883 | - foreach ($parent_line_item->children() as $child_line_item) { |
|
| 884 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 885 | - $deleted += EEH_Line_Item::delete_all_child_items($child_line_item); |
|
| 886 | - if ($child_line_item->ID()) { |
|
| 887 | - $child_line_item->delete(); |
|
| 888 | - unset($child_line_item); |
|
| 889 | - } else { |
|
| 890 | - $parent_line_item->delete_child_line_item($child_line_item->code()); |
|
| 891 | - } |
|
| 892 | - $deleted++; |
|
| 893 | - } |
|
| 894 | - } |
|
| 895 | - return $deleted; |
|
| 896 | - } |
|
| 897 | - |
|
| 898 | - |
|
| 899 | - /** |
|
| 900 | - * Deletes the line items as indicated by the line item code(s) provided, |
|
| 901 | - * regardless of where they're found in the line item tree. Automatically |
|
| 902 | - * re-calculates the line item totals and updates the related transaction. But |
|
| 903 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 904 | - * should probably change because of this). |
|
| 905 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 906 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 907 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 908 | - * @param array|bool|string $line_item_codes |
|
| 909 | - * @return int number of items successfully removed |
|
| 910 | - */ |
|
| 911 | - public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = FALSE) |
|
| 912 | - { |
|
| 913 | - |
|
| 914 | - if ($total_line_item->type() !== EEM_Line_Item::type_total) { |
|
| 915 | - EE_Error::doing_it_wrong( |
|
| 916 | - 'EEH_Line_Item::delete_items', |
|
| 917 | - __( |
|
| 918 | - 'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly', |
|
| 919 | - 'event_espresso' |
|
| 920 | - ), |
|
| 921 | - '4.6.18' |
|
| 922 | - ); |
|
| 923 | - } |
|
| 924 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 925 | - |
|
| 926 | - // check if only a single line_item_id was passed |
|
| 927 | - if (!empty($line_item_codes) && !is_array($line_item_codes)) { |
|
| 928 | - // place single line_item_id in an array to appear as multiple line_item_ids |
|
| 929 | - $line_item_codes = array($line_item_codes); |
|
| 930 | - } |
|
| 931 | - $removals = 0; |
|
| 932 | - // cycle thru line_item_ids |
|
| 933 | - foreach ($line_item_codes as $line_item_id) { |
|
| 934 | - $removals += $total_line_item->delete_child_line_item($line_item_id); |
|
| 935 | - } |
|
| 936 | - |
|
| 937 | - if ($removals > 0) { |
|
| 938 | - $total_line_item->recalculate_taxes_and_tax_total(); |
|
| 939 | - return $removals; |
|
| 940 | - } else { |
|
| 941 | - return FALSE; |
|
| 942 | - } |
|
| 943 | - } |
|
| 944 | - |
|
| 945 | - |
|
| 946 | - /** |
|
| 947 | - * Overwrites the previous tax by clearing out the old taxes, and creates a new |
|
| 948 | - * tax and updates the total line item accordingly |
|
| 949 | - * |
|
| 950 | - * @param EE_Line_Item $total_line_item |
|
| 951 | - * @param float $amount |
|
| 952 | - * @param string $name |
|
| 953 | - * @param string $description |
|
| 954 | - * @param string $code |
|
| 955 | - * @param boolean $add_to_existing_line_item |
|
| 956 | - * if true, and a duplicate line item with the same code is found, |
|
| 957 | - * $amount will be added onto it; otherwise will simply set the taxes to match $amount |
|
| 958 | - * @return EE_Line_Item the new tax line item created |
|
| 959 | - * @throws \EE_Error |
|
| 960 | - */ |
|
| 961 | - public static function set_total_tax_to( |
|
| 962 | - EE_Line_Item $total_line_item, |
|
| 963 | - $amount, |
|
| 964 | - $name = null, |
|
| 965 | - $description = null, |
|
| 966 | - $code = null, |
|
| 967 | - $add_to_existing_line_item = false |
|
| 968 | - ) |
|
| 969 | - { |
|
| 970 | - $tax_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 971 | - $taxable_total = $total_line_item->taxable_total(); |
|
| 972 | - |
|
| 973 | - if ($add_to_existing_line_item) { |
|
| 974 | - $new_tax = $tax_subtotal->get_child_line_item($code); |
|
| 975 | - EEM_Line_Item::instance()->delete( |
|
| 976 | - array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID())) |
|
| 977 | - ); |
|
| 978 | - } else { |
|
| 979 | - $new_tax = null; |
|
| 980 | - $tax_subtotal->delete_children_line_items(); |
|
| 981 | - } |
|
| 982 | - if ($new_tax) { |
|
| 983 | - $new_tax->set_total($new_tax->total() + $amount); |
|
| 984 | - $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0); |
|
| 985 | - } else { |
|
| 986 | - //no existing tax item. Create it |
|
| 987 | - $new_tax = EE_Line_Item::new_instance(array( |
|
| 988 | - 'TXN_ID' => $total_line_item->TXN_ID(), |
|
| 989 | - 'LIN_name' => $name ? $name : __('Tax', 'event_espresso'), |
|
| 990 | - 'LIN_desc' => $description ? $description : '', |
|
| 991 | - 'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0, |
|
| 992 | - 'LIN_total' => $amount, |
|
| 993 | - 'LIN_parent' => $tax_subtotal->ID(), |
|
| 994 | - 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 995 | - 'LIN_code' => $code |
|
| 996 | - )); |
|
| 997 | - } |
|
| 998 | - |
|
| 999 | - $new_tax = apply_filters( |
|
| 1000 | - 'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal', |
|
| 1001 | - $new_tax, |
|
| 1002 | - $total_line_item |
|
| 1003 | - ); |
|
| 1004 | - $new_tax->save(); |
|
| 1005 | - $tax_subtotal->set_total($new_tax->total()); |
|
| 1006 | - $tax_subtotal->save(); |
|
| 1007 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 1008 | - return $new_tax; |
|
| 1009 | - } |
|
| 1010 | - |
|
| 1011 | - |
|
| 1012 | - /** |
|
| 1013 | - * Makes all the line items which are children of $line_item taxable (or not). |
|
| 1014 | - * Does NOT save the line items |
|
| 1015 | - * @param EE_Line_Item $line_item |
|
| 1016 | - * @param string $code_substring_for_whitelist if this string is part of the line item's code |
|
| 1017 | - * it will be whitelisted (ie, except from becoming taxable) |
|
| 1018 | - * @param boolean $taxable |
|
| 1019 | - */ |
|
| 1020 | - public static function set_line_items_taxable( |
|
| 1021 | - EE_Line_Item $line_item, |
|
| 1022 | - $taxable = true, |
|
| 1023 | - $code_substring_for_whitelist = null |
|
| 1024 | - ) |
|
| 1025 | - { |
|
| 1026 | - $whitelisted = false; |
|
| 1027 | - if ($code_substring_for_whitelist !== null) { |
|
| 1028 | - $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false; |
|
| 1029 | - } |
|
| 1030 | - if (!$whitelisted && $line_item->is_line_item()) { |
|
| 1031 | - $line_item->set_is_taxable($taxable); |
|
| 1032 | - } |
|
| 1033 | - foreach ($line_item->children() as $child_line_item) { |
|
| 1034 | - EEH_Line_Item::set_line_items_taxable($child_line_item, $taxable, $code_substring_for_whitelist); |
|
| 1035 | - } |
|
| 1036 | - } |
|
| 1037 | - |
|
| 1038 | - |
|
| 1039 | - /** |
|
| 1040 | - * Gets all descendants that are event subtotals |
|
| 1041 | - * |
|
| 1042 | - * @uses EEH_Line_Item::get_subtotals_of_object_type() |
|
| 1043 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1044 | - * @return EE_Line_Item[] |
|
| 1045 | - */ |
|
| 1046 | - public static function get_event_subtotals(EE_Line_Item $parent_line_item) |
|
| 1047 | - { |
|
| 1048 | - return self::get_subtotals_of_object_type($parent_line_item, 'Event'); |
|
| 1049 | - } |
|
| 1050 | - |
|
| 1051 | - |
|
| 1052 | - /** |
|
| 1053 | - * Gets all descendants subtotals that match the supplied object type |
|
| 1054 | - * |
|
| 1055 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1056 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1057 | - * @param string $obj_type |
|
| 1058 | - * @return EE_Line_Item[] |
|
| 1059 | - */ |
|
| 1060 | - public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1061 | - { |
|
| 1062 | - return self::_get_descendants_by_type_and_object_type( |
|
| 1063 | - $parent_line_item, |
|
| 1064 | - EEM_Line_Item::type_sub_total, |
|
| 1065 | - $obj_type |
|
| 1066 | - ); |
|
| 1067 | - } |
|
| 1068 | - |
|
| 1069 | - |
|
| 1070 | - /** |
|
| 1071 | - * Gets all descendants that are tickets |
|
| 1072 | - * |
|
| 1073 | - * @uses EEH_Line_Item::get_line_items_of_object_type() |
|
| 1074 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1075 | - * @return EE_Line_Item[] |
|
| 1076 | - */ |
|
| 1077 | - public static function get_ticket_line_items(EE_Line_Item $parent_line_item) |
|
| 1078 | - { |
|
| 1079 | - return self::get_line_items_of_object_type($parent_line_item, 'Ticket'); |
|
| 1080 | - } |
|
| 1081 | - |
|
| 1082 | - |
|
| 1083 | - /** |
|
| 1084 | - * Gets all descendants subtotals that match the supplied object type |
|
| 1085 | - * |
|
| 1086 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1087 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1088 | - * @param string $obj_type |
|
| 1089 | - * @return EE_Line_Item[] |
|
| 1090 | - */ |
|
| 1091 | - public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1092 | - { |
|
| 1093 | - return self::_get_descendants_by_type_and_object_type($parent_line_item, EEM_Line_Item::type_line_item, $obj_type); |
|
| 1094 | - } |
|
| 1095 | - |
|
| 1096 | - |
|
| 1097 | - /** |
|
| 1098 | - * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax' |
|
| 1099 | - * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1100 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1101 | - * @return EE_Line_Item[] |
|
| 1102 | - */ |
|
| 1103 | - public static function get_tax_descendants(EE_Line_Item $parent_line_item) |
|
| 1104 | - { |
|
| 1105 | - return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_tax); |
|
| 1106 | - } |
|
| 1107 | - |
|
| 1108 | - |
|
| 1109 | - /** |
|
| 1110 | - * Gets all the real items purchased which are children of this item |
|
| 1111 | - * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1112 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1113 | - * @return EE_Line_Item[] |
|
| 1114 | - */ |
|
| 1115 | - public static function get_line_item_descendants(EE_Line_Item $parent_line_item) |
|
| 1116 | - { |
|
| 1117 | - return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_line_item); |
|
| 1118 | - } |
|
| 1119 | - |
|
| 1120 | - |
|
| 1121 | - /** |
|
| 1122 | - * Gets all descendants of supplied line item that match the supplied line item type |
|
| 1123 | - * |
|
| 1124 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1125 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1126 | - * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1127 | - * @return EE_Line_Item[] |
|
| 1128 | - */ |
|
| 1129 | - public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type) |
|
| 1130 | - { |
|
| 1131 | - return self::_get_descendants_by_type_and_object_type($parent_line_item, $line_item_type, NULL); |
|
| 1132 | - } |
|
| 1133 | - |
|
| 1134 | - |
|
| 1135 | - /** |
|
| 1136 | - * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well |
|
| 1137 | - * |
|
| 1138 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1139 | - * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1140 | - * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when searching |
|
| 1141 | - * @return EE_Line_Item[] |
|
| 1142 | - */ |
|
| 1143 | - protected static function _get_descendants_by_type_and_object_type( |
|
| 1144 | - EE_Line_Item $parent_line_item, |
|
| 1145 | - $line_item_type, |
|
| 1146 | - $obj_type = null |
|
| 1147 | - ) |
|
| 1148 | - { |
|
| 1149 | - $objects = array(); |
|
| 1150 | - foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1151 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1152 | - if ( |
|
| 1153 | - $child_line_item->type() === $line_item_type |
|
| 1154 | - && ( |
|
| 1155 | - $child_line_item->OBJ_type() === $obj_type || $obj_type === null |
|
| 1156 | - ) |
|
| 1157 | - ) { |
|
| 1158 | - $objects[] = $child_line_item; |
|
| 1159 | - } else { |
|
| 1160 | - //go-through-all-its children looking for more matches |
|
| 1161 | - $objects = array_merge( |
|
| 1162 | - $objects, |
|
| 1163 | - self::_get_descendants_by_type_and_object_type( |
|
| 1164 | - $child_line_item, |
|
| 1165 | - $line_item_type, |
|
| 1166 | - $obj_type |
|
| 1167 | - ) |
|
| 1168 | - ); |
|
| 1169 | - } |
|
| 1170 | - } |
|
| 1171 | - } |
|
| 1172 | - return $objects; |
|
| 1173 | - } |
|
| 1174 | - |
|
| 1175 | - |
|
| 1176 | - /** |
|
| 1177 | - * Gets all descendants subtotals that match the supplied object type |
|
| 1178 | - * |
|
| 1179 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1180 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1181 | - * @param string $OBJ_type object type (like Event) |
|
| 1182 | - * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1183 | - * @return EE_Line_Item[] |
|
| 1184 | - */ |
|
| 1185 | - public static function get_line_items_by_object_type_and_IDs( |
|
| 1186 | - EE_Line_Item $parent_line_item, |
|
| 1187 | - $OBJ_type = '', |
|
| 1188 | - $OBJ_IDs = array() |
|
| 1189 | - ) |
|
| 1190 | - { |
|
| 1191 | - return self::_get_descendants_by_object_type_and_object_ID($parent_line_item, $OBJ_type, $OBJ_IDs); |
|
| 1192 | - } |
|
| 1193 | - |
|
| 1194 | - |
|
| 1195 | - /** |
|
| 1196 | - * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well |
|
| 1197 | - * |
|
| 1198 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1199 | - * @param string $OBJ_type object type (like Event) |
|
| 1200 | - * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1201 | - * @return EE_Line_Item[] |
|
| 1202 | - */ |
|
| 1203 | - protected static function _get_descendants_by_object_type_and_object_ID( |
|
| 1204 | - EE_Line_Item $parent_line_item, |
|
| 1205 | - $OBJ_type, |
|
| 1206 | - $OBJ_IDs |
|
| 1207 | - ) |
|
| 1208 | - { |
|
| 1209 | - $objects = array(); |
|
| 1210 | - foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1211 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1212 | - if ( |
|
| 1213 | - $child_line_item->OBJ_type() === $OBJ_type |
|
| 1214 | - && is_array($OBJ_IDs) |
|
| 1215 | - && in_array($child_line_item->OBJ_ID(), $OBJ_IDs) |
|
| 1216 | - ) { |
|
| 1217 | - $objects[] = $child_line_item; |
|
| 1218 | - } else { |
|
| 1219 | - //go-through-all-its children looking for more matches |
|
| 1220 | - $objects = array_merge( |
|
| 1221 | - $objects, |
|
| 1222 | - self::_get_descendants_by_object_type_and_object_ID( |
|
| 1223 | - $child_line_item, |
|
| 1224 | - $OBJ_type, |
|
| 1225 | - $OBJ_IDs |
|
| 1226 | - ) |
|
| 1227 | - ); |
|
| 1228 | - } |
|
| 1229 | - } |
|
| 1230 | - } |
|
| 1231 | - return $objects; |
|
| 1232 | - } |
|
| 1233 | - |
|
| 1234 | - |
|
| 1235 | - /** |
|
| 1236 | - * Uses a breadth-first-search in order to find the nearest descendant of |
|
| 1237 | - * the specified type and returns it, else NULL |
|
| 1238 | - * |
|
| 1239 | - * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1240 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1241 | - * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1242 | - * @return EE_Line_Item |
|
| 1243 | - */ |
|
| 1244 | - public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type) |
|
| 1245 | - { |
|
| 1246 | - return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type); |
|
| 1247 | - } |
|
| 1248 | - |
|
| 1249 | - |
|
| 1250 | - /** |
|
| 1251 | - * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1252 | - * having the specified LIN_code and returns it, else NULL |
|
| 1253 | - * |
|
| 1254 | - * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1255 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1256 | - * @param string $code any value used for LIN_code |
|
| 1257 | - * @return EE_Line_Item |
|
| 1258 | - */ |
|
| 1259 | - public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code) |
|
| 1260 | - { |
|
| 1261 | - return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code); |
|
| 1262 | - } |
|
| 1263 | - |
|
| 1264 | - |
|
| 1265 | - /** |
|
| 1266 | - * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1267 | - * having the specified LIN_code and returns it, else NULL |
|
| 1268 | - * |
|
| 1269 | - * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1270 | - * @param string $search_field name of EE_Line_Item property |
|
| 1271 | - * @param string $value any value stored in $search_field |
|
| 1272 | - * @return EE_Line_Item |
|
| 1273 | - */ |
|
| 1274 | - protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value) |
|
| 1275 | - { |
|
| 1276 | - foreach ($parent_line_item->children() as $child) { |
|
| 1277 | - if ($child->get($search_field) == $value) { |
|
| 1278 | - return $child; |
|
| 1279 | - } |
|
| 1280 | - } |
|
| 1281 | - foreach ($parent_line_item->children() as $child) { |
|
| 1282 | - $descendant_found = self::_get_nearest_descendant($child, $search_field, $value); |
|
| 1283 | - if ($descendant_found) { |
|
| 1284 | - return $descendant_found; |
|
| 1285 | - } |
|
| 1286 | - } |
|
| 1287 | - return NULL; |
|
| 1288 | - } |
|
| 1289 | - |
|
| 1290 | - |
|
| 1291 | - /** |
|
| 1292 | - * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction, |
|
| 1293 | - * else recursively walks up the line item tree until a parent of type total is found, |
|
| 1294 | - * |
|
| 1295 | - * @param EE_Line_Item $line_item |
|
| 1296 | - * @return \EE_Line_Item |
|
| 1297 | - * @throws \EE_Error |
|
| 1298 | - */ |
|
| 1299 | - public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item) |
|
| 1300 | - { |
|
| 1301 | - if ($line_item->TXN_ID()) { |
|
| 1302 | - $total_line_item = $line_item->transaction()->total_line_item(false); |
|
| 1303 | - if ($total_line_item instanceof EE_Line_Item) { |
|
| 1304 | - return $total_line_item; |
|
| 1305 | - } |
|
| 1306 | - } else { |
|
| 1307 | - $line_item_parent = $line_item->parent(); |
|
| 1308 | - if ($line_item_parent instanceof EE_Line_Item) { |
|
| 1309 | - if ($line_item_parent->is_total()) { |
|
| 1310 | - return $line_item_parent; |
|
| 1311 | - } |
|
| 1312 | - return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent); |
|
| 1313 | - } |
|
| 1314 | - } |
|
| 1315 | - throw new EE_Error( |
|
| 1316 | - sprintf( |
|
| 1317 | - __('A valid grand total for line item %1$d was not found.', 'event_espresso'), |
|
| 1318 | - $line_item->ID() |
|
| 1319 | - ) |
|
| 1320 | - ); |
|
| 1321 | - } |
|
| 1322 | - |
|
| 1323 | - |
|
| 1324 | - /** |
|
| 1325 | - * Prints out a representation of the line item tree |
|
| 1326 | - * |
|
| 1327 | - * @param EE_Line_Item $line_item |
|
| 1328 | - * @param int $indentation |
|
| 1329 | - * @return void |
|
| 1330 | - * @throws \EE_Error |
|
| 1331 | - */ |
|
| 1332 | - public static function visualize(EE_Line_Item $line_item, $indentation = 0) |
|
| 1333 | - { |
|
| 1334 | - echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1335 | - if (!$indentation) { |
|
| 1336 | - echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1337 | - } |
|
| 1338 | - for ($i = 0; $i < $indentation; $i++) { |
|
| 1339 | - echo ". "; |
|
| 1340 | - } |
|
| 1341 | - $breakdown = ''; |
|
| 1342 | - if ($line_item->is_line_item()) { |
|
| 1343 | - if ($line_item->is_percent()) { |
|
| 1344 | - $breakdown = "{$line_item->percent()}%"; |
|
| 1345 | - } else { |
|
| 1346 | - $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1347 | - } |
|
| 1348 | - } |
|
| 1349 | - echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}"; |
|
| 1350 | - if ($breakdown) { |
|
| 1351 | - echo " ( {$breakdown} )"; |
|
| 1352 | - } |
|
| 1353 | - if ($line_item->is_taxable()) { |
|
| 1354 | - echo " * taxable"; |
|
| 1355 | - } |
|
| 1356 | - if ($line_item->children()) { |
|
| 1357 | - foreach ($line_item->children() as $child) { |
|
| 1358 | - self::visualize($child, $indentation + 1); |
|
| 1359 | - } |
|
| 1360 | - } |
|
| 1361 | - } |
|
| 1362 | - |
|
| 1363 | - |
|
| 1364 | - /** |
|
| 1365 | - * Calculates the registration's final price, taking into account that they |
|
| 1366 | - * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes, |
|
| 1367 | - * and receive a portion of any transaction-wide discounts. |
|
| 1368 | - * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount |
|
| 1369 | - * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get |
|
| 1370 | - * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50 |
|
| 1371 | - * and brent's final price should be $5.50. |
|
| 1372 | - * |
|
| 1373 | - * In order to do this, we basically need to traverse the line item tree calculating |
|
| 1374 | - * the running totals (just as if we were recalculating the total), but when we identify |
|
| 1375 | - * regular line items, we need to keep track of their share of the grand total. |
|
| 1376 | - * Also, we need to keep track of the TAXABLE total for each ticket purchase, so |
|
| 1377 | - * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total" |
|
| 1378 | - * when there are non-taxable items; otherwise they would be the same) |
|
| 1379 | - * |
|
| 1380 | - * @param EE_Line_Item $line_item |
|
| 1381 | - * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that |
|
| 1382 | - * can be included in price calculations at this moment |
|
| 1383 | - * @return array keys are line items for tickets IDs and values are their share of the running total, |
|
| 1384 | - * plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg |
|
| 1385 | - * array( |
|
| 1386 | - * 12 => 4.3 |
|
| 1387 | - * 23 => 8.0 |
|
| 1388 | - * 'total' => 16.6, |
|
| 1389 | - * 'taxable' => array( |
|
| 1390 | - * 12 => 10, |
|
| 1391 | - * 23 => 4 |
|
| 1392 | - * ). |
|
| 1393 | - * So to find which registrations have which final price, we need to find which line item |
|
| 1394 | - * is theirs, which can be done with |
|
| 1395 | - * `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );` |
|
| 1396 | - */ |
|
| 1397 | - public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array()) |
|
| 1398 | - { |
|
| 1399 | - //init running grand total if not already |
|
| 1400 | - if (!isset($running_totals['total'])) { |
|
| 1401 | - $running_totals['total'] = 0; |
|
| 1402 | - } |
|
| 1403 | - if (!isset($running_totals['taxable'])) { |
|
| 1404 | - $running_totals['taxable'] = array('total' => 0); |
|
| 1405 | - } |
|
| 1406 | - foreach ($line_item->children() as $child_line_item) { |
|
| 1407 | - switch ($child_line_item->type()) { |
|
| 1408 | - |
|
| 1409 | - case EEM_Line_Item::type_sub_total : |
|
| 1410 | - $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities); |
|
| 1411 | - //combine arrays but preserve numeric keys |
|
| 1412 | - $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals); |
|
| 1413 | - $running_totals['total'] += $running_totals_from_subtotal['total']; |
|
| 1414 | - $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total']; |
|
| 1415 | - break; |
|
| 1416 | - |
|
| 1417 | - case EEM_Line_Item::type_tax_sub_total : |
|
| 1418 | - |
|
| 1419 | - //find how much the taxes percentage is |
|
| 1420 | - if ($child_line_item->percent() !== 0) { |
|
| 1421 | - $tax_percent_decimal = $child_line_item->percent() / 100; |
|
| 1422 | - } else { |
|
| 1423 | - $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100; |
|
| 1424 | - } |
|
| 1425 | - //and apply to all the taxable totals, and add to the pretax totals |
|
| 1426 | - foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1427 | - //"total" and "taxable" array key is an exception |
|
| 1428 | - if ($line_item_id === 'taxable') { |
|
| 1429 | - continue; |
|
| 1430 | - } |
|
| 1431 | - $taxable_total = $running_totals['taxable'][$line_item_id]; |
|
| 1432 | - $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal); |
|
| 1433 | - } |
|
| 1434 | - break; |
|
| 1435 | - |
|
| 1436 | - case EEM_Line_Item::type_line_item : |
|
| 1437 | - |
|
| 1438 | - // ticket line items or ???? |
|
| 1439 | - if ($child_line_item->OBJ_type() === 'Ticket') { |
|
| 1440 | - // kk it's a ticket |
|
| 1441 | - if (isset($running_totals[$child_line_item->ID()])) { |
|
| 1442 | - //huh? that shouldn't happen. |
|
| 1443 | - $running_totals['total'] += $child_line_item->total(); |
|
| 1444 | - } else { |
|
| 1445 | - //its not in our running totals yet. great. |
|
| 1446 | - if ($child_line_item->is_taxable()) { |
|
| 1447 | - $taxable_amount = $child_line_item->unit_price(); |
|
| 1448 | - } else { |
|
| 1449 | - $taxable_amount = 0; |
|
| 1450 | - } |
|
| 1451 | - // are we only calculating totals for some tickets? |
|
| 1452 | - if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) { |
|
| 1453 | - $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()]; |
|
| 1454 | - $running_totals[$child_line_item->ID()] = $quantity |
|
| 1455 | - ? $child_line_item->unit_price() |
|
| 1456 | - : 0; |
|
| 1457 | - $running_totals['taxable'][$child_line_item->ID()] = $quantity |
|
| 1458 | - ? $taxable_amount |
|
| 1459 | - : 0; |
|
| 1460 | - } else { |
|
| 1461 | - $quantity = $child_line_item->quantity(); |
|
| 1462 | - $running_totals[$child_line_item->ID()] = $child_line_item->unit_price(); |
|
| 1463 | - $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount; |
|
| 1464 | - } |
|
| 1465 | - $running_totals['taxable']['total'] += $taxable_amount * $quantity; |
|
| 1466 | - $running_totals['total'] += $child_line_item->unit_price() * $quantity; |
|
| 1467 | - } |
|
| 1468 | - } else { |
|
| 1469 | - // it's some other type of item added to the cart |
|
| 1470 | - // it should affect the running totals |
|
| 1471 | - // basically we want to convert it into a PERCENT modifier. Because |
|
| 1472 | - // more clearly affect all registration's final price equally |
|
| 1473 | - $line_items_percent_of_running_total = $running_totals['total'] > 0 |
|
| 1474 | - ? ($child_line_item->total() / $running_totals['total']) + 1 |
|
| 1475 | - : 1; |
|
| 1476 | - foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1477 | - //the "taxable" array key is an exception |
|
| 1478 | - if ($line_item_id === 'taxable') { |
|
| 1479 | - continue; |
|
| 1480 | - } |
|
| 1481 | - // update the running totals |
|
| 1482 | - // yes this actually even works for the running grand total! |
|
| 1483 | - $running_totals[$line_item_id] = |
|
| 1484 | - $line_items_percent_of_running_total * $this_running_total; |
|
| 1485 | - |
|
| 1486 | - if ($child_line_item->is_taxable()) { |
|
| 1487 | - $running_totals['taxable'][$line_item_id] = |
|
| 1488 | - $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id]; |
|
| 1489 | - } |
|
| 1490 | - } |
|
| 1491 | - } |
|
| 1492 | - break; |
|
| 1493 | - } |
|
| 1494 | - } |
|
| 1495 | - return $running_totals; |
|
| 1496 | - } |
|
| 1497 | - |
|
| 1498 | - |
|
| 1499 | - /** |
|
| 1500 | - * @param \EE_Line_Item $total_line_item |
|
| 1501 | - * @param \EE_Line_Item $ticket_line_item |
|
| 1502 | - * @return float | null |
|
| 1503 | - * @throws \OutOfRangeException |
|
| 1504 | - */ |
|
| 1505 | - public static function calculate_final_price_for_ticket_line_item(\EE_Line_Item $total_line_item, \EE_Line_Item $ticket_line_item) |
|
| 1506 | - { |
|
| 1507 | - static $final_prices_per_ticket_line_item = array(); |
|
| 1508 | - if (empty($final_prices_per_ticket_line_item)) { |
|
| 1509 | - $final_prices_per_ticket_line_item = \EEH_Line_Item::calculate_reg_final_prices_per_line_item( |
|
| 1510 | - $total_line_item |
|
| 1511 | - ); |
|
| 1512 | - } |
|
| 1513 | - //ok now find this new registration's final price |
|
| 1514 | - if (isset($final_prices_per_ticket_line_item[$ticket_line_item->ID()])) { |
|
| 1515 | - return $final_prices_per_ticket_line_item[$ticket_line_item->ID()]; |
|
| 1516 | - } |
|
| 1517 | - $message = sprintf( |
|
| 1518 | - __( |
|
| 1519 | - 'The final price for the ticket line item (ID:%1$d) could not be calculated.', |
|
| 1520 | - 'event_espresso' |
|
| 1521 | - ), |
|
| 1522 | - $ticket_line_item->ID() |
|
| 1523 | - ); |
|
| 1524 | - if (WP_DEBUG) { |
|
| 1525 | - $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true); |
|
| 1526 | - throw new \OutOfRangeException($message); |
|
| 1527 | - } else { |
|
| 1528 | - EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message); |
|
| 1529 | - } |
|
| 1530 | - return null; |
|
| 1531 | - } |
|
| 1532 | - |
|
| 1533 | - |
|
| 1534 | - /** |
|
| 1535 | - * Creates a duplicate of the line item tree, except only includes billable items |
|
| 1536 | - * and the portion of line items attributed to billable things |
|
| 1537 | - * |
|
| 1538 | - * @param EE_Line_Item $line_item |
|
| 1539 | - * @param EE_Registration[] $registrations |
|
| 1540 | - * @return \EE_Line_Item |
|
| 1541 | - * @throws \EE_Error |
|
| 1542 | - */ |
|
| 1543 | - public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations) |
|
| 1544 | - { |
|
| 1545 | - $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations); |
|
| 1546 | - foreach ($line_item->children() as $child_li) { |
|
| 1547 | - $copy_li->add_child_line_item(EEH_Line_Item::billable_line_item_tree($child_li, $registrations)); |
|
| 1548 | - } |
|
| 1549 | - //if this is the grand total line item, make sure the totals all add up |
|
| 1550 | - //(we could have duplicated this logic AS we copied the line items, but |
|
| 1551 | - //it seems DRYer this way) |
|
| 1552 | - if ($copy_li->type() === EEM_Line_Item::type_total) { |
|
| 1553 | - $copy_li->recalculate_total_including_taxes(); |
|
| 1554 | - } |
|
| 1555 | - return $copy_li; |
|
| 1556 | - } |
|
| 1557 | - |
|
| 1558 | - |
|
| 1559 | - /** |
|
| 1560 | - * Creates a new, unsaved line item from $line_item that factors in the |
|
| 1561 | - * number of billable registrations on $registrations. |
|
| 1562 | - * |
|
| 1563 | - * @param EE_Line_Item $line_item |
|
| 1564 | - * @return EE_Line_Item |
|
| 1565 | - * @throws \EE_Error |
|
| 1566 | - * @param EE_Registration[] $registrations |
|
| 1567 | - */ |
|
| 1568 | - public static function billable_line_item(EE_Line_Item $line_item, $registrations) |
|
| 1569 | - { |
|
| 1570 | - $new_li_fields = $line_item->model_field_array(); |
|
| 1571 | - if ($line_item->type() === EEM_Line_Item::type_line_item && |
|
| 1572 | - $line_item->OBJ_type() === 'Ticket' |
|
| 1573 | - ) { |
|
| 1574 | - $count = 0; |
|
| 1575 | - foreach ($registrations as $registration) { |
|
| 1576 | - if ($line_item->OBJ_ID() === $registration->ticket_ID() && |
|
| 1577 | - in_array($registration->status_ID(), EEM_Registration::reg_statuses_that_allow_payment()) |
|
| 1578 | - ) { |
|
| 1579 | - $count++; |
|
| 1580 | - } |
|
| 1581 | - } |
|
| 1582 | - $new_li_fields['LIN_quantity'] = $count; |
|
| 1583 | - } |
|
| 1584 | - //don't set the total. We'll leave that up to the code that calculates it |
|
| 1585 | - unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']); |
|
| 1586 | - return EE_Line_Item::new_instance($new_li_fields); |
|
| 1587 | - } |
|
| 1588 | - |
|
| 1589 | - |
|
| 1590 | - /** |
|
| 1591 | - * Returns a modified line item tree where all the subtotals which have a total of 0 |
|
| 1592 | - * are removed, and line items with a quantity of 0 |
|
| 1593 | - * |
|
| 1594 | - * @param EE_Line_Item $line_item |null |
|
| 1595 | - * @return \EE_Line_Item|null |
|
| 1596 | - * @throws \EE_Error |
|
| 1597 | - */ |
|
| 1598 | - public static function non_empty_line_items(EE_Line_Item $line_item) |
|
| 1599 | - { |
|
| 1600 | - $copied_li = EEH_Line_Item::non_empty_line_item($line_item); |
|
| 1601 | - if ($copied_li === null) { |
|
| 1602 | - return null; |
|
| 1603 | - } |
|
| 1604 | - //if this is an event subtotal, we want to only include it if it |
|
| 1605 | - //has a non-zero total and at least one ticket line item child |
|
| 1606 | - $ticket_children = 0; |
|
| 1607 | - foreach ($line_item->children() as $child_li) { |
|
| 1608 | - $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li); |
|
| 1609 | - if ($child_li_copy !== null) { |
|
| 1610 | - $copied_li->add_child_line_item($child_li_copy); |
|
| 1611 | - if ($child_li_copy->type() === EEM_Line_Item::type_line_item && |
|
| 1612 | - $child_li_copy->OBJ_type() === 'Ticket' |
|
| 1613 | - ) { |
|
| 1614 | - $ticket_children++; |
|
| 1615 | - } |
|
| 1616 | - } |
|
| 1617 | - } |
|
| 1618 | - //if this is an event subtotal with NO ticket children |
|
| 1619 | - //we basically want to ignore it |
|
| 1620 | - if ( |
|
| 1621 | - $ticket_children === 0 |
|
| 1622 | - && $line_item->type() === EEM_Line_Item::type_sub_total |
|
| 1623 | - && $line_item->OBJ_type() === 'Event' |
|
| 1624 | - && $line_item->total() === 0 |
|
| 1625 | - ) { |
|
| 1626 | - return null; |
|
| 1627 | - } |
|
| 1628 | - return $copied_li; |
|
| 1629 | - } |
|
| 1630 | - |
|
| 1631 | - |
|
| 1632 | - /** |
|
| 1633 | - * Creates a new, unsaved line item, but if it's a ticket line item |
|
| 1634 | - * with a total of 0, or a subtotal of 0, returns null instead |
|
| 1635 | - * |
|
| 1636 | - * @param EE_Line_Item $line_item |
|
| 1637 | - * @return EE_Line_Item |
|
| 1638 | - * @throws \EE_Error |
|
| 1639 | - */ |
|
| 1640 | - public static function non_empty_line_item(EE_Line_Item $line_item) |
|
| 1641 | - { |
|
| 1642 | - if ($line_item->type() === EEM_Line_Item::type_line_item && |
|
| 1643 | - $line_item->OBJ_type() === 'Ticket' && |
|
| 1644 | - $line_item->quantity() === 0 |
|
| 1645 | - ) { |
|
| 1646 | - return null; |
|
| 1647 | - } |
|
| 1648 | - $new_li_fields = $line_item->model_field_array(); |
|
| 1649 | - //don't set the total. We'll leave that up to the code that calculates it |
|
| 1650 | - unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']); |
|
| 1651 | - return EE_Line_Item::new_instance($new_li_fields); |
|
| 1652 | - } |
|
| 1653 | - |
|
| 1654 | - |
|
| 1655 | - |
|
| 1656 | - /**************************************** @DEPRECATED METHODS *************************************** */ |
|
| 1657 | - /** |
|
| 1658 | - * @deprecated |
|
| 1659 | - * @param EE_Line_Item $total_line_item |
|
| 1660 | - * @return \EE_Line_Item |
|
| 1661 | - * @throws \EE_Error |
|
| 1662 | - */ |
|
| 1663 | - public static function get_items_subtotal(EE_Line_Item $total_line_item) |
|
| 1664 | - { |
|
| 1665 | - EE_Error::doing_it_wrong('EEH_Line_Item::get_items_subtotal()', __('Method replaced with EEH_Line_Item::get_pre_tax_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1666 | - return self::get_pre_tax_subtotal($total_line_item); |
|
| 1667 | - } |
|
| 1668 | - |
|
| 1669 | - |
|
| 1670 | - /** |
|
| 1671 | - * @deprecated |
|
| 1672 | - * @param EE_Transaction $transaction |
|
| 1673 | - * @return \EE_Line_Item |
|
| 1674 | - * @throws \EE_Error |
|
| 1675 | - */ |
|
| 1676 | - public static function create_default_total_line_item($transaction = NULL) |
|
| 1677 | - { |
|
| 1678 | - EE_Error::doing_it_wrong('EEH_Line_Item::create_default_total_line_item()', __('Method replaced with EEH_Line_Item::create_total_line_item()', 'event_espresso'), '4.6.0'); |
|
| 1679 | - return self::create_total_line_item($transaction); |
|
| 1680 | - } |
|
| 1681 | - |
|
| 1682 | - |
|
| 1683 | - /** |
|
| 1684 | - * @deprecated |
|
| 1685 | - * @param EE_Line_Item $total_line_item |
|
| 1686 | - * @param EE_Transaction $transaction |
|
| 1687 | - * @return \EE_Line_Item |
|
| 1688 | - * @throws \EE_Error |
|
| 1689 | - */ |
|
| 1690 | - public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 1691 | - { |
|
| 1692 | - EE_Error::doing_it_wrong('EEH_Line_Item::create_default_tickets_subtotal()', __('Method replaced with EEH_Line_Item::create_pre_tax_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1693 | - return self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 1694 | - } |
|
| 1695 | - |
|
| 1696 | - |
|
| 1697 | - /** |
|
| 1698 | - * @deprecated |
|
| 1699 | - * @param EE_Line_Item $total_line_item |
|
| 1700 | - * @param EE_Transaction $transaction |
|
| 1701 | - * @return \EE_Line_Item |
|
| 1702 | - * @throws \EE_Error |
|
| 1703 | - */ |
|
| 1704 | - public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 1705 | - { |
|
| 1706 | - EE_Error::doing_it_wrong('EEH_Line_Item::create_default_taxes_subtotal()', __('Method replaced with EEH_Line_Item::create_taxes_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1707 | - return self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 1708 | - } |
|
| 1709 | - |
|
| 1710 | - |
|
| 1711 | - /** |
|
| 1712 | - * @deprecated |
|
| 1713 | - * @param EE_Line_Item $total_line_item |
|
| 1714 | - * @param EE_Transaction $transaction |
|
| 1715 | - * @return \EE_Line_Item |
|
| 1716 | - * @throws \EE_Error |
|
| 1717 | - */ |
|
| 1718 | - public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 1719 | - { |
|
| 1720 | - EE_Error::doing_it_wrong('EEH_Line_Item::create_default_event_subtotal()', __('Method replaced with EEH_Line_Item::create_event_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1721 | - return self::create_event_subtotal($total_line_item, $transaction); |
|
| 1722 | - } |
|
| 26 | + //other functions: cancel ticket purchase |
|
| 27 | + //delete ticket purchase |
|
| 28 | + //add promotion |
|
| 29 | + |
|
| 30 | + |
|
| 31 | + /** |
|
| 32 | + * Adds a simple item (unrelated to any other model object) to the provided PARENT line item. |
|
| 33 | + * Does NOT automatically re-calculate the line item totals or update the related transaction. |
|
| 34 | + * You should call recalculate_total_including_taxes() on the grant total line item after this |
|
| 35 | + * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 36 | + * to keep the registration final prices in-sync with the transaction's total. |
|
| 37 | + * |
|
| 38 | + * @param EE_Line_Item $parent_line_item |
|
| 39 | + * @param string $name |
|
| 40 | + * @param float $unit_price |
|
| 41 | + * @param string $description |
|
| 42 | + * @param int $quantity |
|
| 43 | + * @param boolean $taxable |
|
| 44 | + * @param boolean $code if set to a value, ensures there is only one line item with that code |
|
| 45 | + * @return boolean success |
|
| 46 | + * @throws \EE_Error |
|
| 47 | + */ |
|
| 48 | + public static function add_unrelated_item(EE_Line_Item $parent_line_item, $name, $unit_price, $description = '', $quantity = 1, $taxable = FALSE, $code = NULL) |
|
| 49 | + { |
|
| 50 | + $items_subtotal = self::get_pre_tax_subtotal($parent_line_item); |
|
| 51 | + $line_item = EE_Line_Item::new_instance(array( |
|
| 52 | + 'LIN_name' => $name, |
|
| 53 | + 'LIN_desc' => $description, |
|
| 54 | + 'LIN_unit_price' => $unit_price, |
|
| 55 | + 'LIN_quantity' => $quantity, |
|
| 56 | + 'LIN_percent' => null, |
|
| 57 | + 'LIN_is_taxable' => $taxable, |
|
| 58 | + 'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0, |
|
| 59 | + 'LIN_total' => (float)$unit_price * (int)$quantity, |
|
| 60 | + 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 61 | + 'LIN_code' => $code, |
|
| 62 | + )); |
|
| 63 | + $line_item = apply_filters( |
|
| 64 | + 'FHEE__EEH_Line_Item__add_unrelated_item__line_item', |
|
| 65 | + $line_item, |
|
| 66 | + $parent_line_item |
|
| 67 | + ); |
|
| 68 | + return self::add_item($parent_line_item, $line_item); |
|
| 69 | + } |
|
| 70 | + |
|
| 71 | + |
|
| 72 | + /** |
|
| 73 | + * Adds a simple item ( unrelated to any other model object) to the total line item, |
|
| 74 | + * in the correct spot in the line item tree. Automatically |
|
| 75 | + * re-calculates the line item totals and updates the related transaction. But |
|
| 76 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 77 | + * should probably change because of this). |
|
| 78 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 79 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 80 | + * |
|
| 81 | + * @param EE_Line_Item $parent_line_item |
|
| 82 | + * @param string $name |
|
| 83 | + * @param float $percentage_amount |
|
| 84 | + * @param string $description |
|
| 85 | + * @param boolean $taxable |
|
| 86 | + * @return boolean success |
|
| 87 | + * @throws \EE_Error |
|
| 88 | + */ |
|
| 89 | + public static function add_percentage_based_item(EE_Line_Item $parent_line_item, $name, $percentage_amount, $description = '', $taxable = FALSE) |
|
| 90 | + { |
|
| 91 | + $line_item = EE_Line_Item::new_instance(array( |
|
| 92 | + 'LIN_name' => $name, |
|
| 93 | + 'LIN_desc' => $description, |
|
| 94 | + 'LIN_unit_price' => 0, |
|
| 95 | + 'LIN_percent' => $percentage_amount, |
|
| 96 | + 'LIN_quantity' => 1, |
|
| 97 | + 'LIN_is_taxable' => $taxable, |
|
| 98 | + 'LIN_total' => (float)($percentage_amount * ($parent_line_item->total() / 100)), |
|
| 99 | + 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 100 | + 'LIN_parent' => $parent_line_item->ID() |
|
| 101 | + )); |
|
| 102 | + $line_item = apply_filters( |
|
| 103 | + 'FHEE__EEH_Line_Item__add_percentage_based_item__line_item', |
|
| 104 | + $line_item |
|
| 105 | + ); |
|
| 106 | + return $parent_line_item->add_child_line_item($line_item, false); |
|
| 107 | + } |
|
| 108 | + |
|
| 109 | + |
|
| 110 | + /** |
|
| 111 | + * Returns the new line item created by adding a purchase of the ticket |
|
| 112 | + * ensures that ticket line item is saved, and that cart total has been recalculated. |
|
| 113 | + * If this ticket has already been purchased, just increments its count. |
|
| 114 | + * Automatically re-calculates the line item totals and updates the related transaction. But |
|
| 115 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 116 | + * should probably change because of this). |
|
| 117 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 118 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 119 | + * |
|
| 120 | + * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total |
|
| 121 | + * @param EE_Ticket $ticket |
|
| 122 | + * @param int $qty |
|
| 123 | + * @return \EE_Line_Item |
|
| 124 | + * @throws \EE_Error |
|
| 125 | + */ |
|
| 126 | + public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 127 | + { |
|
| 128 | + if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) { |
|
| 129 | + throw new EE_Error(sprintf(__('A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', 'event_espresso'), $ticket->ID(), $total_line_item->ID())); |
|
| 130 | + } |
|
| 131 | + // either increment the qty for an existing ticket |
|
| 132 | + $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty); |
|
| 133 | + // or add a new one |
|
| 134 | + if (!$line_item instanceof EE_Line_Item) { |
|
| 135 | + $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty); |
|
| 136 | + } |
|
| 137 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 138 | + return $line_item; |
|
| 139 | + } |
|
| 140 | + |
|
| 141 | + |
|
| 142 | + /** |
|
| 143 | + * Returns the new line item created by adding a purchase of the ticket |
|
| 144 | + * @param \EE_Line_Item $total_line_item |
|
| 145 | + * @param EE_Ticket $ticket |
|
| 146 | + * @param int $qty |
|
| 147 | + * @return \EE_Line_Item |
|
| 148 | + * @throws \EE_Error |
|
| 149 | + */ |
|
| 150 | + public static function increment_ticket_qty_if_already_in_cart(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 151 | + { |
|
| 152 | + $line_item = null; |
|
| 153 | + if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) { |
|
| 154 | + $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item); |
|
| 155 | + foreach ((array)$ticket_line_items as $ticket_line_item) { |
|
| 156 | + if ( |
|
| 157 | + $ticket_line_item instanceof EE_Line_Item |
|
| 158 | + && (int)$ticket_line_item->OBJ_ID() === (int)$ticket->ID() |
|
| 159 | + ) { |
|
| 160 | + $line_item = $ticket_line_item; |
|
| 161 | + break; |
|
| 162 | + } |
|
| 163 | + } |
|
| 164 | + } |
|
| 165 | + if ($line_item instanceof EE_Line_Item) { |
|
| 166 | + EEH_Line_Item::increment_quantity($line_item, $qty); |
|
| 167 | + return $line_item; |
|
| 168 | + } |
|
| 169 | + return null; |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + |
|
| 173 | + /** |
|
| 174 | + * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 175 | + * Does NOT save or recalculate other line items totals |
|
| 176 | + * |
|
| 177 | + * @param EE_Line_Item $line_item |
|
| 178 | + * @param int $qty |
|
| 179 | + * @return void |
|
| 180 | + * @throws \EE_Error |
|
| 181 | + */ |
|
| 182 | + public static function increment_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 183 | + { |
|
| 184 | + if (!$line_item->is_percent()) { |
|
| 185 | + $qty += $line_item->quantity(); |
|
| 186 | + $line_item->set_quantity($qty); |
|
| 187 | + $line_item->set_total($line_item->unit_price() * $qty); |
|
| 188 | + $line_item->save(); |
|
| 189 | + } |
|
| 190 | + foreach ($line_item->children() as $child) { |
|
| 191 | + if ($child->is_sub_line_item()) { |
|
| 192 | + EEH_Line_Item::update_quantity($child, $qty); |
|
| 193 | + } |
|
| 194 | + } |
|
| 195 | + } |
|
| 196 | + |
|
| 197 | + |
|
| 198 | + /** |
|
| 199 | + * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 200 | + * Does NOT save or recalculate other line items totals |
|
| 201 | + * |
|
| 202 | + * @param EE_Line_Item $line_item |
|
| 203 | + * @param int $qty |
|
| 204 | + * @return void |
|
| 205 | + * @throws \EE_Error |
|
| 206 | + */ |
|
| 207 | + public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 208 | + { |
|
| 209 | + if (!$line_item->is_percent()) { |
|
| 210 | + $qty = $line_item->quantity() - $qty; |
|
| 211 | + $qty = max($qty, 0); |
|
| 212 | + $line_item->set_quantity($qty); |
|
| 213 | + $line_item->set_total($line_item->unit_price() * $qty); |
|
| 214 | + $line_item->save(); |
|
| 215 | + } |
|
| 216 | + foreach ($line_item->children() as $child) { |
|
| 217 | + if ($child->is_sub_line_item()) { |
|
| 218 | + EEH_Line_Item::update_quantity($child, $qty); |
|
| 219 | + } |
|
| 220 | + } |
|
| 221 | + } |
|
| 222 | + |
|
| 223 | + |
|
| 224 | + /** |
|
| 225 | + * Updates the line item and its children's quantities to the specified number. |
|
| 226 | + * Does NOT save them or recalculate totals. |
|
| 227 | + * |
|
| 228 | + * @param EE_Line_Item $line_item |
|
| 229 | + * @param int $new_quantity |
|
| 230 | + * @throws \EE_Error |
|
| 231 | + */ |
|
| 232 | + public static function update_quantity(EE_Line_Item $line_item, $new_quantity) |
|
| 233 | + { |
|
| 234 | + if (!$line_item->is_percent()) { |
|
| 235 | + $line_item->set_quantity($new_quantity); |
|
| 236 | + $line_item->set_total($line_item->unit_price() * $new_quantity); |
|
| 237 | + $line_item->save(); |
|
| 238 | + } |
|
| 239 | + foreach ($line_item->children() as $child) { |
|
| 240 | + if ($child->is_sub_line_item()) { |
|
| 241 | + EEH_Line_Item::update_quantity($child, $new_quantity); |
|
| 242 | + } |
|
| 243 | + } |
|
| 244 | + } |
|
| 245 | + |
|
| 246 | + |
|
| 247 | + /** |
|
| 248 | + * Returns the new line item created by adding a purchase of the ticket |
|
| 249 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 250 | + * @param EE_Ticket $ticket |
|
| 251 | + * @param int $qty |
|
| 252 | + * @return \EE_Line_Item |
|
| 253 | + * @throws \EE_Error |
|
| 254 | + */ |
|
| 255 | + public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 256 | + { |
|
| 257 | + $datetimes = $ticket->datetimes(); |
|
| 258 | + $first_datetime = reset($datetimes); |
|
| 259 | + if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) { |
|
| 260 | + $first_datetime_name = $first_datetime->event()->name(); |
|
| 261 | + } else { |
|
| 262 | + $first_datetime_name = __('Event', 'event_espresso'); |
|
| 263 | + } |
|
| 264 | + $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name); |
|
| 265 | + // get event subtotal line |
|
| 266 | + $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket); |
|
| 267 | + // add $ticket to cart |
|
| 268 | + $line_item = EE_Line_Item::new_instance(array( |
|
| 269 | + 'LIN_name' => $ticket->name(), |
|
| 270 | + 'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event, |
|
| 271 | + 'LIN_unit_price' => $ticket->price(), |
|
| 272 | + 'LIN_quantity' => $qty, |
|
| 273 | + 'LIN_is_taxable' => $ticket->taxable(), |
|
| 274 | + 'LIN_order' => count($events_sub_total->children()), |
|
| 275 | + 'LIN_total' => $ticket->price() * $qty, |
|
| 276 | + 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 277 | + 'OBJ_ID' => $ticket->ID(), |
|
| 278 | + 'OBJ_type' => 'Ticket' |
|
| 279 | + )); |
|
| 280 | + $line_item = apply_filters( |
|
| 281 | + 'FHEE__EEH_Line_Item__create_ticket_line_item__line_item', |
|
| 282 | + $line_item |
|
| 283 | + ); |
|
| 284 | + $events_sub_total->add_child_line_item($line_item); |
|
| 285 | + //now add the sub-line items |
|
| 286 | + $running_total_for_ticket = 0; |
|
| 287 | + foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) { |
|
| 288 | + $sign = $price->is_discount() ? -1 : 1; |
|
| 289 | + $price_total = $price->is_percent() |
|
| 290 | + ? $running_total_for_ticket * $price->amount() / 100 |
|
| 291 | + : $price->amount() * $qty; |
|
| 292 | + $sub_line_item = EE_Line_Item::new_instance(array( |
|
| 293 | + 'LIN_name' => $price->name(), |
|
| 294 | + 'LIN_desc' => $price->desc(), |
|
| 295 | + 'LIN_quantity' => $price->is_percent() ? null : $qty, |
|
| 296 | + 'LIN_is_taxable' => false, |
|
| 297 | + 'LIN_order' => $price->order(), |
|
| 298 | + 'LIN_total' => $sign * $price_total, |
|
| 299 | + 'LIN_type' => EEM_Line_Item::type_sub_line_item, |
|
| 300 | + 'OBJ_ID' => $price->ID(), |
|
| 301 | + 'OBJ_type' => 'Price' |
|
| 302 | + )); |
|
| 303 | + $sub_line_item = apply_filters( |
|
| 304 | + 'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item', |
|
| 305 | + $sub_line_item |
|
| 306 | + ); |
|
| 307 | + if ($price->is_percent()) { |
|
| 308 | + $sub_line_item->set_percent($sign * $price->amount()); |
|
| 309 | + } else { |
|
| 310 | + $sub_line_item->set_unit_price($sign * $price->amount()); |
|
| 311 | + } |
|
| 312 | + $running_total_for_ticket += $price_total; |
|
| 313 | + $line_item->add_child_line_item($sub_line_item); |
|
| 314 | + } |
|
| 315 | + return $line_item; |
|
| 316 | + } |
|
| 317 | + |
|
| 318 | + |
|
| 319 | + /** |
|
| 320 | + * Adds the specified item under the pre-tax-sub-total line item. Automatically |
|
| 321 | + * re-calculates the line item totals and updates the related transaction. But |
|
| 322 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 323 | + * should probably change because of this). |
|
| 324 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 325 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 326 | + * |
|
| 327 | + * @param EE_Line_Item $total_line_item |
|
| 328 | + * @param EE_Line_Item $item to be added |
|
| 329 | + * @return boolean |
|
| 330 | + * @throws \EE_Error |
|
| 331 | + */ |
|
| 332 | + public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item) |
|
| 333 | + { |
|
| 334 | + $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item); |
|
| 335 | + if ($pre_tax_subtotal instanceof EE_Line_Item) { |
|
| 336 | + $success = $pre_tax_subtotal->add_child_line_item($item); |
|
| 337 | + } else { |
|
| 338 | + return FALSE; |
|
| 339 | + } |
|
| 340 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 341 | + return $success; |
|
| 342 | + } |
|
| 343 | + |
|
| 344 | + |
|
| 345 | + /** |
|
| 346 | + * cancels an existing ticket line item, |
|
| 347 | + * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item. |
|
| 348 | + * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 349 | + * |
|
| 350 | + * @param EE_Line_Item $ticket_line_item |
|
| 351 | + * @param int $qty |
|
| 352 | + * @return bool success |
|
| 353 | + * @throws \EE_Error |
|
| 354 | + */ |
|
| 355 | + public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 356 | + { |
|
| 357 | + // validate incoming line_item |
|
| 358 | + if ($ticket_line_item->OBJ_type() !== 'Ticket') { |
|
| 359 | + throw new EE_Error( |
|
| 360 | + sprintf( |
|
| 361 | + __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'), |
|
| 362 | + $ticket_line_item->type() |
|
| 363 | + ) |
|
| 364 | + ); |
|
| 365 | + } |
|
| 366 | + if ($ticket_line_item->quantity() < $qty) { |
|
| 367 | + throw new EE_Error( |
|
| 368 | + sprintf( |
|
| 369 | + __('Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', 'event_espresso'), |
|
| 370 | + $qty, |
|
| 371 | + $ticket_line_item->quantity() |
|
| 372 | + ) |
|
| 373 | + ); |
|
| 374 | + } |
|
| 375 | + // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this |
|
| 376 | + $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty); |
|
| 377 | + foreach ($ticket_line_item->children() as $child_line_item) { |
|
| 378 | + if ( |
|
| 379 | + $child_line_item->is_sub_line_item() |
|
| 380 | + && !$child_line_item->is_percent() |
|
| 381 | + && !$child_line_item->is_cancellation() |
|
| 382 | + ) { |
|
| 383 | + $child_line_item->set_quantity($child_line_item->quantity() - $qty); |
|
| 384 | + } |
|
| 385 | + } |
|
| 386 | + // get cancellation sub line item |
|
| 387 | + $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 388 | + $ticket_line_item, |
|
| 389 | + EEM_Line_Item::type_cancellation |
|
| 390 | + ); |
|
| 391 | + $cancellation_line_item = reset($cancellation_line_item); |
|
| 392 | + // verify that this ticket was indeed previously cancelled |
|
| 393 | + if ($cancellation_line_item instanceof EE_Line_Item) { |
|
| 394 | + // increment cancelled quantity |
|
| 395 | + $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty); |
|
| 396 | + } else { |
|
| 397 | + // create cancellation sub line item |
|
| 398 | + $cancellation_line_item = EE_Line_Item::new_instance(array( |
|
| 399 | + 'LIN_name' => __('Cancellation', 'event_espresso'), |
|
| 400 | + 'LIN_desc' => sprintf( |
|
| 401 | + _x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'), |
|
| 402 | + $ticket_line_item->name(), |
|
| 403 | + current_time(get_option('date_format') . ' ' . get_option('time_format')) |
|
| 404 | + ), |
|
| 405 | + 'LIN_unit_price' => 0, // $ticket_line_item->unit_price() |
|
| 406 | + 'LIN_quantity' => $qty, |
|
| 407 | + 'LIN_is_taxable' => $ticket_line_item->is_taxable(), |
|
| 408 | + 'LIN_order' => count($ticket_line_item->children()), |
|
| 409 | + 'LIN_total' => 0, // $ticket_line_item->unit_price() |
|
| 410 | + 'LIN_type' => EEM_Line_Item::type_cancellation, |
|
| 411 | + )); |
|
| 412 | + $ticket_line_item->add_child_line_item($cancellation_line_item); |
|
| 413 | + } |
|
| 414 | + if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 415 | + // decrement parent line item quantity |
|
| 416 | + $event_line_item = $ticket_line_item->parent(); |
|
| 417 | + if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') { |
|
| 418 | + $event_line_item->set_quantity($event_line_item->quantity() - $qty); |
|
| 419 | + $event_line_item->save(); |
|
| 420 | + } |
|
| 421 | + EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 422 | + return true; |
|
| 423 | + } |
|
| 424 | + return false; |
|
| 425 | + } |
|
| 426 | + |
|
| 427 | + |
|
| 428 | + /** |
|
| 429 | + * reinstates (un-cancels?) a previously canceled ticket line item, |
|
| 430 | + * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item. |
|
| 431 | + * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 432 | + * |
|
| 433 | + * @param EE_Line_Item $ticket_line_item |
|
| 434 | + * @param int $qty |
|
| 435 | + * @return bool success |
|
| 436 | + * @throws \EE_Error |
|
| 437 | + */ |
|
| 438 | + public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 439 | + { |
|
| 440 | + // validate incoming line_item |
|
| 441 | + if ($ticket_line_item->OBJ_type() !== 'Ticket') { |
|
| 442 | + throw new EE_Error( |
|
| 443 | + sprintf( |
|
| 444 | + __('The supplied line item must have an Object Type of "Ticket", not %1$s.', 'event_espresso'), |
|
| 445 | + $ticket_line_item->type() |
|
| 446 | + ) |
|
| 447 | + ); |
|
| 448 | + } |
|
| 449 | + // get cancellation sub line item |
|
| 450 | + $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 451 | + $ticket_line_item, |
|
| 452 | + EEM_Line_Item::type_cancellation |
|
| 453 | + ); |
|
| 454 | + $cancellation_line_item = reset($cancellation_line_item); |
|
| 455 | + // verify that this ticket was indeed previously cancelled |
|
| 456 | + if (!$cancellation_line_item instanceof EE_Line_Item) { |
|
| 457 | + return false; |
|
| 458 | + } |
|
| 459 | + if ($cancellation_line_item->quantity() > $qty) { |
|
| 460 | + // decrement cancelled quantity |
|
| 461 | + $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 462 | + } else if ($cancellation_line_item->quantity() == $qty) { |
|
| 463 | + // decrement cancelled quantity in case anyone still has the object kicking around |
|
| 464 | + $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 465 | + // delete because quantity will end up as 0 |
|
| 466 | + $cancellation_line_item->delete(); |
|
| 467 | + // and attempt to destroy the object, |
|
| 468 | + // even though PHP won't actually destroy it until it needs the memory |
|
| 469 | + unset($cancellation_line_item); |
|
| 470 | + } else { |
|
| 471 | + // what ?!?! negative quantity ?!?! |
|
| 472 | + throw new EE_Error( |
|
| 473 | + sprintf( |
|
| 474 | + __('Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.', |
|
| 475 | + 'event_espresso'), |
|
| 476 | + $qty, |
|
| 477 | + $cancellation_line_item->quantity() |
|
| 478 | + ) |
|
| 479 | + ); |
|
| 480 | + } |
|
| 481 | + // increment ticket quantity |
|
| 482 | + $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty); |
|
| 483 | + if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 484 | + // increment parent line item quantity |
|
| 485 | + $event_line_item = $ticket_line_item->parent(); |
|
| 486 | + if ($event_line_item instanceof EE_Line_Item && $event_line_item->OBJ_type() === 'Event') { |
|
| 487 | + $event_line_item->set_quantity($event_line_item->quantity() + $qty); |
|
| 488 | + } |
|
| 489 | + EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 490 | + return true; |
|
| 491 | + } |
|
| 492 | + return false; |
|
| 493 | + } |
|
| 494 | + |
|
| 495 | + |
|
| 496 | + /** |
|
| 497 | + * calls EEH_Line_Item::find_transaction_grand_total_for_line_item() |
|
| 498 | + * then EE_Line_Item::recalculate_total_including_taxes() on the result |
|
| 499 | + * |
|
| 500 | + * @param EE_Line_Item $line_item |
|
| 501 | + * @return \EE_Line_Item |
|
| 502 | + */ |
|
| 503 | + public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item) |
|
| 504 | + { |
|
| 505 | + $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item); |
|
| 506 | + return $grand_total_line_item->recalculate_total_including_taxes(); |
|
| 507 | + } |
|
| 508 | + |
|
| 509 | + |
|
| 510 | + /** |
|
| 511 | + * Gets the line item which contains the subtotal of all the items |
|
| 512 | + * |
|
| 513 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 514 | + * @return \EE_Line_Item |
|
| 515 | + * @throws \EE_Error |
|
| 516 | + */ |
|
| 517 | + public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item) |
|
| 518 | + { |
|
| 519 | + $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal'); |
|
| 520 | + return $pre_tax_subtotal instanceof EE_Line_Item |
|
| 521 | + ? $pre_tax_subtotal |
|
| 522 | + : self::create_pre_tax_subtotal($total_line_item); |
|
| 523 | + } |
|
| 524 | + |
|
| 525 | + |
|
| 526 | + /** |
|
| 527 | + * Gets the line item for the taxes subtotal |
|
| 528 | + * |
|
| 529 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 530 | + * @return \EE_Line_Item |
|
| 531 | + * @throws \EE_Error |
|
| 532 | + */ |
|
| 533 | + public static function get_taxes_subtotal(EE_Line_Item $total_line_item) |
|
| 534 | + { |
|
| 535 | + $taxes = $total_line_item->get_child_line_item('taxes'); |
|
| 536 | + return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item); |
|
| 537 | + } |
|
| 538 | + |
|
| 539 | + |
|
| 540 | + /** |
|
| 541 | + * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object |
|
| 542 | + * |
|
| 543 | + * @param EE_Line_Item $line_item |
|
| 544 | + * @param EE_Transaction $transaction |
|
| 545 | + * @return void |
|
| 546 | + * @throws \EE_Error |
|
| 547 | + */ |
|
| 548 | + public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = NULL) |
|
| 549 | + { |
|
| 550 | + if ($transaction) { |
|
| 551 | + /** @type EEM_Transaction $EEM_Transaction */ |
|
| 552 | + $EEM_Transaction = EE_Registry::instance()->load_model('Transaction'); |
|
| 553 | + $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction); |
|
| 554 | + $line_item->set_TXN_ID($TXN_ID); |
|
| 555 | + } |
|
| 556 | + } |
|
| 557 | + |
|
| 558 | + |
|
| 559 | + /** |
|
| 560 | + * Creates a new default total line item for the transaction, |
|
| 561 | + * and its tickets subtotal and taxes subtotal line items (and adds the |
|
| 562 | + * existing taxes as children of the taxes subtotal line item) |
|
| 563 | + * |
|
| 564 | + * @param EE_Transaction $transaction |
|
| 565 | + * @return \EE_Line_Item of type total |
|
| 566 | + * @throws \EE_Error |
|
| 567 | + */ |
|
| 568 | + public static function create_total_line_item($transaction = NULL) |
|
| 569 | + { |
|
| 570 | + $total_line_item = EE_Line_Item::new_instance(array( |
|
| 571 | + 'LIN_code' => 'total', |
|
| 572 | + 'LIN_name' => __('Grand Total', 'event_espresso'), |
|
| 573 | + 'LIN_type' => EEM_Line_Item::type_total, |
|
| 574 | + 'OBJ_type' => 'Transaction' |
|
| 575 | + )); |
|
| 576 | + $total_line_item = apply_filters( |
|
| 577 | + 'FHEE__EEH_Line_Item__create_total_line_item__total_line_item', |
|
| 578 | + $total_line_item |
|
| 579 | + ); |
|
| 580 | + self::set_TXN_ID($total_line_item, $transaction); |
|
| 581 | + self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 582 | + self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 583 | + return $total_line_item; |
|
| 584 | + } |
|
| 585 | + |
|
| 586 | + |
|
| 587 | + /** |
|
| 588 | + * Creates a default items subtotal line item |
|
| 589 | + * |
|
| 590 | + * @param EE_Line_Item $total_line_item |
|
| 591 | + * @param EE_Transaction $transaction |
|
| 592 | + * @return EE_Line_Item |
|
| 593 | + * @throws \EE_Error |
|
| 594 | + */ |
|
| 595 | + protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 596 | + { |
|
| 597 | + $pre_tax_line_item = EE_Line_Item::new_instance(array( |
|
| 598 | + 'LIN_code' => 'pre-tax-subtotal', |
|
| 599 | + 'LIN_name' => __('Pre-Tax Subtotal', 'event_espresso'), |
|
| 600 | + 'LIN_type' => EEM_Line_Item::type_sub_total |
|
| 601 | + )); |
|
| 602 | + $pre_tax_line_item = apply_filters( |
|
| 603 | + 'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item', |
|
| 604 | + $pre_tax_line_item |
|
| 605 | + ); |
|
| 606 | + self::set_TXN_ID($pre_tax_line_item, $transaction); |
|
| 607 | + $total_line_item->add_child_line_item($pre_tax_line_item); |
|
| 608 | + self::create_event_subtotal($pre_tax_line_item, $transaction); |
|
| 609 | + return $pre_tax_line_item; |
|
| 610 | + } |
|
| 611 | + |
|
| 612 | + |
|
| 613 | + /** |
|
| 614 | + * Creates a line item for the taxes subtotal and finds all the tax prices |
|
| 615 | + * and applies taxes to it |
|
| 616 | + * |
|
| 617 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 618 | + * @param EE_Transaction $transaction |
|
| 619 | + * @return EE_Line_Item |
|
| 620 | + * @throws \EE_Error |
|
| 621 | + */ |
|
| 622 | + protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 623 | + { |
|
| 624 | + $tax_line_item = EE_Line_Item::new_instance(array( |
|
| 625 | + 'LIN_code' => 'taxes', |
|
| 626 | + 'LIN_name' => __('Taxes', 'event_espresso'), |
|
| 627 | + 'LIN_type' => EEM_Line_Item::type_tax_sub_total, |
|
| 628 | + 'LIN_order' => 1000,//this should always come last |
|
| 629 | + )); |
|
| 630 | + $tax_line_item = apply_filters( |
|
| 631 | + 'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item', |
|
| 632 | + $tax_line_item |
|
| 633 | + ); |
|
| 634 | + self::set_TXN_ID($tax_line_item, $transaction); |
|
| 635 | + $total_line_item->add_child_line_item($tax_line_item); |
|
| 636 | + //and lastly, add the actual taxes |
|
| 637 | + self::apply_taxes($total_line_item); |
|
| 638 | + return $tax_line_item; |
|
| 639 | + } |
|
| 640 | + |
|
| 641 | + |
|
| 642 | + /** |
|
| 643 | + * Creates a default items subtotal line item |
|
| 644 | + * |
|
| 645 | + * @param EE_Line_Item $pre_tax_line_item |
|
| 646 | + * @param EE_Transaction $transaction |
|
| 647 | + * @param EE_Event $event |
|
| 648 | + * @return EE_Line_Item |
|
| 649 | + * @throws \EE_Error |
|
| 650 | + */ |
|
| 651 | + public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = NULL, $event = NULL) |
|
| 652 | + { |
|
| 653 | + $event_line_item = EE_Line_Item::new_instance(array( |
|
| 654 | + 'LIN_code' => self::get_event_code($event), |
|
| 655 | + 'LIN_name' => self::get_event_name($event), |
|
| 656 | + 'LIN_desc' => self::get_event_desc($event), |
|
| 657 | + 'LIN_type' => EEM_Line_Item::type_sub_total, |
|
| 658 | + 'OBJ_type' => 'Event', |
|
| 659 | + 'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0 |
|
| 660 | + )); |
|
| 661 | + $event_line_item = apply_filters( |
|
| 662 | + 'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item', |
|
| 663 | + $event_line_item |
|
| 664 | + ); |
|
| 665 | + self::set_TXN_ID($event_line_item, $transaction); |
|
| 666 | + $pre_tax_line_item->add_child_line_item($event_line_item); |
|
| 667 | + return $event_line_item; |
|
| 668 | + } |
|
| 669 | + |
|
| 670 | + |
|
| 671 | + /** |
|
| 672 | + * Gets what the event ticket's code SHOULD be |
|
| 673 | + * |
|
| 674 | + * @param EE_Event $event |
|
| 675 | + * @return string |
|
| 676 | + * @throws \EE_Error |
|
| 677 | + */ |
|
| 678 | + public static function get_event_code($event) |
|
| 679 | + { |
|
| 680 | + return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 681 | + } |
|
| 682 | + |
|
| 683 | + /** |
|
| 684 | + * Gets the event name |
|
| 685 | + * @param EE_Event $event |
|
| 686 | + * @return string |
|
| 687 | + */ |
|
| 688 | + public static function get_event_name($event) |
|
| 689 | + { |
|
| 690 | + return $event instanceof EE_Event ? $event->name() : __('Event', 'event_espresso'); |
|
| 691 | + } |
|
| 692 | + |
|
| 693 | + /** |
|
| 694 | + * Gets the event excerpt |
|
| 695 | + * @param EE_Event $event |
|
| 696 | + * @return string |
|
| 697 | + */ |
|
| 698 | + public static function get_event_desc($event) |
|
| 699 | + { |
|
| 700 | + return $event instanceof EE_Event ? $event->short_description() : ''; |
|
| 701 | + } |
|
| 702 | + |
|
| 703 | + /** |
|
| 704 | + * Given the grand total line item and a ticket, finds the event sub-total |
|
| 705 | + * line item the ticket's purchase should be added onto |
|
| 706 | + * |
|
| 707 | + * @access public |
|
| 708 | + * @param EE_Line_Item $grand_total the grand total line item |
|
| 709 | + * @param EE_Ticket $ticket |
|
| 710 | + * @throws \EE_Error |
|
| 711 | + * @return EE_Line_Item |
|
| 712 | + */ |
|
| 713 | + public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket) |
|
| 714 | + { |
|
| 715 | + $first_datetime = $ticket->first_datetime(); |
|
| 716 | + if (!$first_datetime instanceof EE_Datetime) { |
|
| 717 | + throw new EE_Error( |
|
| 718 | + sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID()) |
|
| 719 | + ); |
|
| 720 | + } |
|
| 721 | + $event = $first_datetime->event(); |
|
| 722 | + if (!$event instanceof EE_Event) { |
|
| 723 | + throw new EE_Error( |
|
| 724 | + sprintf( |
|
| 725 | + __('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'), |
|
| 726 | + $ticket->ID() |
|
| 727 | + ) |
|
| 728 | + ); |
|
| 729 | + } |
|
| 730 | + $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event); |
|
| 731 | + if (!$events_sub_total instanceof EE_Line_Item) { |
|
| 732 | + throw new EE_Error( |
|
| 733 | + sprintf( |
|
| 734 | + __('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'), |
|
| 735 | + $ticket->ID(), |
|
| 736 | + $grand_total->ID() |
|
| 737 | + ) |
|
| 738 | + ); |
|
| 739 | + } |
|
| 740 | + return $events_sub_total; |
|
| 741 | + } |
|
| 742 | + |
|
| 743 | + |
|
| 744 | + /** |
|
| 745 | + * Gets the event line item |
|
| 746 | + * |
|
| 747 | + * @param EE_Line_Item $grand_total |
|
| 748 | + * @param EE_Event $event |
|
| 749 | + * @return EE_Line_Item for the event subtotal which is a child of $grand_total |
|
| 750 | + * @throws \EE_Error |
|
| 751 | + */ |
|
| 752 | + public static function get_event_line_item(EE_Line_Item $grand_total, $event) |
|
| 753 | + { |
|
| 754 | + /** @type EE_Event $event */ |
|
| 755 | + $event = EEM_Event::instance()->ensure_is_obj($event, true); |
|
| 756 | + $event_line_item = NULL; |
|
| 757 | + $found = false; |
|
| 758 | + foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) { |
|
| 759 | + // default event subtotal, we should only ever find this the first time this method is called |
|
| 760 | + if (!$event_line_item->OBJ_ID()) { |
|
| 761 | + // let's use this! but first... set the event details |
|
| 762 | + EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 763 | + $found = true; |
|
| 764 | + break; |
|
| 765 | + } else if ($event_line_item->OBJ_ID() === $event->ID()) { |
|
| 766 | + // found existing line item for this event in the cart, so break out of loop and use this one |
|
| 767 | + $found = true; |
|
| 768 | + break; |
|
| 769 | + } |
|
| 770 | + } |
|
| 771 | + if (!$found) { |
|
| 772 | + //there is no event sub-total yet, so add it |
|
| 773 | + $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total); |
|
| 774 | + // create a new "event" subtotal below that |
|
| 775 | + $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event); |
|
| 776 | + // and set the event details |
|
| 777 | + EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 778 | + } |
|
| 779 | + return $event_line_item; |
|
| 780 | + } |
|
| 781 | + |
|
| 782 | + |
|
| 783 | + /** |
|
| 784 | + * Creates a default items subtotal line item |
|
| 785 | + * |
|
| 786 | + * @param EE_Line_Item $event_line_item |
|
| 787 | + * @param EE_Event $event |
|
| 788 | + * @param EE_Transaction $transaction |
|
| 789 | + * @return EE_Line_Item |
|
| 790 | + * @throws \EE_Error |
|
| 791 | + */ |
|
| 792 | + public static function set_event_subtotal_details( |
|
| 793 | + EE_Line_Item $event_line_item, |
|
| 794 | + EE_Event $event, |
|
| 795 | + $transaction = null |
|
| 796 | + ) |
|
| 797 | + { |
|
| 798 | + if ($event instanceof EE_Event) { |
|
| 799 | + $event_line_item->set_code(self::get_event_code($event)); |
|
| 800 | + $event_line_item->set_name(self::get_event_name($event)); |
|
| 801 | + $event_line_item->set_desc(self::get_event_desc($event)); |
|
| 802 | + $event_line_item->set_OBJ_ID($event->ID()); |
|
| 803 | + } |
|
| 804 | + self::set_TXN_ID($event_line_item, $transaction); |
|
| 805 | + } |
|
| 806 | + |
|
| 807 | + |
|
| 808 | + /** |
|
| 809 | + * Finds what taxes should apply, adds them as tax line items under the taxes sub-total, |
|
| 810 | + * and recalculates the taxes sub-total and the grand total. Resets the taxes, so |
|
| 811 | + * any old taxes are removed |
|
| 812 | + * |
|
| 813 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 814 | + * @throws \EE_Error |
|
| 815 | + */ |
|
| 816 | + public static function apply_taxes(EE_Line_Item $total_line_item) |
|
| 817 | + { |
|
| 818 | + /** @type EEM_Price $EEM_Price */ |
|
| 819 | + $EEM_Price = EE_Registry::instance()->load_model('Price'); |
|
| 820 | + // get array of taxes via Price Model |
|
| 821 | + $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes(); |
|
| 822 | + ksort($ordered_taxes); |
|
| 823 | + $taxes_line_item = self::get_taxes_subtotal($total_line_item); |
|
| 824 | + //just to be safe, remove its old tax line items |
|
| 825 | + $taxes_line_item->delete_children_line_items(); |
|
| 826 | + //loop thru taxes |
|
| 827 | + foreach ($ordered_taxes as $order => $taxes) { |
|
| 828 | + foreach ($taxes as $tax) { |
|
| 829 | + if ($tax instanceof EE_Price) { |
|
| 830 | + $tax_line_item = EE_Line_Item::new_instance( |
|
| 831 | + array( |
|
| 832 | + 'LIN_name' => $tax->name(), |
|
| 833 | + 'LIN_desc' => $tax->desc(), |
|
| 834 | + 'LIN_percent' => $tax->amount(), |
|
| 835 | + 'LIN_is_taxable' => false, |
|
| 836 | + 'LIN_order' => $order, |
|
| 837 | + 'LIN_total' => 0, |
|
| 838 | + 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 839 | + 'OBJ_type' => 'Price', |
|
| 840 | + 'OBJ_ID' => $tax->ID() |
|
| 841 | + ) |
|
| 842 | + ); |
|
| 843 | + $tax_line_item = apply_filters( |
|
| 844 | + 'FHEE__EEH_Line_Item__apply_taxes__tax_line_item', |
|
| 845 | + $tax_line_item |
|
| 846 | + ); |
|
| 847 | + $taxes_line_item->add_child_line_item($tax_line_item); |
|
| 848 | + } |
|
| 849 | + } |
|
| 850 | + } |
|
| 851 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 852 | + } |
|
| 853 | + |
|
| 854 | + |
|
| 855 | + /** |
|
| 856 | + * Ensures that taxes have been applied to the order, if not applies them. |
|
| 857 | + * Returns the total amount of tax |
|
| 858 | + * |
|
| 859 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 860 | + * @return float |
|
| 861 | + * @throws \EE_Error |
|
| 862 | + */ |
|
| 863 | + public static function ensure_taxes_applied($total_line_item) |
|
| 864 | + { |
|
| 865 | + $taxes_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 866 | + if (!$taxes_subtotal->children()) { |
|
| 867 | + self::apply_taxes($total_line_item); |
|
| 868 | + } |
|
| 869 | + return $taxes_subtotal->total(); |
|
| 870 | + } |
|
| 871 | + |
|
| 872 | + |
|
| 873 | + /** |
|
| 874 | + * Deletes ALL children of the passed line item |
|
| 875 | + * |
|
| 876 | + * @param EE_Line_Item $parent_line_item |
|
| 877 | + * @return bool |
|
| 878 | + * @throws \EE_Error |
|
| 879 | + */ |
|
| 880 | + public static function delete_all_child_items(EE_Line_Item $parent_line_item) |
|
| 881 | + { |
|
| 882 | + $deleted = 0; |
|
| 883 | + foreach ($parent_line_item->children() as $child_line_item) { |
|
| 884 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 885 | + $deleted += EEH_Line_Item::delete_all_child_items($child_line_item); |
|
| 886 | + if ($child_line_item->ID()) { |
|
| 887 | + $child_line_item->delete(); |
|
| 888 | + unset($child_line_item); |
|
| 889 | + } else { |
|
| 890 | + $parent_line_item->delete_child_line_item($child_line_item->code()); |
|
| 891 | + } |
|
| 892 | + $deleted++; |
|
| 893 | + } |
|
| 894 | + } |
|
| 895 | + return $deleted; |
|
| 896 | + } |
|
| 897 | + |
|
| 898 | + |
|
| 899 | + /** |
|
| 900 | + * Deletes the line items as indicated by the line item code(s) provided, |
|
| 901 | + * regardless of where they're found in the line item tree. Automatically |
|
| 902 | + * re-calculates the line item totals and updates the related transaction. But |
|
| 903 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 904 | + * should probably change because of this). |
|
| 905 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 906 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 907 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 908 | + * @param array|bool|string $line_item_codes |
|
| 909 | + * @return int number of items successfully removed |
|
| 910 | + */ |
|
| 911 | + public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = FALSE) |
|
| 912 | + { |
|
| 913 | + |
|
| 914 | + if ($total_line_item->type() !== EEM_Line_Item::type_total) { |
|
| 915 | + EE_Error::doing_it_wrong( |
|
| 916 | + 'EEH_Line_Item::delete_items', |
|
| 917 | + __( |
|
| 918 | + 'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly', |
|
| 919 | + 'event_espresso' |
|
| 920 | + ), |
|
| 921 | + '4.6.18' |
|
| 922 | + ); |
|
| 923 | + } |
|
| 924 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 925 | + |
|
| 926 | + // check if only a single line_item_id was passed |
|
| 927 | + if (!empty($line_item_codes) && !is_array($line_item_codes)) { |
|
| 928 | + // place single line_item_id in an array to appear as multiple line_item_ids |
|
| 929 | + $line_item_codes = array($line_item_codes); |
|
| 930 | + } |
|
| 931 | + $removals = 0; |
|
| 932 | + // cycle thru line_item_ids |
|
| 933 | + foreach ($line_item_codes as $line_item_id) { |
|
| 934 | + $removals += $total_line_item->delete_child_line_item($line_item_id); |
|
| 935 | + } |
|
| 936 | + |
|
| 937 | + if ($removals > 0) { |
|
| 938 | + $total_line_item->recalculate_taxes_and_tax_total(); |
|
| 939 | + return $removals; |
|
| 940 | + } else { |
|
| 941 | + return FALSE; |
|
| 942 | + } |
|
| 943 | + } |
|
| 944 | + |
|
| 945 | + |
|
| 946 | + /** |
|
| 947 | + * Overwrites the previous tax by clearing out the old taxes, and creates a new |
|
| 948 | + * tax and updates the total line item accordingly |
|
| 949 | + * |
|
| 950 | + * @param EE_Line_Item $total_line_item |
|
| 951 | + * @param float $amount |
|
| 952 | + * @param string $name |
|
| 953 | + * @param string $description |
|
| 954 | + * @param string $code |
|
| 955 | + * @param boolean $add_to_existing_line_item |
|
| 956 | + * if true, and a duplicate line item with the same code is found, |
|
| 957 | + * $amount will be added onto it; otherwise will simply set the taxes to match $amount |
|
| 958 | + * @return EE_Line_Item the new tax line item created |
|
| 959 | + * @throws \EE_Error |
|
| 960 | + */ |
|
| 961 | + public static function set_total_tax_to( |
|
| 962 | + EE_Line_Item $total_line_item, |
|
| 963 | + $amount, |
|
| 964 | + $name = null, |
|
| 965 | + $description = null, |
|
| 966 | + $code = null, |
|
| 967 | + $add_to_existing_line_item = false |
|
| 968 | + ) |
|
| 969 | + { |
|
| 970 | + $tax_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 971 | + $taxable_total = $total_line_item->taxable_total(); |
|
| 972 | + |
|
| 973 | + if ($add_to_existing_line_item) { |
|
| 974 | + $new_tax = $tax_subtotal->get_child_line_item($code); |
|
| 975 | + EEM_Line_Item::instance()->delete( |
|
| 976 | + array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID())) |
|
| 977 | + ); |
|
| 978 | + } else { |
|
| 979 | + $new_tax = null; |
|
| 980 | + $tax_subtotal->delete_children_line_items(); |
|
| 981 | + } |
|
| 982 | + if ($new_tax) { |
|
| 983 | + $new_tax->set_total($new_tax->total() + $amount); |
|
| 984 | + $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0); |
|
| 985 | + } else { |
|
| 986 | + //no existing tax item. Create it |
|
| 987 | + $new_tax = EE_Line_Item::new_instance(array( |
|
| 988 | + 'TXN_ID' => $total_line_item->TXN_ID(), |
|
| 989 | + 'LIN_name' => $name ? $name : __('Tax', 'event_espresso'), |
|
| 990 | + 'LIN_desc' => $description ? $description : '', |
|
| 991 | + 'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0, |
|
| 992 | + 'LIN_total' => $amount, |
|
| 993 | + 'LIN_parent' => $tax_subtotal->ID(), |
|
| 994 | + 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 995 | + 'LIN_code' => $code |
|
| 996 | + )); |
|
| 997 | + } |
|
| 998 | + |
|
| 999 | + $new_tax = apply_filters( |
|
| 1000 | + 'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal', |
|
| 1001 | + $new_tax, |
|
| 1002 | + $total_line_item |
|
| 1003 | + ); |
|
| 1004 | + $new_tax->save(); |
|
| 1005 | + $tax_subtotal->set_total($new_tax->total()); |
|
| 1006 | + $tax_subtotal->save(); |
|
| 1007 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 1008 | + return $new_tax; |
|
| 1009 | + } |
|
| 1010 | + |
|
| 1011 | + |
|
| 1012 | + /** |
|
| 1013 | + * Makes all the line items which are children of $line_item taxable (or not). |
|
| 1014 | + * Does NOT save the line items |
|
| 1015 | + * @param EE_Line_Item $line_item |
|
| 1016 | + * @param string $code_substring_for_whitelist if this string is part of the line item's code |
|
| 1017 | + * it will be whitelisted (ie, except from becoming taxable) |
|
| 1018 | + * @param boolean $taxable |
|
| 1019 | + */ |
|
| 1020 | + public static function set_line_items_taxable( |
|
| 1021 | + EE_Line_Item $line_item, |
|
| 1022 | + $taxable = true, |
|
| 1023 | + $code_substring_for_whitelist = null |
|
| 1024 | + ) |
|
| 1025 | + { |
|
| 1026 | + $whitelisted = false; |
|
| 1027 | + if ($code_substring_for_whitelist !== null) { |
|
| 1028 | + $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false; |
|
| 1029 | + } |
|
| 1030 | + if (!$whitelisted && $line_item->is_line_item()) { |
|
| 1031 | + $line_item->set_is_taxable($taxable); |
|
| 1032 | + } |
|
| 1033 | + foreach ($line_item->children() as $child_line_item) { |
|
| 1034 | + EEH_Line_Item::set_line_items_taxable($child_line_item, $taxable, $code_substring_for_whitelist); |
|
| 1035 | + } |
|
| 1036 | + } |
|
| 1037 | + |
|
| 1038 | + |
|
| 1039 | + /** |
|
| 1040 | + * Gets all descendants that are event subtotals |
|
| 1041 | + * |
|
| 1042 | + * @uses EEH_Line_Item::get_subtotals_of_object_type() |
|
| 1043 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1044 | + * @return EE_Line_Item[] |
|
| 1045 | + */ |
|
| 1046 | + public static function get_event_subtotals(EE_Line_Item $parent_line_item) |
|
| 1047 | + { |
|
| 1048 | + return self::get_subtotals_of_object_type($parent_line_item, 'Event'); |
|
| 1049 | + } |
|
| 1050 | + |
|
| 1051 | + |
|
| 1052 | + /** |
|
| 1053 | + * Gets all descendants subtotals that match the supplied object type |
|
| 1054 | + * |
|
| 1055 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1056 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1057 | + * @param string $obj_type |
|
| 1058 | + * @return EE_Line_Item[] |
|
| 1059 | + */ |
|
| 1060 | + public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1061 | + { |
|
| 1062 | + return self::_get_descendants_by_type_and_object_type( |
|
| 1063 | + $parent_line_item, |
|
| 1064 | + EEM_Line_Item::type_sub_total, |
|
| 1065 | + $obj_type |
|
| 1066 | + ); |
|
| 1067 | + } |
|
| 1068 | + |
|
| 1069 | + |
|
| 1070 | + /** |
|
| 1071 | + * Gets all descendants that are tickets |
|
| 1072 | + * |
|
| 1073 | + * @uses EEH_Line_Item::get_line_items_of_object_type() |
|
| 1074 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1075 | + * @return EE_Line_Item[] |
|
| 1076 | + */ |
|
| 1077 | + public static function get_ticket_line_items(EE_Line_Item $parent_line_item) |
|
| 1078 | + { |
|
| 1079 | + return self::get_line_items_of_object_type($parent_line_item, 'Ticket'); |
|
| 1080 | + } |
|
| 1081 | + |
|
| 1082 | + |
|
| 1083 | + /** |
|
| 1084 | + * Gets all descendants subtotals that match the supplied object type |
|
| 1085 | + * |
|
| 1086 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1087 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1088 | + * @param string $obj_type |
|
| 1089 | + * @return EE_Line_Item[] |
|
| 1090 | + */ |
|
| 1091 | + public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1092 | + { |
|
| 1093 | + return self::_get_descendants_by_type_and_object_type($parent_line_item, EEM_Line_Item::type_line_item, $obj_type); |
|
| 1094 | + } |
|
| 1095 | + |
|
| 1096 | + |
|
| 1097 | + /** |
|
| 1098 | + * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax' |
|
| 1099 | + * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1100 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1101 | + * @return EE_Line_Item[] |
|
| 1102 | + */ |
|
| 1103 | + public static function get_tax_descendants(EE_Line_Item $parent_line_item) |
|
| 1104 | + { |
|
| 1105 | + return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_tax); |
|
| 1106 | + } |
|
| 1107 | + |
|
| 1108 | + |
|
| 1109 | + /** |
|
| 1110 | + * Gets all the real items purchased which are children of this item |
|
| 1111 | + * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1112 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1113 | + * @return EE_Line_Item[] |
|
| 1114 | + */ |
|
| 1115 | + public static function get_line_item_descendants(EE_Line_Item $parent_line_item) |
|
| 1116 | + { |
|
| 1117 | + return EEH_Line_Item::get_descendants_of_type($parent_line_item, EEM_Line_Item::type_line_item); |
|
| 1118 | + } |
|
| 1119 | + |
|
| 1120 | + |
|
| 1121 | + /** |
|
| 1122 | + * Gets all descendants of supplied line item that match the supplied line item type |
|
| 1123 | + * |
|
| 1124 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1125 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1126 | + * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1127 | + * @return EE_Line_Item[] |
|
| 1128 | + */ |
|
| 1129 | + public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type) |
|
| 1130 | + { |
|
| 1131 | + return self::_get_descendants_by_type_and_object_type($parent_line_item, $line_item_type, NULL); |
|
| 1132 | + } |
|
| 1133 | + |
|
| 1134 | + |
|
| 1135 | + /** |
|
| 1136 | + * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well |
|
| 1137 | + * |
|
| 1138 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1139 | + * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1140 | + * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when searching |
|
| 1141 | + * @return EE_Line_Item[] |
|
| 1142 | + */ |
|
| 1143 | + protected static function _get_descendants_by_type_and_object_type( |
|
| 1144 | + EE_Line_Item $parent_line_item, |
|
| 1145 | + $line_item_type, |
|
| 1146 | + $obj_type = null |
|
| 1147 | + ) |
|
| 1148 | + { |
|
| 1149 | + $objects = array(); |
|
| 1150 | + foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1151 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1152 | + if ( |
|
| 1153 | + $child_line_item->type() === $line_item_type |
|
| 1154 | + && ( |
|
| 1155 | + $child_line_item->OBJ_type() === $obj_type || $obj_type === null |
|
| 1156 | + ) |
|
| 1157 | + ) { |
|
| 1158 | + $objects[] = $child_line_item; |
|
| 1159 | + } else { |
|
| 1160 | + //go-through-all-its children looking for more matches |
|
| 1161 | + $objects = array_merge( |
|
| 1162 | + $objects, |
|
| 1163 | + self::_get_descendants_by_type_and_object_type( |
|
| 1164 | + $child_line_item, |
|
| 1165 | + $line_item_type, |
|
| 1166 | + $obj_type |
|
| 1167 | + ) |
|
| 1168 | + ); |
|
| 1169 | + } |
|
| 1170 | + } |
|
| 1171 | + } |
|
| 1172 | + return $objects; |
|
| 1173 | + } |
|
| 1174 | + |
|
| 1175 | + |
|
| 1176 | + /** |
|
| 1177 | + * Gets all descendants subtotals that match the supplied object type |
|
| 1178 | + * |
|
| 1179 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1180 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1181 | + * @param string $OBJ_type object type (like Event) |
|
| 1182 | + * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1183 | + * @return EE_Line_Item[] |
|
| 1184 | + */ |
|
| 1185 | + public static function get_line_items_by_object_type_and_IDs( |
|
| 1186 | + EE_Line_Item $parent_line_item, |
|
| 1187 | + $OBJ_type = '', |
|
| 1188 | + $OBJ_IDs = array() |
|
| 1189 | + ) |
|
| 1190 | + { |
|
| 1191 | + return self::_get_descendants_by_object_type_and_object_ID($parent_line_item, $OBJ_type, $OBJ_IDs); |
|
| 1192 | + } |
|
| 1193 | + |
|
| 1194 | + |
|
| 1195 | + /** |
|
| 1196 | + * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type as well |
|
| 1197 | + * |
|
| 1198 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1199 | + * @param string $OBJ_type object type (like Event) |
|
| 1200 | + * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1201 | + * @return EE_Line_Item[] |
|
| 1202 | + */ |
|
| 1203 | + protected static function _get_descendants_by_object_type_and_object_ID( |
|
| 1204 | + EE_Line_Item $parent_line_item, |
|
| 1205 | + $OBJ_type, |
|
| 1206 | + $OBJ_IDs |
|
| 1207 | + ) |
|
| 1208 | + { |
|
| 1209 | + $objects = array(); |
|
| 1210 | + foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1211 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1212 | + if ( |
|
| 1213 | + $child_line_item->OBJ_type() === $OBJ_type |
|
| 1214 | + && is_array($OBJ_IDs) |
|
| 1215 | + && in_array($child_line_item->OBJ_ID(), $OBJ_IDs) |
|
| 1216 | + ) { |
|
| 1217 | + $objects[] = $child_line_item; |
|
| 1218 | + } else { |
|
| 1219 | + //go-through-all-its children looking for more matches |
|
| 1220 | + $objects = array_merge( |
|
| 1221 | + $objects, |
|
| 1222 | + self::_get_descendants_by_object_type_and_object_ID( |
|
| 1223 | + $child_line_item, |
|
| 1224 | + $OBJ_type, |
|
| 1225 | + $OBJ_IDs |
|
| 1226 | + ) |
|
| 1227 | + ); |
|
| 1228 | + } |
|
| 1229 | + } |
|
| 1230 | + } |
|
| 1231 | + return $objects; |
|
| 1232 | + } |
|
| 1233 | + |
|
| 1234 | + |
|
| 1235 | + /** |
|
| 1236 | + * Uses a breadth-first-search in order to find the nearest descendant of |
|
| 1237 | + * the specified type and returns it, else NULL |
|
| 1238 | + * |
|
| 1239 | + * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1240 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1241 | + * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1242 | + * @return EE_Line_Item |
|
| 1243 | + */ |
|
| 1244 | + public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type) |
|
| 1245 | + { |
|
| 1246 | + return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type); |
|
| 1247 | + } |
|
| 1248 | + |
|
| 1249 | + |
|
| 1250 | + /** |
|
| 1251 | + * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1252 | + * having the specified LIN_code and returns it, else NULL |
|
| 1253 | + * |
|
| 1254 | + * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1255 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1256 | + * @param string $code any value used for LIN_code |
|
| 1257 | + * @return EE_Line_Item |
|
| 1258 | + */ |
|
| 1259 | + public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code) |
|
| 1260 | + { |
|
| 1261 | + return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code); |
|
| 1262 | + } |
|
| 1263 | + |
|
| 1264 | + |
|
| 1265 | + /** |
|
| 1266 | + * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1267 | + * having the specified LIN_code and returns it, else NULL |
|
| 1268 | + * |
|
| 1269 | + * @param \EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1270 | + * @param string $search_field name of EE_Line_Item property |
|
| 1271 | + * @param string $value any value stored in $search_field |
|
| 1272 | + * @return EE_Line_Item |
|
| 1273 | + */ |
|
| 1274 | + protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value) |
|
| 1275 | + { |
|
| 1276 | + foreach ($parent_line_item->children() as $child) { |
|
| 1277 | + if ($child->get($search_field) == $value) { |
|
| 1278 | + return $child; |
|
| 1279 | + } |
|
| 1280 | + } |
|
| 1281 | + foreach ($parent_line_item->children() as $child) { |
|
| 1282 | + $descendant_found = self::_get_nearest_descendant($child, $search_field, $value); |
|
| 1283 | + if ($descendant_found) { |
|
| 1284 | + return $descendant_found; |
|
| 1285 | + } |
|
| 1286 | + } |
|
| 1287 | + return NULL; |
|
| 1288 | + } |
|
| 1289 | + |
|
| 1290 | + |
|
| 1291 | + /** |
|
| 1292 | + * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction, |
|
| 1293 | + * else recursively walks up the line item tree until a parent of type total is found, |
|
| 1294 | + * |
|
| 1295 | + * @param EE_Line_Item $line_item |
|
| 1296 | + * @return \EE_Line_Item |
|
| 1297 | + * @throws \EE_Error |
|
| 1298 | + */ |
|
| 1299 | + public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item) |
|
| 1300 | + { |
|
| 1301 | + if ($line_item->TXN_ID()) { |
|
| 1302 | + $total_line_item = $line_item->transaction()->total_line_item(false); |
|
| 1303 | + if ($total_line_item instanceof EE_Line_Item) { |
|
| 1304 | + return $total_line_item; |
|
| 1305 | + } |
|
| 1306 | + } else { |
|
| 1307 | + $line_item_parent = $line_item->parent(); |
|
| 1308 | + if ($line_item_parent instanceof EE_Line_Item) { |
|
| 1309 | + if ($line_item_parent->is_total()) { |
|
| 1310 | + return $line_item_parent; |
|
| 1311 | + } |
|
| 1312 | + return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent); |
|
| 1313 | + } |
|
| 1314 | + } |
|
| 1315 | + throw new EE_Error( |
|
| 1316 | + sprintf( |
|
| 1317 | + __('A valid grand total for line item %1$d was not found.', 'event_espresso'), |
|
| 1318 | + $line_item->ID() |
|
| 1319 | + ) |
|
| 1320 | + ); |
|
| 1321 | + } |
|
| 1322 | + |
|
| 1323 | + |
|
| 1324 | + /** |
|
| 1325 | + * Prints out a representation of the line item tree |
|
| 1326 | + * |
|
| 1327 | + * @param EE_Line_Item $line_item |
|
| 1328 | + * @param int $indentation |
|
| 1329 | + * @return void |
|
| 1330 | + * @throws \EE_Error |
|
| 1331 | + */ |
|
| 1332 | + public static function visualize(EE_Line_Item $line_item, $indentation = 0) |
|
| 1333 | + { |
|
| 1334 | + echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1335 | + if (!$indentation) { |
|
| 1336 | + echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1337 | + } |
|
| 1338 | + for ($i = 0; $i < $indentation; $i++) { |
|
| 1339 | + echo ". "; |
|
| 1340 | + } |
|
| 1341 | + $breakdown = ''; |
|
| 1342 | + if ($line_item->is_line_item()) { |
|
| 1343 | + if ($line_item->is_percent()) { |
|
| 1344 | + $breakdown = "{$line_item->percent()}%"; |
|
| 1345 | + } else { |
|
| 1346 | + $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1347 | + } |
|
| 1348 | + } |
|
| 1349 | + echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}"; |
|
| 1350 | + if ($breakdown) { |
|
| 1351 | + echo " ( {$breakdown} )"; |
|
| 1352 | + } |
|
| 1353 | + if ($line_item->is_taxable()) { |
|
| 1354 | + echo " * taxable"; |
|
| 1355 | + } |
|
| 1356 | + if ($line_item->children()) { |
|
| 1357 | + foreach ($line_item->children() as $child) { |
|
| 1358 | + self::visualize($child, $indentation + 1); |
|
| 1359 | + } |
|
| 1360 | + } |
|
| 1361 | + } |
|
| 1362 | + |
|
| 1363 | + |
|
| 1364 | + /** |
|
| 1365 | + * Calculates the registration's final price, taking into account that they |
|
| 1366 | + * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes, |
|
| 1367 | + * and receive a portion of any transaction-wide discounts. |
|
| 1368 | + * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount |
|
| 1369 | + * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get |
|
| 1370 | + * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50 |
|
| 1371 | + * and brent's final price should be $5.50. |
|
| 1372 | + * |
|
| 1373 | + * In order to do this, we basically need to traverse the line item tree calculating |
|
| 1374 | + * the running totals (just as if we were recalculating the total), but when we identify |
|
| 1375 | + * regular line items, we need to keep track of their share of the grand total. |
|
| 1376 | + * Also, we need to keep track of the TAXABLE total for each ticket purchase, so |
|
| 1377 | + * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total" |
|
| 1378 | + * when there are non-taxable items; otherwise they would be the same) |
|
| 1379 | + * |
|
| 1380 | + * @param EE_Line_Item $line_item |
|
| 1381 | + * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that |
|
| 1382 | + * can be included in price calculations at this moment |
|
| 1383 | + * @return array keys are line items for tickets IDs and values are their share of the running total, |
|
| 1384 | + * plus the key 'total', and 'taxable' which also has keys of all the ticket IDs. Eg |
|
| 1385 | + * array( |
|
| 1386 | + * 12 => 4.3 |
|
| 1387 | + * 23 => 8.0 |
|
| 1388 | + * 'total' => 16.6, |
|
| 1389 | + * 'taxable' => array( |
|
| 1390 | + * 12 => 10, |
|
| 1391 | + * 23 => 4 |
|
| 1392 | + * ). |
|
| 1393 | + * So to find which registrations have which final price, we need to find which line item |
|
| 1394 | + * is theirs, which can be done with |
|
| 1395 | + * `EEM_Line_Item::instance()->get_line_item_for_registration( $registration );` |
|
| 1396 | + */ |
|
| 1397 | + public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array()) |
|
| 1398 | + { |
|
| 1399 | + //init running grand total if not already |
|
| 1400 | + if (!isset($running_totals['total'])) { |
|
| 1401 | + $running_totals['total'] = 0; |
|
| 1402 | + } |
|
| 1403 | + if (!isset($running_totals['taxable'])) { |
|
| 1404 | + $running_totals['taxable'] = array('total' => 0); |
|
| 1405 | + } |
|
| 1406 | + foreach ($line_item->children() as $child_line_item) { |
|
| 1407 | + switch ($child_line_item->type()) { |
|
| 1408 | + |
|
| 1409 | + case EEM_Line_Item::type_sub_total : |
|
| 1410 | + $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item($child_line_item, $billable_ticket_quantities); |
|
| 1411 | + //combine arrays but preserve numeric keys |
|
| 1412 | + $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals); |
|
| 1413 | + $running_totals['total'] += $running_totals_from_subtotal['total']; |
|
| 1414 | + $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total']; |
|
| 1415 | + break; |
|
| 1416 | + |
|
| 1417 | + case EEM_Line_Item::type_tax_sub_total : |
|
| 1418 | + |
|
| 1419 | + //find how much the taxes percentage is |
|
| 1420 | + if ($child_line_item->percent() !== 0) { |
|
| 1421 | + $tax_percent_decimal = $child_line_item->percent() / 100; |
|
| 1422 | + } else { |
|
| 1423 | + $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100; |
|
| 1424 | + } |
|
| 1425 | + //and apply to all the taxable totals, and add to the pretax totals |
|
| 1426 | + foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1427 | + //"total" and "taxable" array key is an exception |
|
| 1428 | + if ($line_item_id === 'taxable') { |
|
| 1429 | + continue; |
|
| 1430 | + } |
|
| 1431 | + $taxable_total = $running_totals['taxable'][$line_item_id]; |
|
| 1432 | + $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal); |
|
| 1433 | + } |
|
| 1434 | + break; |
|
| 1435 | + |
|
| 1436 | + case EEM_Line_Item::type_line_item : |
|
| 1437 | + |
|
| 1438 | + // ticket line items or ???? |
|
| 1439 | + if ($child_line_item->OBJ_type() === 'Ticket') { |
|
| 1440 | + // kk it's a ticket |
|
| 1441 | + if (isset($running_totals[$child_line_item->ID()])) { |
|
| 1442 | + //huh? that shouldn't happen. |
|
| 1443 | + $running_totals['total'] += $child_line_item->total(); |
|
| 1444 | + } else { |
|
| 1445 | + //its not in our running totals yet. great. |
|
| 1446 | + if ($child_line_item->is_taxable()) { |
|
| 1447 | + $taxable_amount = $child_line_item->unit_price(); |
|
| 1448 | + } else { |
|
| 1449 | + $taxable_amount = 0; |
|
| 1450 | + } |
|
| 1451 | + // are we only calculating totals for some tickets? |
|
| 1452 | + if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) { |
|
| 1453 | + $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()]; |
|
| 1454 | + $running_totals[$child_line_item->ID()] = $quantity |
|
| 1455 | + ? $child_line_item->unit_price() |
|
| 1456 | + : 0; |
|
| 1457 | + $running_totals['taxable'][$child_line_item->ID()] = $quantity |
|
| 1458 | + ? $taxable_amount |
|
| 1459 | + : 0; |
|
| 1460 | + } else { |
|
| 1461 | + $quantity = $child_line_item->quantity(); |
|
| 1462 | + $running_totals[$child_line_item->ID()] = $child_line_item->unit_price(); |
|
| 1463 | + $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount; |
|
| 1464 | + } |
|
| 1465 | + $running_totals['taxable']['total'] += $taxable_amount * $quantity; |
|
| 1466 | + $running_totals['total'] += $child_line_item->unit_price() * $quantity; |
|
| 1467 | + } |
|
| 1468 | + } else { |
|
| 1469 | + // it's some other type of item added to the cart |
|
| 1470 | + // it should affect the running totals |
|
| 1471 | + // basically we want to convert it into a PERCENT modifier. Because |
|
| 1472 | + // more clearly affect all registration's final price equally |
|
| 1473 | + $line_items_percent_of_running_total = $running_totals['total'] > 0 |
|
| 1474 | + ? ($child_line_item->total() / $running_totals['total']) + 1 |
|
| 1475 | + : 1; |
|
| 1476 | + foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1477 | + //the "taxable" array key is an exception |
|
| 1478 | + if ($line_item_id === 'taxable') { |
|
| 1479 | + continue; |
|
| 1480 | + } |
|
| 1481 | + // update the running totals |
|
| 1482 | + // yes this actually even works for the running grand total! |
|
| 1483 | + $running_totals[$line_item_id] = |
|
| 1484 | + $line_items_percent_of_running_total * $this_running_total; |
|
| 1485 | + |
|
| 1486 | + if ($child_line_item->is_taxable()) { |
|
| 1487 | + $running_totals['taxable'][$line_item_id] = |
|
| 1488 | + $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id]; |
|
| 1489 | + } |
|
| 1490 | + } |
|
| 1491 | + } |
|
| 1492 | + break; |
|
| 1493 | + } |
|
| 1494 | + } |
|
| 1495 | + return $running_totals; |
|
| 1496 | + } |
|
| 1497 | + |
|
| 1498 | + |
|
| 1499 | + /** |
|
| 1500 | + * @param \EE_Line_Item $total_line_item |
|
| 1501 | + * @param \EE_Line_Item $ticket_line_item |
|
| 1502 | + * @return float | null |
|
| 1503 | + * @throws \OutOfRangeException |
|
| 1504 | + */ |
|
| 1505 | + public static function calculate_final_price_for_ticket_line_item(\EE_Line_Item $total_line_item, \EE_Line_Item $ticket_line_item) |
|
| 1506 | + { |
|
| 1507 | + static $final_prices_per_ticket_line_item = array(); |
|
| 1508 | + if (empty($final_prices_per_ticket_line_item)) { |
|
| 1509 | + $final_prices_per_ticket_line_item = \EEH_Line_Item::calculate_reg_final_prices_per_line_item( |
|
| 1510 | + $total_line_item |
|
| 1511 | + ); |
|
| 1512 | + } |
|
| 1513 | + //ok now find this new registration's final price |
|
| 1514 | + if (isset($final_prices_per_ticket_line_item[$ticket_line_item->ID()])) { |
|
| 1515 | + return $final_prices_per_ticket_line_item[$ticket_line_item->ID()]; |
|
| 1516 | + } |
|
| 1517 | + $message = sprintf( |
|
| 1518 | + __( |
|
| 1519 | + 'The final price for the ticket line item (ID:%1$d) could not be calculated.', |
|
| 1520 | + 'event_espresso' |
|
| 1521 | + ), |
|
| 1522 | + $ticket_line_item->ID() |
|
| 1523 | + ); |
|
| 1524 | + if (WP_DEBUG) { |
|
| 1525 | + $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true); |
|
| 1526 | + throw new \OutOfRangeException($message); |
|
| 1527 | + } else { |
|
| 1528 | + EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message); |
|
| 1529 | + } |
|
| 1530 | + return null; |
|
| 1531 | + } |
|
| 1532 | + |
|
| 1533 | + |
|
| 1534 | + /** |
|
| 1535 | + * Creates a duplicate of the line item tree, except only includes billable items |
|
| 1536 | + * and the portion of line items attributed to billable things |
|
| 1537 | + * |
|
| 1538 | + * @param EE_Line_Item $line_item |
|
| 1539 | + * @param EE_Registration[] $registrations |
|
| 1540 | + * @return \EE_Line_Item |
|
| 1541 | + * @throws \EE_Error |
|
| 1542 | + */ |
|
| 1543 | + public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations) |
|
| 1544 | + { |
|
| 1545 | + $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations); |
|
| 1546 | + foreach ($line_item->children() as $child_li) { |
|
| 1547 | + $copy_li->add_child_line_item(EEH_Line_Item::billable_line_item_tree($child_li, $registrations)); |
|
| 1548 | + } |
|
| 1549 | + //if this is the grand total line item, make sure the totals all add up |
|
| 1550 | + //(we could have duplicated this logic AS we copied the line items, but |
|
| 1551 | + //it seems DRYer this way) |
|
| 1552 | + if ($copy_li->type() === EEM_Line_Item::type_total) { |
|
| 1553 | + $copy_li->recalculate_total_including_taxes(); |
|
| 1554 | + } |
|
| 1555 | + return $copy_li; |
|
| 1556 | + } |
|
| 1557 | + |
|
| 1558 | + |
|
| 1559 | + /** |
|
| 1560 | + * Creates a new, unsaved line item from $line_item that factors in the |
|
| 1561 | + * number of billable registrations on $registrations. |
|
| 1562 | + * |
|
| 1563 | + * @param EE_Line_Item $line_item |
|
| 1564 | + * @return EE_Line_Item |
|
| 1565 | + * @throws \EE_Error |
|
| 1566 | + * @param EE_Registration[] $registrations |
|
| 1567 | + */ |
|
| 1568 | + public static function billable_line_item(EE_Line_Item $line_item, $registrations) |
|
| 1569 | + { |
|
| 1570 | + $new_li_fields = $line_item->model_field_array(); |
|
| 1571 | + if ($line_item->type() === EEM_Line_Item::type_line_item && |
|
| 1572 | + $line_item->OBJ_type() === 'Ticket' |
|
| 1573 | + ) { |
|
| 1574 | + $count = 0; |
|
| 1575 | + foreach ($registrations as $registration) { |
|
| 1576 | + if ($line_item->OBJ_ID() === $registration->ticket_ID() && |
|
| 1577 | + in_array($registration->status_ID(), EEM_Registration::reg_statuses_that_allow_payment()) |
|
| 1578 | + ) { |
|
| 1579 | + $count++; |
|
| 1580 | + } |
|
| 1581 | + } |
|
| 1582 | + $new_li_fields['LIN_quantity'] = $count; |
|
| 1583 | + } |
|
| 1584 | + //don't set the total. We'll leave that up to the code that calculates it |
|
| 1585 | + unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']); |
|
| 1586 | + return EE_Line_Item::new_instance($new_li_fields); |
|
| 1587 | + } |
|
| 1588 | + |
|
| 1589 | + |
|
| 1590 | + /** |
|
| 1591 | + * Returns a modified line item tree where all the subtotals which have a total of 0 |
|
| 1592 | + * are removed, and line items with a quantity of 0 |
|
| 1593 | + * |
|
| 1594 | + * @param EE_Line_Item $line_item |null |
|
| 1595 | + * @return \EE_Line_Item|null |
|
| 1596 | + * @throws \EE_Error |
|
| 1597 | + */ |
|
| 1598 | + public static function non_empty_line_items(EE_Line_Item $line_item) |
|
| 1599 | + { |
|
| 1600 | + $copied_li = EEH_Line_Item::non_empty_line_item($line_item); |
|
| 1601 | + if ($copied_li === null) { |
|
| 1602 | + return null; |
|
| 1603 | + } |
|
| 1604 | + //if this is an event subtotal, we want to only include it if it |
|
| 1605 | + //has a non-zero total and at least one ticket line item child |
|
| 1606 | + $ticket_children = 0; |
|
| 1607 | + foreach ($line_item->children() as $child_li) { |
|
| 1608 | + $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li); |
|
| 1609 | + if ($child_li_copy !== null) { |
|
| 1610 | + $copied_li->add_child_line_item($child_li_copy); |
|
| 1611 | + if ($child_li_copy->type() === EEM_Line_Item::type_line_item && |
|
| 1612 | + $child_li_copy->OBJ_type() === 'Ticket' |
|
| 1613 | + ) { |
|
| 1614 | + $ticket_children++; |
|
| 1615 | + } |
|
| 1616 | + } |
|
| 1617 | + } |
|
| 1618 | + //if this is an event subtotal with NO ticket children |
|
| 1619 | + //we basically want to ignore it |
|
| 1620 | + if ( |
|
| 1621 | + $ticket_children === 0 |
|
| 1622 | + && $line_item->type() === EEM_Line_Item::type_sub_total |
|
| 1623 | + && $line_item->OBJ_type() === 'Event' |
|
| 1624 | + && $line_item->total() === 0 |
|
| 1625 | + ) { |
|
| 1626 | + return null; |
|
| 1627 | + } |
|
| 1628 | + return $copied_li; |
|
| 1629 | + } |
|
| 1630 | + |
|
| 1631 | + |
|
| 1632 | + /** |
|
| 1633 | + * Creates a new, unsaved line item, but if it's a ticket line item |
|
| 1634 | + * with a total of 0, or a subtotal of 0, returns null instead |
|
| 1635 | + * |
|
| 1636 | + * @param EE_Line_Item $line_item |
|
| 1637 | + * @return EE_Line_Item |
|
| 1638 | + * @throws \EE_Error |
|
| 1639 | + */ |
|
| 1640 | + public static function non_empty_line_item(EE_Line_Item $line_item) |
|
| 1641 | + { |
|
| 1642 | + if ($line_item->type() === EEM_Line_Item::type_line_item && |
|
| 1643 | + $line_item->OBJ_type() === 'Ticket' && |
|
| 1644 | + $line_item->quantity() === 0 |
|
| 1645 | + ) { |
|
| 1646 | + return null; |
|
| 1647 | + } |
|
| 1648 | + $new_li_fields = $line_item->model_field_array(); |
|
| 1649 | + //don't set the total. We'll leave that up to the code that calculates it |
|
| 1650 | + unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']); |
|
| 1651 | + return EE_Line_Item::new_instance($new_li_fields); |
|
| 1652 | + } |
|
| 1653 | + |
|
| 1654 | + |
|
| 1655 | + |
|
| 1656 | + /**************************************** @DEPRECATED METHODS *************************************** */ |
|
| 1657 | + /** |
|
| 1658 | + * @deprecated |
|
| 1659 | + * @param EE_Line_Item $total_line_item |
|
| 1660 | + * @return \EE_Line_Item |
|
| 1661 | + * @throws \EE_Error |
|
| 1662 | + */ |
|
| 1663 | + public static function get_items_subtotal(EE_Line_Item $total_line_item) |
|
| 1664 | + { |
|
| 1665 | + EE_Error::doing_it_wrong('EEH_Line_Item::get_items_subtotal()', __('Method replaced with EEH_Line_Item::get_pre_tax_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1666 | + return self::get_pre_tax_subtotal($total_line_item); |
|
| 1667 | + } |
|
| 1668 | + |
|
| 1669 | + |
|
| 1670 | + /** |
|
| 1671 | + * @deprecated |
|
| 1672 | + * @param EE_Transaction $transaction |
|
| 1673 | + * @return \EE_Line_Item |
|
| 1674 | + * @throws \EE_Error |
|
| 1675 | + */ |
|
| 1676 | + public static function create_default_total_line_item($transaction = NULL) |
|
| 1677 | + { |
|
| 1678 | + EE_Error::doing_it_wrong('EEH_Line_Item::create_default_total_line_item()', __('Method replaced with EEH_Line_Item::create_total_line_item()', 'event_espresso'), '4.6.0'); |
|
| 1679 | + return self::create_total_line_item($transaction); |
|
| 1680 | + } |
|
| 1681 | + |
|
| 1682 | + |
|
| 1683 | + /** |
|
| 1684 | + * @deprecated |
|
| 1685 | + * @param EE_Line_Item $total_line_item |
|
| 1686 | + * @param EE_Transaction $transaction |
|
| 1687 | + * @return \EE_Line_Item |
|
| 1688 | + * @throws \EE_Error |
|
| 1689 | + */ |
|
| 1690 | + public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 1691 | + { |
|
| 1692 | + EE_Error::doing_it_wrong('EEH_Line_Item::create_default_tickets_subtotal()', __('Method replaced with EEH_Line_Item::create_pre_tax_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1693 | + return self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 1694 | + } |
|
| 1695 | + |
|
| 1696 | + |
|
| 1697 | + /** |
|
| 1698 | + * @deprecated |
|
| 1699 | + * @param EE_Line_Item $total_line_item |
|
| 1700 | + * @param EE_Transaction $transaction |
|
| 1701 | + * @return \EE_Line_Item |
|
| 1702 | + * @throws \EE_Error |
|
| 1703 | + */ |
|
| 1704 | + public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 1705 | + { |
|
| 1706 | + EE_Error::doing_it_wrong('EEH_Line_Item::create_default_taxes_subtotal()', __('Method replaced with EEH_Line_Item::create_taxes_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1707 | + return self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 1708 | + } |
|
| 1709 | + |
|
| 1710 | + |
|
| 1711 | + /** |
|
| 1712 | + * @deprecated |
|
| 1713 | + * @param EE_Line_Item $total_line_item |
|
| 1714 | + * @param EE_Transaction $transaction |
|
| 1715 | + * @return \EE_Line_Item |
|
| 1716 | + * @throws \EE_Error |
|
| 1717 | + */ |
|
| 1718 | + public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = NULL) |
|
| 1719 | + { |
|
| 1720 | + EE_Error::doing_it_wrong('EEH_Line_Item::create_default_event_subtotal()', __('Method replaced with EEH_Line_Item::create_event_subtotal()', 'event_espresso'), '4.6.0'); |
|
| 1721 | + return self::create_event_subtotal($total_line_item, $transaction); |
|
| 1722 | + } |
|
| 1723 | 1723 | |
| 1724 | 1724 | |
| 1725 | 1725 | } |
@@ -1,4 +1,4 @@ discard block |
||
| 1 | -<?php if (!defined('EVENT_ESPRESSO_VERSION')) { |
|
| 1 | +<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
|
| 2 | 2 | exit('No direct script access allowed'); |
| 3 | 3 | } |
| 4 | 4 | |
@@ -56,7 +56,7 @@ discard block |
||
| 56 | 56 | 'LIN_percent' => null, |
| 57 | 57 | 'LIN_is_taxable' => $taxable, |
| 58 | 58 | 'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0, |
| 59 | - 'LIN_total' => (float)$unit_price * (int)$quantity, |
|
| 59 | + 'LIN_total' => (float) $unit_price * (int) $quantity, |
|
| 60 | 60 | 'LIN_type' => EEM_Line_Item::type_line_item, |
| 61 | 61 | 'LIN_code' => $code, |
| 62 | 62 | )); |
@@ -95,7 +95,7 @@ discard block |
||
| 95 | 95 | 'LIN_percent' => $percentage_amount, |
| 96 | 96 | 'LIN_quantity' => 1, |
| 97 | 97 | 'LIN_is_taxable' => $taxable, |
| 98 | - 'LIN_total' => (float)($percentage_amount * ($parent_line_item->total() / 100)), |
|
| 98 | + 'LIN_total' => (float) ($percentage_amount * ($parent_line_item->total() / 100)), |
|
| 99 | 99 | 'LIN_type' => EEM_Line_Item::type_line_item, |
| 100 | 100 | 'LIN_parent' => $parent_line_item->ID() |
| 101 | 101 | )); |
@@ -125,13 +125,13 @@ discard block |
||
| 125 | 125 | */ |
| 126 | 126 | public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
| 127 | 127 | { |
| 128 | - if (!$total_line_item instanceof EE_Line_Item || !$total_line_item->is_total()) { |
|
| 128 | + if ( ! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) { |
|
| 129 | 129 | throw new EE_Error(sprintf(__('A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', 'event_espresso'), $ticket->ID(), $total_line_item->ID())); |
| 130 | 130 | } |
| 131 | 131 | // either increment the qty for an existing ticket |
| 132 | 132 | $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty); |
| 133 | 133 | // or add a new one |
| 134 | - if (!$line_item instanceof EE_Line_Item) { |
|
| 134 | + if ( ! $line_item instanceof EE_Line_Item) { |
|
| 135 | 135 | $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty); |
| 136 | 136 | } |
| 137 | 137 | $total_line_item->recalculate_total_including_taxes(); |
@@ -152,10 +152,10 @@ discard block |
||
| 152 | 152 | $line_item = null; |
| 153 | 153 | if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) { |
| 154 | 154 | $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item); |
| 155 | - foreach ((array)$ticket_line_items as $ticket_line_item) { |
|
| 155 | + foreach ((array) $ticket_line_items as $ticket_line_item) { |
|
| 156 | 156 | if ( |
| 157 | 157 | $ticket_line_item instanceof EE_Line_Item |
| 158 | - && (int)$ticket_line_item->OBJ_ID() === (int)$ticket->ID() |
|
| 158 | + && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID() |
|
| 159 | 159 | ) { |
| 160 | 160 | $line_item = $ticket_line_item; |
| 161 | 161 | break; |
@@ -181,7 +181,7 @@ discard block |
||
| 181 | 181 | */ |
| 182 | 182 | public static function increment_quantity(EE_Line_Item $line_item, $qty = 1) |
| 183 | 183 | { |
| 184 | - if (!$line_item->is_percent()) { |
|
| 184 | + if ( ! $line_item->is_percent()) { |
|
| 185 | 185 | $qty += $line_item->quantity(); |
| 186 | 186 | $line_item->set_quantity($qty); |
| 187 | 187 | $line_item->set_total($line_item->unit_price() * $qty); |
@@ -206,7 +206,7 @@ discard block |
||
| 206 | 206 | */ |
| 207 | 207 | public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1) |
| 208 | 208 | { |
| 209 | - if (!$line_item->is_percent()) { |
|
| 209 | + if ( ! $line_item->is_percent()) { |
|
| 210 | 210 | $qty = $line_item->quantity() - $qty; |
| 211 | 211 | $qty = max($qty, 0); |
| 212 | 212 | $line_item->set_quantity($qty); |
@@ -231,7 +231,7 @@ discard block |
||
| 231 | 231 | */ |
| 232 | 232 | public static function update_quantity(EE_Line_Item $line_item, $new_quantity) |
| 233 | 233 | { |
| 234 | - if (!$line_item->is_percent()) { |
|
| 234 | + if ( ! $line_item->is_percent()) { |
|
| 235 | 235 | $line_item->set_quantity($new_quantity); |
| 236 | 236 | $line_item->set_total($line_item->unit_price() * $new_quantity); |
| 237 | 237 | $line_item->save(); |
@@ -267,7 +267,7 @@ discard block |
||
| 267 | 267 | // add $ticket to cart |
| 268 | 268 | $line_item = EE_Line_Item::new_instance(array( |
| 269 | 269 | 'LIN_name' => $ticket->name(), |
| 270 | - 'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event, |
|
| 270 | + 'LIN_desc' => $ticket->description() !== '' ? $ticket->description().' '.$event : $event, |
|
| 271 | 271 | 'LIN_unit_price' => $ticket->price(), |
| 272 | 272 | 'LIN_quantity' => $qty, |
| 273 | 273 | 'LIN_is_taxable' => $ticket->taxable(), |
@@ -377,8 +377,8 @@ discard block |
||
| 377 | 377 | foreach ($ticket_line_item->children() as $child_line_item) { |
| 378 | 378 | if ( |
| 379 | 379 | $child_line_item->is_sub_line_item() |
| 380 | - && !$child_line_item->is_percent() |
|
| 381 | - && !$child_line_item->is_cancellation() |
|
| 380 | + && ! $child_line_item->is_percent() |
|
| 381 | + && ! $child_line_item->is_cancellation() |
|
| 382 | 382 | ) { |
| 383 | 383 | $child_line_item->set_quantity($child_line_item->quantity() - $qty); |
| 384 | 384 | } |
@@ -400,7 +400,7 @@ discard block |
||
| 400 | 400 | 'LIN_desc' => sprintf( |
| 401 | 401 | _x('Cancelled %1$s : %2$s', 'Cancelled Ticket Name : 2015-01-01 11:11', 'event_espresso'), |
| 402 | 402 | $ticket_line_item->name(), |
| 403 | - current_time(get_option('date_format') . ' ' . get_option('time_format')) |
|
| 403 | + current_time(get_option('date_format').' '.get_option('time_format')) |
|
| 404 | 404 | ), |
| 405 | 405 | 'LIN_unit_price' => 0, // $ticket_line_item->unit_price() |
| 406 | 406 | 'LIN_quantity' => $qty, |
@@ -453,7 +453,7 @@ discard block |
||
| 453 | 453 | ); |
| 454 | 454 | $cancellation_line_item = reset($cancellation_line_item); |
| 455 | 455 | // verify that this ticket was indeed previously cancelled |
| 456 | - if (!$cancellation_line_item instanceof EE_Line_Item) { |
|
| 456 | + if ( ! $cancellation_line_item instanceof EE_Line_Item) { |
|
| 457 | 457 | return false; |
| 458 | 458 | } |
| 459 | 459 | if ($cancellation_line_item->quantity() > $qty) { |
@@ -625,7 +625,7 @@ discard block |
||
| 625 | 625 | 'LIN_code' => 'taxes', |
| 626 | 626 | 'LIN_name' => __('Taxes', 'event_espresso'), |
| 627 | 627 | 'LIN_type' => EEM_Line_Item::type_tax_sub_total, |
| 628 | - 'LIN_order' => 1000,//this should always come last |
|
| 628 | + 'LIN_order' => 1000, //this should always come last |
|
| 629 | 629 | )); |
| 630 | 630 | $tax_line_item = apply_filters( |
| 631 | 631 | 'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item', |
@@ -677,7 +677,7 @@ discard block |
||
| 677 | 677 | */ |
| 678 | 678 | public static function get_event_code($event) |
| 679 | 679 | { |
| 680 | - return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 680 | + return 'event-'.($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 681 | 681 | } |
| 682 | 682 | |
| 683 | 683 | /** |
@@ -713,13 +713,13 @@ discard block |
||
| 713 | 713 | public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket) |
| 714 | 714 | { |
| 715 | 715 | $first_datetime = $ticket->first_datetime(); |
| 716 | - if (!$first_datetime instanceof EE_Datetime) { |
|
| 716 | + if ( ! $first_datetime instanceof EE_Datetime) { |
|
| 717 | 717 | throw new EE_Error( |
| 718 | 718 | sprintf(__('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), $ticket->ID()) |
| 719 | 719 | ); |
| 720 | 720 | } |
| 721 | 721 | $event = $first_datetime->event(); |
| 722 | - if (!$event instanceof EE_Event) { |
|
| 722 | + if ( ! $event instanceof EE_Event) { |
|
| 723 | 723 | throw new EE_Error( |
| 724 | 724 | sprintf( |
| 725 | 725 | __('The supplied ticket (ID %d) has no event data associated with it.', 'event_espresso'), |
@@ -728,7 +728,7 @@ discard block |
||
| 728 | 728 | ); |
| 729 | 729 | } |
| 730 | 730 | $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event); |
| 731 | - if (!$events_sub_total instanceof EE_Line_Item) { |
|
| 731 | + if ( ! $events_sub_total instanceof EE_Line_Item) { |
|
| 732 | 732 | throw new EE_Error( |
| 733 | 733 | sprintf( |
| 734 | 734 | __('There is no events sub-total for ticket %s on total line item %d', 'event_espresso'), |
@@ -757,7 +757,7 @@ discard block |
||
| 757 | 757 | $found = false; |
| 758 | 758 | foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) { |
| 759 | 759 | // default event subtotal, we should only ever find this the first time this method is called |
| 760 | - if (!$event_line_item->OBJ_ID()) { |
|
| 760 | + if ( ! $event_line_item->OBJ_ID()) { |
|
| 761 | 761 | // let's use this! but first... set the event details |
| 762 | 762 | EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
| 763 | 763 | $found = true; |
@@ -768,7 +768,7 @@ discard block |
||
| 768 | 768 | break; |
| 769 | 769 | } |
| 770 | 770 | } |
| 771 | - if (!$found) { |
|
| 771 | + if ( ! $found) { |
|
| 772 | 772 | //there is no event sub-total yet, so add it |
| 773 | 773 | $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total); |
| 774 | 774 | // create a new "event" subtotal below that |
@@ -863,7 +863,7 @@ discard block |
||
| 863 | 863 | public static function ensure_taxes_applied($total_line_item) |
| 864 | 864 | { |
| 865 | 865 | $taxes_subtotal = self::get_taxes_subtotal($total_line_item); |
| 866 | - if (!$taxes_subtotal->children()) { |
|
| 866 | + if ( ! $taxes_subtotal->children()) { |
|
| 867 | 867 | self::apply_taxes($total_line_item); |
| 868 | 868 | } |
| 869 | 869 | return $taxes_subtotal->total(); |
@@ -924,7 +924,7 @@ discard block |
||
| 924 | 924 | do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
| 925 | 925 | |
| 926 | 926 | // check if only a single line_item_id was passed |
| 927 | - if (!empty($line_item_codes) && !is_array($line_item_codes)) { |
|
| 927 | + if ( ! empty($line_item_codes) && ! is_array($line_item_codes)) { |
|
| 928 | 928 | // place single line_item_id in an array to appear as multiple line_item_ids |
| 929 | 929 | $line_item_codes = array($line_item_codes); |
| 930 | 930 | } |
@@ -1027,7 +1027,7 @@ discard block |
||
| 1027 | 1027 | if ($code_substring_for_whitelist !== null) { |
| 1028 | 1028 | $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false ? true : false; |
| 1029 | 1029 | } |
| 1030 | - if (!$whitelisted && $line_item->is_line_item()) { |
|
| 1030 | + if ( ! $whitelisted && $line_item->is_line_item()) { |
|
| 1031 | 1031 | $line_item->set_is_taxable($taxable); |
| 1032 | 1032 | } |
| 1033 | 1033 | foreach ($line_item->children() as $child_line_item) { |
@@ -1332,7 +1332,7 @@ discard block |
||
| 1332 | 1332 | public static function visualize(EE_Line_Item $line_item, $indentation = 0) |
| 1333 | 1333 | { |
| 1334 | 1334 | echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
| 1335 | - if (!$indentation) { |
|
| 1335 | + if ( ! $indentation) { |
|
| 1336 | 1336 | echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
| 1337 | 1337 | } |
| 1338 | 1338 | for ($i = 0; $i < $indentation; $i++) { |
@@ -1343,10 +1343,10 @@ discard block |
||
| 1343 | 1343 | if ($line_item->is_percent()) { |
| 1344 | 1344 | $breakdown = "{$line_item->percent()}%"; |
| 1345 | 1345 | } else { |
| 1346 | - $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1346 | + $breakdown = '$'."{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1347 | 1347 | } |
| 1348 | 1348 | } |
| 1349 | - echo $line_item->name() . " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : " . '$' . "{$line_item->total()}"; |
|
| 1349 | + echo $line_item->name()." [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : ".'$'."{$line_item->total()}"; |
|
| 1350 | 1350 | if ($breakdown) { |
| 1351 | 1351 | echo " ( {$breakdown} )"; |
| 1352 | 1352 | } |
@@ -1397,10 +1397,10 @@ discard block |
||
| 1397 | 1397 | public static function calculate_reg_final_prices_per_line_item(EE_Line_Item $line_item, $billable_ticket_quantities = array()) |
| 1398 | 1398 | { |
| 1399 | 1399 | //init running grand total if not already |
| 1400 | - if (!isset($running_totals['total'])) { |
|
| 1400 | + if ( ! isset($running_totals['total'])) { |
|
| 1401 | 1401 | $running_totals['total'] = 0; |
| 1402 | 1402 | } |
| 1403 | - if (!isset($running_totals['taxable'])) { |
|
| 1403 | + if ( ! isset($running_totals['taxable'])) { |
|
| 1404 | 1404 | $running_totals['taxable'] = array('total' => 0); |
| 1405 | 1405 | } |
| 1406 | 1406 | foreach ($line_item->children() as $child_line_item) { |
@@ -1522,7 +1522,7 @@ discard block |
||
| 1522 | 1522 | $ticket_line_item->ID() |
| 1523 | 1523 | ); |
| 1524 | 1524 | if (WP_DEBUG) { |
| 1525 | - $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true); |
|
| 1525 | + $message .= '<br>'.print_r($final_prices_per_ticket_line_item, true); |
|
| 1526 | 1526 | throw new \OutOfRangeException($message); |
| 1527 | 1527 | } else { |
| 1528 | 1528 | EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message); |
@@ -17,1432 +17,1432 @@ |
||
| 17 | 17 | class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item |
| 18 | 18 | { |
| 19 | 19 | |
| 20 | - /** |
|
| 21 | - * for children line items (currently not a normal relation) |
|
| 22 | - * |
|
| 23 | - * @type EE_Line_Item[] |
|
| 24 | - */ |
|
| 25 | - protected $_children = array(); |
|
| 26 | - |
|
| 27 | - /** |
|
| 28 | - * for the parent line item |
|
| 29 | - * |
|
| 30 | - * @var EE_Line_Item |
|
| 31 | - */ |
|
| 32 | - protected $_parent; |
|
| 33 | - |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * |
|
| 37 | - * @param array $props_n_values incoming values |
|
| 38 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 39 | - * used.) |
|
| 40 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 41 | - * date_format and the second value is the time format |
|
| 42 | - * @return EE_Line_Item |
|
| 43 | - * @throws EE_Error |
|
| 44 | - */ |
|
| 45 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
| 46 | - { |
|
| 47 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 48 | - return $has_object |
|
| 49 | - ? $has_object |
|
| 50 | - : new self($props_n_values, false, $timezone); |
|
| 51 | - } |
|
| 52 | - |
|
| 53 | - |
|
| 54 | - /** |
|
| 55 | - * @param array $props_n_values incoming values from the database |
|
| 56 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 57 | - * the website will be used. |
|
| 58 | - * @return EE_Line_Item |
|
| 59 | - * @throws EE_Error |
|
| 60 | - */ |
|
| 61 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
| 62 | - { |
|
| 63 | - return new self($props_n_values, true, $timezone); |
|
| 64 | - } |
|
| 65 | - |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * Adds some defaults if they're not specified |
|
| 69 | - * |
|
| 70 | - * @param array $fieldValues |
|
| 71 | - * @param bool $bydb |
|
| 72 | - * @param string $timezone |
|
| 73 | - * @throws EE_Error |
|
| 74 | - */ |
|
| 75 | - protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
| 76 | - { |
|
| 77 | - parent::__construct($fieldValues, $bydb, $timezone); |
|
| 78 | - if (!$this->get('LIN_code')) { |
|
| 79 | - $this->set_code($this->generate_code()); |
|
| 80 | - } |
|
| 81 | - } |
|
| 82 | - |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * Gets ID |
|
| 86 | - * |
|
| 87 | - * @return int |
|
| 88 | - * @throws EE_Error |
|
| 89 | - */ |
|
| 90 | - public function ID() |
|
| 91 | - { |
|
| 92 | - return $this->get('LIN_ID'); |
|
| 93 | - } |
|
| 94 | - |
|
| 95 | - |
|
| 96 | - /** |
|
| 97 | - * Gets TXN_ID |
|
| 98 | - * |
|
| 99 | - * @return int |
|
| 100 | - * @throws EE_Error |
|
| 101 | - */ |
|
| 102 | - public function TXN_ID() |
|
| 103 | - { |
|
| 104 | - return $this->get('TXN_ID'); |
|
| 105 | - } |
|
| 106 | - |
|
| 107 | - |
|
| 108 | - /** |
|
| 109 | - * Sets TXN_ID |
|
| 110 | - * |
|
| 111 | - * @param int $TXN_ID |
|
| 112 | - * @throws EE_Error |
|
| 113 | - */ |
|
| 114 | - public function set_TXN_ID($TXN_ID) |
|
| 115 | - { |
|
| 116 | - $this->set('TXN_ID', $TXN_ID); |
|
| 117 | - } |
|
| 118 | - |
|
| 119 | - |
|
| 120 | - /** |
|
| 121 | - * Gets name |
|
| 122 | - * |
|
| 123 | - * @return string |
|
| 124 | - * @throws EE_Error |
|
| 125 | - */ |
|
| 126 | - public function name() |
|
| 127 | - { |
|
| 128 | - $name = $this->get('LIN_name'); |
|
| 129 | - if (!$name) { |
|
| 130 | - $name = ucwords(str_replace('-', ' ', $this->type())); |
|
| 131 | - } |
|
| 132 | - return $name; |
|
| 133 | - } |
|
| 134 | - |
|
| 135 | - |
|
| 136 | - /** |
|
| 137 | - * Sets name |
|
| 138 | - * |
|
| 139 | - * @param string $name |
|
| 140 | - * @throws EE_Error |
|
| 141 | - */ |
|
| 142 | - public function set_name($name) |
|
| 143 | - { |
|
| 144 | - $this->set('LIN_name', $name); |
|
| 145 | - } |
|
| 146 | - |
|
| 147 | - |
|
| 148 | - /** |
|
| 149 | - * Gets desc |
|
| 150 | - * |
|
| 151 | - * @return string |
|
| 152 | - * @throws EE_Error |
|
| 153 | - */ |
|
| 154 | - public function desc() |
|
| 155 | - { |
|
| 156 | - return $this->get('LIN_desc'); |
|
| 157 | - } |
|
| 158 | - |
|
| 159 | - |
|
| 160 | - /** |
|
| 161 | - * Sets desc |
|
| 162 | - * |
|
| 163 | - * @param string $desc |
|
| 164 | - * @throws EE_Error |
|
| 165 | - */ |
|
| 166 | - public function set_desc($desc) |
|
| 167 | - { |
|
| 168 | - $this->set('LIN_desc', $desc); |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * Gets quantity |
|
| 174 | - * |
|
| 175 | - * @return int |
|
| 176 | - * @throws EE_Error |
|
| 177 | - */ |
|
| 178 | - public function quantity() |
|
| 179 | - { |
|
| 180 | - return $this->get('LIN_quantity'); |
|
| 181 | - } |
|
| 182 | - |
|
| 183 | - |
|
| 184 | - /** |
|
| 185 | - * Sets quantity |
|
| 186 | - * |
|
| 187 | - * @param int $quantity |
|
| 188 | - * @throws EE_Error |
|
| 189 | - */ |
|
| 190 | - public function set_quantity($quantity) |
|
| 191 | - { |
|
| 192 | - $this->set('LIN_quantity', max($quantity, 0)); |
|
| 193 | - } |
|
| 194 | - |
|
| 195 | - |
|
| 196 | - /** |
|
| 197 | - * Gets item_id |
|
| 198 | - * |
|
| 199 | - * @return string |
|
| 200 | - * @throws EE_Error |
|
| 201 | - */ |
|
| 202 | - public function OBJ_ID() |
|
| 203 | - { |
|
| 204 | - return $this->get('OBJ_ID'); |
|
| 205 | - } |
|
| 206 | - |
|
| 207 | - |
|
| 208 | - /** |
|
| 209 | - * Sets item_id |
|
| 210 | - * |
|
| 211 | - * @param string $item_id |
|
| 212 | - * @throws EE_Error |
|
| 213 | - */ |
|
| 214 | - public function set_OBJ_ID($item_id) |
|
| 215 | - { |
|
| 216 | - $this->set('OBJ_ID', $item_id); |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - |
|
| 220 | - /** |
|
| 221 | - * Gets item_type |
|
| 222 | - * |
|
| 223 | - * @return string |
|
| 224 | - * @throws EE_Error |
|
| 225 | - */ |
|
| 226 | - public function OBJ_type() |
|
| 227 | - { |
|
| 228 | - return $this->get('OBJ_type'); |
|
| 229 | - } |
|
| 230 | - |
|
| 231 | - |
|
| 232 | - /** |
|
| 233 | - * Gets item_type |
|
| 234 | - * |
|
| 235 | - * @return string |
|
| 236 | - * @throws EE_Error |
|
| 237 | - */ |
|
| 238 | - public function OBJ_type_i18n() |
|
| 239 | - { |
|
| 240 | - $obj_type = $this->OBJ_type(); |
|
| 241 | - switch ($obj_type) { |
|
| 242 | - case 'Event': |
|
| 243 | - $obj_type = __('Event', 'event_espresso'); |
|
| 244 | - break; |
|
| 245 | - case 'Price': |
|
| 246 | - $obj_type = __('Price', 'event_espresso'); |
|
| 247 | - break; |
|
| 248 | - case 'Promotion': |
|
| 249 | - $obj_type = __('Promotion', 'event_espresso'); |
|
| 250 | - break; |
|
| 251 | - case 'Ticket': |
|
| 252 | - $obj_type = __('Ticket', 'event_espresso'); |
|
| 253 | - break; |
|
| 254 | - case 'Transaction': |
|
| 255 | - $obj_type = __('Transaction', 'event_espresso'); |
|
| 256 | - break; |
|
| 257 | - } |
|
| 258 | - return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
| 259 | - } |
|
| 260 | - |
|
| 261 | - |
|
| 262 | - /** |
|
| 263 | - * Sets item_type |
|
| 264 | - * |
|
| 265 | - * @param string $OBJ_type |
|
| 266 | - * @throws EE_Error |
|
| 267 | - */ |
|
| 268 | - public function set_OBJ_type($OBJ_type) |
|
| 269 | - { |
|
| 270 | - $this->set('OBJ_type', $OBJ_type); |
|
| 271 | - } |
|
| 272 | - |
|
| 273 | - |
|
| 274 | - /** |
|
| 275 | - * Gets unit_price |
|
| 276 | - * |
|
| 277 | - * @return float |
|
| 278 | - * @throws EE_Error |
|
| 279 | - */ |
|
| 280 | - public function unit_price() |
|
| 281 | - { |
|
| 282 | - return $this->get('LIN_unit_price'); |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - |
|
| 286 | - /** |
|
| 287 | - * Sets unit_price |
|
| 288 | - * |
|
| 289 | - * @param float $unit_price |
|
| 290 | - * @throws EE_Error |
|
| 291 | - */ |
|
| 292 | - public function set_unit_price($unit_price) |
|
| 293 | - { |
|
| 294 | - $this->set('LIN_unit_price', $unit_price); |
|
| 295 | - } |
|
| 296 | - |
|
| 297 | - |
|
| 298 | - /** |
|
| 299 | - * Checks if this item is a percentage modifier or not |
|
| 300 | - * |
|
| 301 | - * @return boolean |
|
| 302 | - * @throws EE_Error |
|
| 303 | - */ |
|
| 304 | - public function is_percent() |
|
| 305 | - { |
|
| 306 | - if ($this->is_tax_sub_total()) { |
|
| 307 | - //tax subtotals HAVE a percent on them, that percentage only applies |
|
| 308 | - //to taxable items, so its' an exception. Treat it like a flat line item |
|
| 309 | - return false; |
|
| 310 | - } |
|
| 311 | - $unit_price = abs($this->get('LIN_unit_price')); |
|
| 312 | - $percent = abs($this->get('LIN_percent')); |
|
| 313 | - if ($unit_price < .001 && $percent) { |
|
| 314 | - return true; |
|
| 315 | - } |
|
| 316 | - if ($unit_price >= .001 && !$percent) { |
|
| 317 | - return false; |
|
| 318 | - } |
|
| 319 | - if ($unit_price >= .001 && $percent) { |
|
| 320 | - throw new EE_Error( |
|
| 321 | - sprintf( |
|
| 322 | - esc_html__('A Line Item can not have a unit price of (%s) AND a percent (%s)!', 'event_espresso'), |
|
| 323 | - $unit_price, $percent |
|
| 324 | - ) |
|
| 325 | - ); |
|
| 326 | - } |
|
| 327 | - // if they're both 0, assume its not a percent item |
|
| 328 | - return false; |
|
| 329 | - } |
|
| 330 | - |
|
| 331 | - |
|
| 332 | - /** |
|
| 333 | - * Gets percent (between 100-.001) |
|
| 334 | - * |
|
| 335 | - * @return float |
|
| 336 | - * @throws EE_Error |
|
| 337 | - */ |
|
| 338 | - public function percent() |
|
| 339 | - { |
|
| 340 | - return $this->get('LIN_percent'); |
|
| 341 | - } |
|
| 342 | - |
|
| 343 | - |
|
| 344 | - /** |
|
| 345 | - * Sets percent (between 100-0.01) |
|
| 346 | - * |
|
| 347 | - * @param float $percent |
|
| 348 | - * @throws EE_Error |
|
| 349 | - */ |
|
| 350 | - public function set_percent($percent) |
|
| 351 | - { |
|
| 352 | - $this->set('LIN_percent', $percent); |
|
| 353 | - } |
|
| 354 | - |
|
| 355 | - |
|
| 356 | - /** |
|
| 357 | - * Gets total |
|
| 358 | - * |
|
| 359 | - * @return float |
|
| 360 | - * @throws EE_Error |
|
| 361 | - */ |
|
| 362 | - public function total() |
|
| 363 | - { |
|
| 364 | - return $this->get('LIN_total'); |
|
| 365 | - } |
|
| 366 | - |
|
| 367 | - |
|
| 368 | - /** |
|
| 369 | - * Sets total |
|
| 370 | - * |
|
| 371 | - * @param float $total |
|
| 372 | - * @throws EE_Error |
|
| 373 | - */ |
|
| 374 | - public function set_total($total) |
|
| 375 | - { |
|
| 376 | - $this->set('LIN_total', $total); |
|
| 377 | - } |
|
| 378 | - |
|
| 379 | - |
|
| 380 | - /** |
|
| 381 | - * Gets order |
|
| 382 | - * |
|
| 383 | - * @return int |
|
| 384 | - * @throws EE_Error |
|
| 385 | - */ |
|
| 386 | - public function order() |
|
| 387 | - { |
|
| 388 | - return $this->get('LIN_order'); |
|
| 389 | - } |
|
| 390 | - |
|
| 391 | - |
|
| 392 | - /** |
|
| 393 | - * Sets order |
|
| 394 | - * |
|
| 395 | - * @param int $order |
|
| 396 | - * @throws EE_Error |
|
| 397 | - */ |
|
| 398 | - public function set_order($order) |
|
| 399 | - { |
|
| 400 | - $this->set('LIN_order', $order); |
|
| 401 | - } |
|
| 402 | - |
|
| 403 | - |
|
| 404 | - /** |
|
| 405 | - * Gets parent |
|
| 406 | - * |
|
| 407 | - * @return int |
|
| 408 | - * @throws EE_Error |
|
| 409 | - */ |
|
| 410 | - public function parent_ID() |
|
| 411 | - { |
|
| 412 | - return $this->get('LIN_parent'); |
|
| 413 | - } |
|
| 414 | - |
|
| 415 | - |
|
| 416 | - /** |
|
| 417 | - * Sets parent |
|
| 418 | - * |
|
| 419 | - * @param int $parent |
|
| 420 | - * @throws EE_Error |
|
| 421 | - */ |
|
| 422 | - public function set_parent_ID($parent) |
|
| 423 | - { |
|
| 424 | - $this->set('LIN_parent', $parent); |
|
| 425 | - } |
|
| 426 | - |
|
| 427 | - |
|
| 428 | - /** |
|
| 429 | - * Gets type |
|
| 430 | - * |
|
| 431 | - * @return string |
|
| 432 | - * @throws EE_Error |
|
| 433 | - */ |
|
| 434 | - public function type() |
|
| 435 | - { |
|
| 436 | - return $this->get('LIN_type'); |
|
| 437 | - } |
|
| 438 | - |
|
| 439 | - |
|
| 440 | - /** |
|
| 441 | - * Sets type |
|
| 442 | - * |
|
| 443 | - * @param string $type |
|
| 444 | - * @throws EE_Error |
|
| 445 | - */ |
|
| 446 | - public function set_type($type) |
|
| 447 | - { |
|
| 448 | - $this->set('LIN_type', $type); |
|
| 449 | - } |
|
| 450 | - |
|
| 451 | - |
|
| 452 | - /** |
|
| 453 | - * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
| 454 | - * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB |
|
| 455 | - * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
| 456 | - * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
| 457 | - * |
|
| 458 | - * @return EE_Base_Class|EE_Line_Item |
|
| 459 | - * @throws EE_Error |
|
| 460 | - */ |
|
| 461 | - public function parent() |
|
| 462 | - { |
|
| 463 | - return $this->ID() |
|
| 464 | - ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
| 465 | - : $this->_parent; |
|
| 466 | - } |
|
| 467 | - |
|
| 468 | - |
|
| 469 | - /** |
|
| 470 | - * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
| 471 | - * |
|
| 472 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 473 | - * @throws EE_Error |
|
| 474 | - */ |
|
| 475 | - public function children() |
|
| 476 | - { |
|
| 477 | - if ($this->ID()) { |
|
| 478 | - return $this->get_model()->get_all( |
|
| 479 | - array( |
|
| 480 | - array('LIN_parent' => $this->ID()), |
|
| 481 | - 'order_by' => array('LIN_order' => 'ASC'), |
|
| 482 | - ) |
|
| 483 | - ); |
|
| 484 | - } |
|
| 485 | - if (!is_array($this->_children)) { |
|
| 486 | - $this->_children = array(); |
|
| 487 | - } |
|
| 488 | - return $this->_children; |
|
| 489 | - } |
|
| 490 | - |
|
| 491 | - |
|
| 492 | - /** |
|
| 493 | - * Gets code |
|
| 494 | - * |
|
| 495 | - * @return string |
|
| 496 | - * @throws EE_Error |
|
| 497 | - */ |
|
| 498 | - public function code() |
|
| 499 | - { |
|
| 500 | - return $this->get('LIN_code'); |
|
| 501 | - } |
|
| 502 | - |
|
| 503 | - |
|
| 504 | - /** |
|
| 505 | - * Sets code |
|
| 506 | - * |
|
| 507 | - * @param string $code |
|
| 508 | - * @throws EE_Error |
|
| 509 | - */ |
|
| 510 | - public function set_code($code) |
|
| 511 | - { |
|
| 512 | - $this->set('LIN_code', $code); |
|
| 513 | - } |
|
| 514 | - |
|
| 515 | - |
|
| 516 | - /** |
|
| 517 | - * Gets is_taxable |
|
| 518 | - * |
|
| 519 | - * @return boolean |
|
| 520 | - * @throws EE_Error |
|
| 521 | - */ |
|
| 522 | - public function is_taxable() |
|
| 523 | - { |
|
| 524 | - return $this->get('LIN_is_taxable'); |
|
| 525 | - } |
|
| 526 | - |
|
| 527 | - |
|
| 528 | - /** |
|
| 529 | - * Sets is_taxable |
|
| 530 | - * |
|
| 531 | - * @param boolean $is_taxable |
|
| 532 | - * @throws EE_Error |
|
| 533 | - */ |
|
| 534 | - public function set_is_taxable($is_taxable) |
|
| 535 | - { |
|
| 536 | - $this->set('LIN_is_taxable', $is_taxable); |
|
| 537 | - } |
|
| 538 | - |
|
| 539 | - |
|
| 540 | - /** |
|
| 541 | - * Gets the object that this model-joins-to. |
|
| 542 | - * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
| 543 | - * EEM_Promotion_Object |
|
| 544 | - * |
|
| 545 | - * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
| 546 | - * |
|
| 547 | - * @return EE_Base_Class | NULL |
|
| 548 | - * @throws EE_Error |
|
| 549 | - */ |
|
| 550 | - public function get_object() |
|
| 551 | - { |
|
| 552 | - $model_name_of_related_obj = $this->OBJ_type(); |
|
| 553 | - return $this->get_model()->has_relation($model_name_of_related_obj) |
|
| 554 | - ? $this->get_first_related($model_name_of_related_obj) |
|
| 555 | - : null; |
|
| 556 | - } |
|
| 557 | - |
|
| 558 | - |
|
| 559 | - /** |
|
| 560 | - * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
| 561 | - * (IE, if this line item is for a price or something else, will return NULL) |
|
| 562 | - * |
|
| 563 | - * @param array $query_params |
|
| 564 | - * @return EE_Base_Class|EE_Ticket |
|
| 565 | - * @throws EE_Error |
|
| 566 | - */ |
|
| 567 | - public function ticket($query_params = array()) |
|
| 568 | - { |
|
| 569 | - //we're going to assume that when this method is called we always want to receive the attached ticket EVEN if that ticket is archived. This can be overridden via the incoming $query_params argument |
|
| 570 | - $remove_defaults = array('default_where_conditions' => 'none'); |
|
| 571 | - $query_params = array_merge($remove_defaults, $query_params); |
|
| 572 | - return $this->get_first_related('Ticket', $query_params); |
|
| 573 | - } |
|
| 574 | - |
|
| 575 | - |
|
| 576 | - /** |
|
| 577 | - * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
| 578 | - * |
|
| 579 | - * @return EE_Datetime | NULL |
|
| 580 | - * @throws EE_Error |
|
| 581 | - */ |
|
| 582 | - public function get_ticket_datetime() |
|
| 583 | - { |
|
| 584 | - if ($this->OBJ_type() === 'Ticket') { |
|
| 585 | - $ticket = $this->ticket(); |
|
| 586 | - if ($ticket instanceof EE_Ticket) { |
|
| 587 | - $datetime = $ticket->first_datetime(); |
|
| 588 | - if ($datetime instanceof EE_Datetime) { |
|
| 589 | - return $datetime; |
|
| 590 | - } |
|
| 591 | - } |
|
| 592 | - } |
|
| 593 | - return null; |
|
| 594 | - } |
|
| 595 | - |
|
| 596 | - |
|
| 597 | - /** |
|
| 598 | - * Gets the event's name that's related to the ticket, if this is for |
|
| 599 | - * a ticket |
|
| 600 | - * |
|
| 601 | - * @return string |
|
| 602 | - * @throws EE_Error |
|
| 603 | - */ |
|
| 604 | - public function ticket_event_name() |
|
| 605 | - { |
|
| 606 | - $event_name = esc_html__('Unknown', 'event_espresso'); |
|
| 607 | - $event = $this->ticket_event(); |
|
| 608 | - if ($event instanceof EE_Event) { |
|
| 609 | - $event_name = $event->name(); |
|
| 610 | - } |
|
| 611 | - return $event_name; |
|
| 612 | - } |
|
| 613 | - |
|
| 614 | - |
|
| 615 | - /** |
|
| 616 | - * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
| 617 | - * |
|
| 618 | - * @return EE_Event|null |
|
| 619 | - * @throws EE_Error |
|
| 620 | - */ |
|
| 621 | - public function ticket_event() |
|
| 622 | - { |
|
| 623 | - $event = null; |
|
| 624 | - $ticket = $this->ticket(); |
|
| 625 | - if ($ticket instanceof EE_Ticket) { |
|
| 626 | - $datetime = $ticket->first_datetime(); |
|
| 627 | - if ($datetime instanceof EE_Datetime) { |
|
| 628 | - $event = $datetime->event(); |
|
| 629 | - } |
|
| 630 | - } |
|
| 631 | - return $event; |
|
| 632 | - } |
|
| 633 | - |
|
| 634 | - |
|
| 635 | - /** |
|
| 636 | - * Gets the first datetime for this lien item, assuming it's for a ticket |
|
| 637 | - * |
|
| 638 | - * @param string $date_format |
|
| 639 | - * @param string $time_format |
|
| 640 | - * @return string |
|
| 641 | - * @throws EE_Error |
|
| 642 | - */ |
|
| 643 | - public function ticket_datetime_start($date_format = '', $time_format = '') |
|
| 644 | - { |
|
| 645 | - $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
| 646 | - $datetime = $this->get_ticket_datetime(); |
|
| 647 | - if ($datetime) { |
|
| 648 | - $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
| 649 | - } |
|
| 650 | - return $first_datetime_string; |
|
| 651 | - } |
|
| 652 | - |
|
| 653 | - |
|
| 654 | - /** |
|
| 655 | - * Adds the line item as a child to this line item. If there is another child line |
|
| 656 | - * item with the same LIN_code, it is overwritten by this new one |
|
| 657 | - * |
|
| 658 | - * @param EEI_Line_Item $line_item |
|
| 659 | - * @param bool $set_order |
|
| 660 | - * @return bool success |
|
| 661 | - * @throws EE_Error |
|
| 662 | - */ |
|
| 663 | - public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
| 664 | - { |
|
| 665 | - // should we calculate the LIN_order for this line item ? |
|
| 666 | - if ($set_order || $line_item->order() === null) { |
|
| 667 | - $line_item->set_order(count($this->children())); |
|
| 668 | - } |
|
| 669 | - if ($this->ID()) { |
|
| 670 | - //check for any duplicate line items (with the same code), if so, this replaces it |
|
| 671 | - $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
| 672 | - if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
| 673 | - $this->delete_child_line_item($line_item_with_same_code->code()); |
|
| 674 | - } |
|
| 675 | - $line_item->set_parent_ID($this->ID()); |
|
| 676 | - if ($this->TXN_ID()) { |
|
| 677 | - $line_item->set_TXN_ID($this->TXN_ID()); |
|
| 678 | - } |
|
| 679 | - return $line_item->save(); |
|
| 680 | - } |
|
| 681 | - $this->_children[$line_item->code()] = $line_item; |
|
| 682 | - if ($line_item->parent() !== $this) { |
|
| 683 | - $line_item->set_parent($this); |
|
| 684 | - } |
|
| 685 | - return true; |
|
| 686 | - } |
|
| 687 | - |
|
| 688 | - |
|
| 689 | - /** |
|
| 690 | - * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
| 691 | - * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
| 692 | - * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
| 693 | - * the EE_Line_Item::_parent property. |
|
| 694 | - * |
|
| 695 | - * @param EE_Line_Item $line_item |
|
| 696 | - * @throws EE_Error |
|
| 697 | - */ |
|
| 698 | - public function set_parent($line_item) |
|
| 699 | - { |
|
| 700 | - if ($this->ID()) { |
|
| 701 | - if (!$line_item->ID()) { |
|
| 702 | - $line_item->save(); |
|
| 703 | - } |
|
| 704 | - $this->set_parent_ID($line_item->ID()); |
|
| 705 | - $this->save(); |
|
| 706 | - } else { |
|
| 707 | - $this->_parent = $line_item; |
|
| 708 | - $this->set_parent_ID($line_item->ID()); |
|
| 709 | - } |
|
| 710 | - } |
|
| 711 | - |
|
| 712 | - |
|
| 713 | - /** |
|
| 714 | - * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
| 715 | - * you can modify this child line item and the parent (this object) can know about them |
|
| 716 | - * because it also has a reference to that line item |
|
| 717 | - * |
|
| 718 | - * @param string $code |
|
| 719 | - * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 720 | - * @throws EE_Error |
|
| 721 | - */ |
|
| 722 | - public function get_child_line_item($code) |
|
| 723 | - { |
|
| 724 | - if ($this->ID()) { |
|
| 725 | - return $this->get_model()->get_one( |
|
| 726 | - array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
| 727 | - ); |
|
| 728 | - } |
|
| 729 | - return isset($this->_children[$code]) |
|
| 730 | - ? $this->_children[$code] |
|
| 731 | - : null; |
|
| 732 | - } |
|
| 733 | - |
|
| 734 | - |
|
| 735 | - /** |
|
| 736 | - * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
| 737 | - * cached on it) |
|
| 738 | - * |
|
| 739 | - * @return int |
|
| 740 | - * @throws EE_Error |
|
| 741 | - */ |
|
| 742 | - public function delete_children_line_items() |
|
| 743 | - { |
|
| 744 | - if ($this->ID()) { |
|
| 745 | - return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
| 746 | - } |
|
| 747 | - $count = count($this->_children); |
|
| 748 | - $this->_children = array(); |
|
| 749 | - return $count; |
|
| 750 | - } |
|
| 751 | - |
|
| 752 | - |
|
| 753 | - /** |
|
| 754 | - * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
| 755 | - * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
| 756 | - * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
| 757 | - * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
| 758 | - * deleted) |
|
| 759 | - * |
|
| 760 | - * @param string $code |
|
| 761 | - * @param bool $stop_search_once_found |
|
| 762 | - * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
| 763 | - * the DB yet) |
|
| 764 | - * @throws EE_Error |
|
| 765 | - */ |
|
| 766 | - public function delete_child_line_item($code, $stop_search_once_found = true) |
|
| 767 | - { |
|
| 768 | - if ($this->ID()) { |
|
| 769 | - $items_deleted = 0; |
|
| 770 | - if ($this->code() === $code) { |
|
| 771 | - $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
| 772 | - $items_deleted += (int)$this->delete(); |
|
| 773 | - if ($stop_search_once_found) { |
|
| 774 | - return $items_deleted; |
|
| 775 | - } |
|
| 776 | - } |
|
| 777 | - foreach ($this->children() as $child_line_item) { |
|
| 778 | - $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
| 779 | - } |
|
| 780 | - return $items_deleted; |
|
| 781 | - } |
|
| 782 | - if (isset($this->_children[$code])) { |
|
| 783 | - unset($this->_children[$code]); |
|
| 784 | - return 1; |
|
| 785 | - } |
|
| 786 | - return 0; |
|
| 787 | - } |
|
| 788 | - |
|
| 789 | - |
|
| 790 | - /** |
|
| 791 | - * If this line item is in the database, is of the type subtotal, and |
|
| 792 | - * has no children, why do we have it? It should be deleted so this function |
|
| 793 | - * does that |
|
| 794 | - * |
|
| 795 | - * @return boolean |
|
| 796 | - * @throws EE_Error |
|
| 797 | - */ |
|
| 798 | - public function delete_if_childless_subtotal() |
|
| 799 | - { |
|
| 800 | - if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && !$this->children()) { |
|
| 801 | - return $this->delete(); |
|
| 802 | - } |
|
| 803 | - return false; |
|
| 804 | - } |
|
| 805 | - |
|
| 806 | - |
|
| 807 | - /** |
|
| 808 | - * Creates a code and returns a string. doesn't assign the code to this model object |
|
| 809 | - * |
|
| 810 | - * @return string |
|
| 811 | - * @throws EE_Error |
|
| 812 | - */ |
|
| 813 | - public function generate_code() |
|
| 814 | - { |
|
| 815 | - // each line item in the cart requires a unique identifier |
|
| 816 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
| 817 | - } |
|
| 818 | - |
|
| 819 | - |
|
| 820 | - /** |
|
| 821 | - * @return bool |
|
| 822 | - * @throws EE_Error |
|
| 823 | - */ |
|
| 824 | - public function is_tax() |
|
| 825 | - { |
|
| 826 | - return $this->type() === EEM_Line_Item::type_tax; |
|
| 827 | - } |
|
| 828 | - |
|
| 829 | - |
|
| 830 | - /** |
|
| 831 | - * @return bool |
|
| 832 | - * @throws EE_Error |
|
| 833 | - */ |
|
| 834 | - public function is_tax_sub_total() |
|
| 835 | - { |
|
| 836 | - return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
| 837 | - } |
|
| 838 | - |
|
| 839 | - |
|
| 840 | - /** |
|
| 841 | - * @return bool |
|
| 842 | - * @throws EE_Error |
|
| 843 | - */ |
|
| 844 | - public function is_line_item() |
|
| 845 | - { |
|
| 846 | - return $this->type() === EEM_Line_Item::type_line_item; |
|
| 847 | - } |
|
| 848 | - |
|
| 849 | - |
|
| 850 | - /** |
|
| 851 | - * @return bool |
|
| 852 | - * @throws EE_Error |
|
| 853 | - */ |
|
| 854 | - public function is_sub_line_item() |
|
| 855 | - { |
|
| 856 | - return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
| 857 | - } |
|
| 858 | - |
|
| 859 | - |
|
| 860 | - /** |
|
| 861 | - * @return bool |
|
| 862 | - * @throws EE_Error |
|
| 863 | - */ |
|
| 864 | - public function is_sub_total() |
|
| 865 | - { |
|
| 866 | - return $this->type() === EEM_Line_Item::type_sub_total; |
|
| 867 | - } |
|
| 868 | - |
|
| 869 | - |
|
| 870 | - /** |
|
| 871 | - * Whether or not this line item is a cancellation line item |
|
| 872 | - * |
|
| 873 | - * @return boolean |
|
| 874 | - * @throws EE_Error |
|
| 875 | - */ |
|
| 876 | - public function is_cancellation() |
|
| 877 | - { |
|
| 878 | - return EEM_Line_Item::type_cancellation === $this->type(); |
|
| 879 | - } |
|
| 880 | - |
|
| 881 | - |
|
| 882 | - /** |
|
| 883 | - * @return bool |
|
| 884 | - * @throws EE_Error |
|
| 885 | - */ |
|
| 886 | - public function is_total() |
|
| 887 | - { |
|
| 888 | - return $this->type() === EEM_Line_Item::type_total; |
|
| 889 | - } |
|
| 890 | - |
|
| 891 | - |
|
| 892 | - /** |
|
| 893 | - * @return bool |
|
| 894 | - * @throws EE_Error |
|
| 895 | - */ |
|
| 896 | - public function is_cancelled() |
|
| 897 | - { |
|
| 898 | - return $this->type() === EEM_Line_Item::type_cancellation; |
|
| 899 | - } |
|
| 900 | - |
|
| 901 | - |
|
| 902 | - /** |
|
| 903 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
| 904 | - * @throws EE_Error |
|
| 905 | - */ |
|
| 906 | - public function unit_price_no_code() |
|
| 907 | - { |
|
| 908 | - return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
| 909 | - } |
|
| 910 | - |
|
| 911 | - |
|
| 912 | - /** |
|
| 913 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
| 914 | - * @throws EE_Error |
|
| 915 | - */ |
|
| 916 | - public function total_no_code() |
|
| 917 | - { |
|
| 918 | - return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
| 919 | - } |
|
| 920 | - |
|
| 921 | - |
|
| 922 | - /** |
|
| 923 | - * Gets the final total on this item, taking taxes into account. |
|
| 924 | - * Has the side-effect of setting the sub-total as it was just calculated. |
|
| 925 | - * If this is used on a grand-total line item, also updates the transaction's |
|
| 926 | - * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
| 927 | - * want to change a persistable transaction with info from a non-persistent line item) |
|
| 928 | - * |
|
| 929 | - * @return float |
|
| 930 | - * @throws EE_Error |
|
| 931 | - * @throws InvalidArgumentException |
|
| 932 | - * @throws InvalidInterfaceException |
|
| 933 | - * @throws InvalidDataTypeException |
|
| 934 | - */ |
|
| 935 | - public function recalculate_total_including_taxes() |
|
| 936 | - { |
|
| 937 | - $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
| 938 | - $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
| 939 | - $total = $pre_tax_total + $tax_total; |
|
| 940 | - // no negative totals plz |
|
| 941 | - $total = max($total, 0); |
|
| 942 | - $this->set_total($total); |
|
| 943 | - //only update the related transaction's total |
|
| 944 | - //if we intend to save this line item and its a grand total |
|
| 945 | - if ( |
|
| 946 | - $this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
| 947 | - && $this->transaction() |
|
| 948 | - instanceof |
|
| 949 | - EE_Transaction |
|
| 950 | - ) { |
|
| 951 | - $this->transaction()->set_total($total); |
|
| 952 | - if ($this->transaction()->ID()) { |
|
| 953 | - $this->transaction()->save(); |
|
| 954 | - } |
|
| 955 | - } |
|
| 956 | - $this->maybe_save(); |
|
| 957 | - return $total; |
|
| 958 | - } |
|
| 959 | - |
|
| 960 | - |
|
| 961 | - /** |
|
| 962 | - * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
| 963 | - * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
| 964 | - * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
| 965 | - * when this is called on the grand total |
|
| 966 | - * |
|
| 967 | - * @return float |
|
| 968 | - * @throws InvalidArgumentException |
|
| 969 | - * @throws InvalidInterfaceException |
|
| 970 | - * @throws InvalidDataTypeException |
|
| 971 | - * @throws EE_Error |
|
| 972 | - */ |
|
| 973 | - public function recalculate_pre_tax_total() |
|
| 974 | - { |
|
| 975 | - $total = 0; |
|
| 976 | - $my_children = $this->children(); |
|
| 977 | - $has_children = !empty($my_children); |
|
| 978 | - if ($has_children && $this->is_line_item()) { |
|
| 979 | - $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
| 980 | - } elseif (!$has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 981 | - $total = $this->unit_price() * $this->quantity(); |
|
| 982 | - } elseif ($this->is_sub_total() || $this->is_total()) { |
|
| 983 | - $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
| 984 | - } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
| 985 | - // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
| 986 | - return 0; |
|
| 987 | - } |
|
| 988 | - // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
| 989 | - if ( |
|
| 990 | - !$this->is_line_item() && !$this->is_sub_line_item() && !$this->is_cancellation() |
|
| 991 | - ) { |
|
| 992 | - if ($this->OBJ_type() !== 'Event') { |
|
| 993 | - $this->set_quantity(1); |
|
| 994 | - } |
|
| 995 | - if (!$this->is_percent()) { |
|
| 996 | - $this->set_unit_price($total); |
|
| 997 | - } |
|
| 998 | - } |
|
| 999 | - //we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
| 1000 | - //so it ought to be |
|
| 1001 | - if (!$this->is_total()) { |
|
| 1002 | - $this->set_total($total); |
|
| 1003 | - //if not a percent line item, make sure we keep the unit price in sync |
|
| 1004 | - if ( |
|
| 1005 | - $has_children |
|
| 1006 | - && $this->is_line_item() |
|
| 1007 | - && !$this->is_percent() |
|
| 1008 | - ) { |
|
| 1009 | - if ($this->quantity() === 0) { |
|
| 1010 | - $new_unit_price = 0; |
|
| 1011 | - } else { |
|
| 1012 | - $new_unit_price = $this->total() / $this->quantity(); |
|
| 1013 | - } |
|
| 1014 | - $this->set_unit_price($new_unit_price); |
|
| 1015 | - } |
|
| 1016 | - $this->maybe_save(); |
|
| 1017 | - } |
|
| 1018 | - return $total; |
|
| 1019 | - } |
|
| 1020 | - |
|
| 1021 | - |
|
| 1022 | - /** |
|
| 1023 | - * Calculates the pretax total when this line item is a subtotal or total line item. |
|
| 1024 | - * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
| 1025 | - * will calculate their total based on the un-rounded total we're working with so far, and |
|
| 1026 | - * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
| 1027 | - * |
|
| 1028 | - * @param float $calculated_total_so_far |
|
| 1029 | - * @param EE_Line_Item[] $my_children |
|
| 1030 | - * @return float |
|
| 1031 | - * @throws InvalidArgumentException |
|
| 1032 | - * @throws InvalidInterfaceException |
|
| 1033 | - * @throws InvalidDataTypeException |
|
| 1034 | - * @throws EE_Error |
|
| 1035 | - */ |
|
| 1036 | - protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
| 1037 | - { |
|
| 1038 | - if ($my_children === null) { |
|
| 1039 | - $my_children = $this->children(); |
|
| 1040 | - } |
|
| 1041 | - $subtotal_quantity = 0; |
|
| 1042 | - //get the total of all its children |
|
| 1043 | - foreach ($my_children as $child_line_item) { |
|
| 1044 | - if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) { |
|
| 1045 | - // percentage line items are based on total so far |
|
| 1046 | - if ($child_line_item->is_percent()) { |
|
| 1047 | - //round as we go so that the line items add up ok |
|
| 1048 | - $percent_total = round( |
|
| 1049 | - $calculated_total_so_far * $child_line_item->percent() / 100, |
|
| 1050 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1051 | - ); |
|
| 1052 | - $child_line_item->set_total($percent_total); |
|
| 1053 | - //so far all percent line items should have a quantity of 1 |
|
| 1054 | - //(ie, no double percent discounts. Although that might be requested someday) |
|
| 1055 | - $child_line_item->set_quantity(1); |
|
| 1056 | - $child_line_item->maybe_save(); |
|
| 1057 | - $calculated_total_so_far += $percent_total; |
|
| 1058 | - } else { |
|
| 1059 | - //verify flat sub-line-item quantities match their parent |
|
| 1060 | - if ($child_line_item->is_sub_line_item()) { |
|
| 1061 | - $child_line_item->set_quantity($this->quantity()); |
|
| 1062 | - } |
|
| 1063 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1064 | - $subtotal_quantity += $child_line_item->quantity(); |
|
| 1065 | - } |
|
| 1066 | - } |
|
| 1067 | - } |
|
| 1068 | - if ($this->is_sub_total()) { |
|
| 1069 | - // no negative totals plz |
|
| 1070 | - $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
| 1071 | - $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
| 1072 | - $this->set_quantity($subtotal_quantity); |
|
| 1073 | - $this->maybe_save(); |
|
| 1074 | - } |
|
| 1075 | - return $calculated_total_so_far; |
|
| 1076 | - } |
|
| 1077 | - |
|
| 1078 | - |
|
| 1079 | - /** |
|
| 1080 | - * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
| 1081 | - * (where each sub-line-item is applied to the base price for the line item |
|
| 1082 | - * and the result is immediately rounded, rather than summing all the sub-line-items |
|
| 1083 | - * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
| 1084 | - * |
|
| 1085 | - * @param float $calculated_total_so_far |
|
| 1086 | - * @param EE_Line_Item[] $my_children |
|
| 1087 | - * @return float |
|
| 1088 | - * @throws InvalidArgumentException |
|
| 1089 | - * @throws InvalidInterfaceException |
|
| 1090 | - * @throws InvalidDataTypeException |
|
| 1091 | - * @throws EE_Error |
|
| 1092 | - */ |
|
| 1093 | - protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
| 1094 | - { |
|
| 1095 | - if ($my_children === null) { |
|
| 1096 | - $my_children = $this->children(); |
|
| 1097 | - } |
|
| 1098 | - //we need to keep track of the running total for a single item, |
|
| 1099 | - //because we need to round as we go |
|
| 1100 | - $unit_price_for_total = 0; |
|
| 1101 | - $quantity_for_total = 1; |
|
| 1102 | - //get the total of all its children |
|
| 1103 | - foreach ($my_children as $child_line_item) { |
|
| 1104 | - if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) { |
|
| 1105 | - if ($child_line_item->is_percent()) { |
|
| 1106 | - //it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
| 1107 | - //not total multiplied by percent, because that ignores rounding along-the-way |
|
| 1108 | - $percent_unit_price = round( |
|
| 1109 | - $unit_price_for_total * $child_line_item->percent() / 100, |
|
| 1110 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1111 | - ); |
|
| 1112 | - $percent_total = $percent_unit_price * $quantity_for_total; |
|
| 1113 | - $child_line_item->set_total($percent_total); |
|
| 1114 | - //so far all percent line items should have a quantity of 1 |
|
| 1115 | - //(ie, no double percent discounts. Although that might be requested someday) |
|
| 1116 | - $child_line_item->set_quantity(1); |
|
| 1117 | - $child_line_item->maybe_save(); |
|
| 1118 | - $calculated_total_so_far += $percent_total; |
|
| 1119 | - $unit_price_for_total += $percent_unit_price; |
|
| 1120 | - } else { |
|
| 1121 | - //verify flat sub-line-item quantities match their parent |
|
| 1122 | - if ($child_line_item->is_sub_line_item()) { |
|
| 1123 | - $child_line_item->set_quantity($this->quantity()); |
|
| 1124 | - } |
|
| 1125 | - $quantity_for_total = $child_line_item->quantity(); |
|
| 1126 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1127 | - $unit_price_for_total += $child_line_item->unit_price(); |
|
| 1128 | - } |
|
| 1129 | - } |
|
| 1130 | - } |
|
| 1131 | - return $calculated_total_so_far; |
|
| 1132 | - } |
|
| 1133 | - |
|
| 1134 | - |
|
| 1135 | - /** |
|
| 1136 | - * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
| 1137 | - * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
| 1138 | - * and tax sub-total if already in the DB |
|
| 1139 | - * |
|
| 1140 | - * @return float |
|
| 1141 | - * @throws EE_Error |
|
| 1142 | - */ |
|
| 1143 | - public function recalculate_taxes_and_tax_total() |
|
| 1144 | - { |
|
| 1145 | - //get all taxes |
|
| 1146 | - $taxes = $this->tax_descendants(); |
|
| 1147 | - //calculate the pretax total |
|
| 1148 | - $taxable_total = $this->taxable_total(); |
|
| 1149 | - $tax_total = 0; |
|
| 1150 | - foreach ($taxes as $tax) { |
|
| 1151 | - $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
| 1152 | - //remember the total on this line item |
|
| 1153 | - $tax->set_total($total_on_this_tax); |
|
| 1154 | - $tax->maybe_save(); |
|
| 1155 | - $tax_total += $tax->total(); |
|
| 1156 | - } |
|
| 1157 | - $this->_recalculate_tax_sub_total(); |
|
| 1158 | - return $tax_total; |
|
| 1159 | - } |
|
| 1160 | - |
|
| 1161 | - |
|
| 1162 | - /** |
|
| 1163 | - * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
| 1164 | - * |
|
| 1165 | - * @return void |
|
| 1166 | - * @throws EE_Error |
|
| 1167 | - */ |
|
| 1168 | - private function _recalculate_tax_sub_total() |
|
| 1169 | - { |
|
| 1170 | - if ($this->is_tax_sub_total()) { |
|
| 1171 | - $total = 0; |
|
| 1172 | - $total_percent = 0; |
|
| 1173 | - //simply loop through all its children (which should be taxes) and sum their total |
|
| 1174 | - foreach ($this->children() as $child_tax) { |
|
| 1175 | - if ($child_tax instanceof EE_Line_Item) { |
|
| 1176 | - $total += $child_tax->total(); |
|
| 1177 | - $total_percent += $child_tax->percent(); |
|
| 1178 | - } |
|
| 1179 | - } |
|
| 1180 | - $this->set_total($total); |
|
| 1181 | - $this->set_percent($total_percent); |
|
| 1182 | - $this->maybe_save(); |
|
| 1183 | - } elseif ($this->is_total()) { |
|
| 1184 | - foreach ($this->children() as $maybe_tax_subtotal) { |
|
| 1185 | - if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
| 1186 | - $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
| 1187 | - } |
|
| 1188 | - } |
|
| 1189 | - } |
|
| 1190 | - } |
|
| 1191 | - |
|
| 1192 | - |
|
| 1193 | - /** |
|
| 1194 | - * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
| 1195 | - * recalculate_taxes_and_total |
|
| 1196 | - * |
|
| 1197 | - * @return float |
|
| 1198 | - * @throws EE_Error |
|
| 1199 | - */ |
|
| 1200 | - public function get_total_tax() |
|
| 1201 | - { |
|
| 1202 | - $this->_recalculate_tax_sub_total(); |
|
| 1203 | - $total = 0; |
|
| 1204 | - foreach ($this->tax_descendants() as $tax_line_item) { |
|
| 1205 | - if ($tax_line_item instanceof EE_Line_Item) { |
|
| 1206 | - $total += $tax_line_item->total(); |
|
| 1207 | - } |
|
| 1208 | - } |
|
| 1209 | - return $total; |
|
| 1210 | - } |
|
| 1211 | - |
|
| 1212 | - |
|
| 1213 | - /** |
|
| 1214 | - * Gets the total for all the items purchased only |
|
| 1215 | - * |
|
| 1216 | - * @return float |
|
| 1217 | - * @throws EE_Error |
|
| 1218 | - */ |
|
| 1219 | - public function get_items_total() |
|
| 1220 | - { |
|
| 1221 | - //by default, let's make sure we're consistent with the existing line item |
|
| 1222 | - if ($this->is_total()) { |
|
| 1223 | - $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
| 1224 | - if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
| 1225 | - return $pretax_subtotal_li->total(); |
|
| 1226 | - } |
|
| 1227 | - } |
|
| 1228 | - $total = 0; |
|
| 1229 | - foreach ($this->get_items() as $item) { |
|
| 1230 | - if ($item instanceof EE_Line_Item) { |
|
| 1231 | - $total += $item->total(); |
|
| 1232 | - } |
|
| 1233 | - } |
|
| 1234 | - return $total; |
|
| 1235 | - } |
|
| 1236 | - |
|
| 1237 | - |
|
| 1238 | - /** |
|
| 1239 | - * Gets all the descendants (ie, children or children of children etc) that |
|
| 1240 | - * are of the type 'tax' |
|
| 1241 | - * |
|
| 1242 | - * @return EE_Line_Item[] |
|
| 1243 | - */ |
|
| 1244 | - public function tax_descendants() |
|
| 1245 | - { |
|
| 1246 | - return EEH_Line_Item::get_tax_descendants($this); |
|
| 1247 | - } |
|
| 1248 | - |
|
| 1249 | - |
|
| 1250 | - /** |
|
| 1251 | - * Gets all the real items purchased which are children of this item |
|
| 1252 | - * |
|
| 1253 | - * @return EE_Line_Item[] |
|
| 1254 | - */ |
|
| 1255 | - public function get_items() |
|
| 1256 | - { |
|
| 1257 | - return EEH_Line_Item::get_line_item_descendants($this); |
|
| 1258 | - } |
|
| 1259 | - |
|
| 1260 | - |
|
| 1261 | - /** |
|
| 1262 | - * Returns the amount taxable among this line item's children (or if it has no children, |
|
| 1263 | - * how much of it is taxable). Does not recalculate totals or subtotals. |
|
| 1264 | - * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
| 1265 | - * but there is a "Taxable" discount), returns 0. |
|
| 1266 | - * |
|
| 1267 | - * @return float |
|
| 1268 | - * @throws EE_Error |
|
| 1269 | - */ |
|
| 1270 | - public function taxable_total() |
|
| 1271 | - { |
|
| 1272 | - $total = 0; |
|
| 1273 | - if ($this->children()) { |
|
| 1274 | - foreach ($this->children() as $child_line_item) { |
|
| 1275 | - if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
| 1276 | - //if it's a percent item, only take into account the percent |
|
| 1277 | - //that's taxable too (the taxable total so far) |
|
| 1278 | - if ($child_line_item->is_percent()) { |
|
| 1279 | - $total += ($total * $child_line_item->percent() / 100); |
|
| 1280 | - } else { |
|
| 1281 | - $total += $child_line_item->total(); |
|
| 1282 | - } |
|
| 1283 | - } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
| 1284 | - $total += $child_line_item->taxable_total(); |
|
| 1285 | - } |
|
| 1286 | - } |
|
| 1287 | - } |
|
| 1288 | - return max($total, 0); |
|
| 1289 | - } |
|
| 1290 | - |
|
| 1291 | - |
|
| 1292 | - /** |
|
| 1293 | - * Gets the transaction for this line item |
|
| 1294 | - * |
|
| 1295 | - * @return EE_Base_Class|EE_Transaction |
|
| 1296 | - * @throws EE_Error |
|
| 1297 | - */ |
|
| 1298 | - public function transaction() |
|
| 1299 | - { |
|
| 1300 | - return $this->get_first_related('Transaction'); |
|
| 1301 | - } |
|
| 1302 | - |
|
| 1303 | - |
|
| 1304 | - /** |
|
| 1305 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1306 | - * Because there currently is no proper parent-child relation on the model, |
|
| 1307 | - * save_this_and_cached() will NOT save the descendants. |
|
| 1308 | - * Also sets the transaction on this line item and all its descendants before saving |
|
| 1309 | - * |
|
| 1310 | - * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
| 1311 | - * @return int count of items saved |
|
| 1312 | - * @throws EE_Error |
|
| 1313 | - */ |
|
| 1314 | - public function save_this_and_descendants_to_txn($txn_id = null) |
|
| 1315 | - { |
|
| 1316 | - $count = 0; |
|
| 1317 | - if (!$txn_id) { |
|
| 1318 | - $txn_id = $this->TXN_ID(); |
|
| 1319 | - } |
|
| 1320 | - $this->set_TXN_ID($txn_id); |
|
| 1321 | - $children = $this->children(); |
|
| 1322 | - $count += $this->save() |
|
| 1323 | - ? 1 |
|
| 1324 | - : 0; |
|
| 1325 | - foreach ($children as $child_line_item) { |
|
| 1326 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1327 | - $child_line_item->set_parent_ID($this->ID()); |
|
| 1328 | - $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
| 1329 | - } |
|
| 1330 | - } |
|
| 1331 | - return $count; |
|
| 1332 | - } |
|
| 1333 | - |
|
| 1334 | - |
|
| 1335 | - /** |
|
| 1336 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1337 | - * |
|
| 1338 | - * @return int count of items saved |
|
| 1339 | - * @throws EE_Error |
|
| 1340 | - */ |
|
| 1341 | - public function save_this_and_descendants() |
|
| 1342 | - { |
|
| 1343 | - $count = 0; |
|
| 1344 | - $children = $this->children(); |
|
| 1345 | - $count += $this->save() |
|
| 1346 | - ? 1 |
|
| 1347 | - : 0; |
|
| 1348 | - foreach ($children as $child_line_item) { |
|
| 1349 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1350 | - $child_line_item->set_parent_ID($this->ID()); |
|
| 1351 | - $count += $child_line_item->save_this_and_descendants(); |
|
| 1352 | - } |
|
| 1353 | - } |
|
| 1354 | - return $count; |
|
| 1355 | - } |
|
| 1356 | - |
|
| 1357 | - |
|
| 1358 | - /** |
|
| 1359 | - * returns the cancellation line item if this item was cancelled |
|
| 1360 | - * |
|
| 1361 | - * @return EE_Line_Item[] |
|
| 1362 | - * @throws InvalidArgumentException |
|
| 1363 | - * @throws InvalidInterfaceException |
|
| 1364 | - * @throws InvalidDataTypeException |
|
| 1365 | - * @throws ReflectionException |
|
| 1366 | - * @throws EE_Error |
|
| 1367 | - */ |
|
| 1368 | - public function get_cancellations() |
|
| 1369 | - { |
|
| 1370 | - EE_Registry::instance()->load_helper('Line_Item'); |
|
| 1371 | - return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
| 1372 | - } |
|
| 1373 | - |
|
| 1374 | - |
|
| 1375 | - /** |
|
| 1376 | - * If this item has an ID, then this saves it again to update the db |
|
| 1377 | - * |
|
| 1378 | - * @return int count of items saved |
|
| 1379 | - * @throws EE_Error |
|
| 1380 | - */ |
|
| 1381 | - public function maybe_save() |
|
| 1382 | - { |
|
| 1383 | - if ($this->ID()) { |
|
| 1384 | - return $this->save(); |
|
| 1385 | - } |
|
| 1386 | - return false; |
|
| 1387 | - } |
|
| 1388 | - |
|
| 1389 | - |
|
| 1390 | - /** |
|
| 1391 | - * clears the cached children and parent from the line item |
|
| 1392 | - * |
|
| 1393 | - * @return void |
|
| 1394 | - */ |
|
| 1395 | - public function clear_related_line_item_cache() |
|
| 1396 | - { |
|
| 1397 | - $this->_children = array(); |
|
| 1398 | - $this->_parent = null; |
|
| 1399 | - } |
|
| 1400 | - |
|
| 1401 | - |
|
| 1402 | - /** |
|
| 1403 | - * @param bool $raw |
|
| 1404 | - * @return int |
|
| 1405 | - * @throws EE_Error |
|
| 1406 | - */ |
|
| 1407 | - public function timestamp($raw = false) |
|
| 1408 | - { |
|
| 1409 | - return $raw |
|
| 1410 | - ? $this->get_raw('LIN_timestamp') |
|
| 1411 | - : $this->get('LIN_timestamp'); |
|
| 1412 | - } |
|
| 1413 | - |
|
| 1414 | - |
|
| 1415 | - |
|
| 1416 | - |
|
| 1417 | - /************************* DEPRECATED *************************/ |
|
| 1418 | - /** |
|
| 1419 | - * @deprecated 4.6.0 |
|
| 1420 | - * @param string $type one of the constants on EEM_Line_Item |
|
| 1421 | - * @return EE_Line_Item[] |
|
| 1422 | - */ |
|
| 1423 | - protected function _get_descendants_of_type($type) |
|
| 1424 | - { |
|
| 1425 | - EE_Error::doing_it_wrong( |
|
| 1426 | - 'EE_Line_Item::_get_descendants_of_type()', |
|
| 1427 | - __('Method replaced with EEH_Line_Item::get_descendants_of_type()', 'event_espresso'), '4.6.0' |
|
| 1428 | - ); |
|
| 1429 | - return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
| 1430 | - } |
|
| 1431 | - |
|
| 1432 | - |
|
| 1433 | - /** |
|
| 1434 | - * @deprecated 4.6.0 |
|
| 1435 | - * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1436 | - * @return EE_Line_Item |
|
| 1437 | - */ |
|
| 1438 | - public function get_nearest_descendant_of_type($type) |
|
| 1439 | - { |
|
| 1440 | - EE_Error::doing_it_wrong( |
|
| 1441 | - 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
| 1442 | - __('Method replaced with EEH_Line_Item::get_nearest_descendant_of_type()', 'event_espresso'), '4.6.0' |
|
| 1443 | - ); |
|
| 1444 | - return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
| 1445 | - } |
|
| 20 | + /** |
|
| 21 | + * for children line items (currently not a normal relation) |
|
| 22 | + * |
|
| 23 | + * @type EE_Line_Item[] |
|
| 24 | + */ |
|
| 25 | + protected $_children = array(); |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * for the parent line item |
|
| 29 | + * |
|
| 30 | + * @var EE_Line_Item |
|
| 31 | + */ |
|
| 32 | + protected $_parent; |
|
| 33 | + |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * |
|
| 37 | + * @param array $props_n_values incoming values |
|
| 38 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 39 | + * used.) |
|
| 40 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 41 | + * date_format and the second value is the time format |
|
| 42 | + * @return EE_Line_Item |
|
| 43 | + * @throws EE_Error |
|
| 44 | + */ |
|
| 45 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
| 46 | + { |
|
| 47 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 48 | + return $has_object |
|
| 49 | + ? $has_object |
|
| 50 | + : new self($props_n_values, false, $timezone); |
|
| 51 | + } |
|
| 52 | + |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * @param array $props_n_values incoming values from the database |
|
| 56 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 57 | + * the website will be used. |
|
| 58 | + * @return EE_Line_Item |
|
| 59 | + * @throws EE_Error |
|
| 60 | + */ |
|
| 61 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
| 62 | + { |
|
| 63 | + return new self($props_n_values, true, $timezone); |
|
| 64 | + } |
|
| 65 | + |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * Adds some defaults if they're not specified |
|
| 69 | + * |
|
| 70 | + * @param array $fieldValues |
|
| 71 | + * @param bool $bydb |
|
| 72 | + * @param string $timezone |
|
| 73 | + * @throws EE_Error |
|
| 74 | + */ |
|
| 75 | + protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
| 76 | + { |
|
| 77 | + parent::__construct($fieldValues, $bydb, $timezone); |
|
| 78 | + if (!$this->get('LIN_code')) { |
|
| 79 | + $this->set_code($this->generate_code()); |
|
| 80 | + } |
|
| 81 | + } |
|
| 82 | + |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * Gets ID |
|
| 86 | + * |
|
| 87 | + * @return int |
|
| 88 | + * @throws EE_Error |
|
| 89 | + */ |
|
| 90 | + public function ID() |
|
| 91 | + { |
|
| 92 | + return $this->get('LIN_ID'); |
|
| 93 | + } |
|
| 94 | + |
|
| 95 | + |
|
| 96 | + /** |
|
| 97 | + * Gets TXN_ID |
|
| 98 | + * |
|
| 99 | + * @return int |
|
| 100 | + * @throws EE_Error |
|
| 101 | + */ |
|
| 102 | + public function TXN_ID() |
|
| 103 | + { |
|
| 104 | + return $this->get('TXN_ID'); |
|
| 105 | + } |
|
| 106 | + |
|
| 107 | + |
|
| 108 | + /** |
|
| 109 | + * Sets TXN_ID |
|
| 110 | + * |
|
| 111 | + * @param int $TXN_ID |
|
| 112 | + * @throws EE_Error |
|
| 113 | + */ |
|
| 114 | + public function set_TXN_ID($TXN_ID) |
|
| 115 | + { |
|
| 116 | + $this->set('TXN_ID', $TXN_ID); |
|
| 117 | + } |
|
| 118 | + |
|
| 119 | + |
|
| 120 | + /** |
|
| 121 | + * Gets name |
|
| 122 | + * |
|
| 123 | + * @return string |
|
| 124 | + * @throws EE_Error |
|
| 125 | + */ |
|
| 126 | + public function name() |
|
| 127 | + { |
|
| 128 | + $name = $this->get('LIN_name'); |
|
| 129 | + if (!$name) { |
|
| 130 | + $name = ucwords(str_replace('-', ' ', $this->type())); |
|
| 131 | + } |
|
| 132 | + return $name; |
|
| 133 | + } |
|
| 134 | + |
|
| 135 | + |
|
| 136 | + /** |
|
| 137 | + * Sets name |
|
| 138 | + * |
|
| 139 | + * @param string $name |
|
| 140 | + * @throws EE_Error |
|
| 141 | + */ |
|
| 142 | + public function set_name($name) |
|
| 143 | + { |
|
| 144 | + $this->set('LIN_name', $name); |
|
| 145 | + } |
|
| 146 | + |
|
| 147 | + |
|
| 148 | + /** |
|
| 149 | + * Gets desc |
|
| 150 | + * |
|
| 151 | + * @return string |
|
| 152 | + * @throws EE_Error |
|
| 153 | + */ |
|
| 154 | + public function desc() |
|
| 155 | + { |
|
| 156 | + return $this->get('LIN_desc'); |
|
| 157 | + } |
|
| 158 | + |
|
| 159 | + |
|
| 160 | + /** |
|
| 161 | + * Sets desc |
|
| 162 | + * |
|
| 163 | + * @param string $desc |
|
| 164 | + * @throws EE_Error |
|
| 165 | + */ |
|
| 166 | + public function set_desc($desc) |
|
| 167 | + { |
|
| 168 | + $this->set('LIN_desc', $desc); |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * Gets quantity |
|
| 174 | + * |
|
| 175 | + * @return int |
|
| 176 | + * @throws EE_Error |
|
| 177 | + */ |
|
| 178 | + public function quantity() |
|
| 179 | + { |
|
| 180 | + return $this->get('LIN_quantity'); |
|
| 181 | + } |
|
| 182 | + |
|
| 183 | + |
|
| 184 | + /** |
|
| 185 | + * Sets quantity |
|
| 186 | + * |
|
| 187 | + * @param int $quantity |
|
| 188 | + * @throws EE_Error |
|
| 189 | + */ |
|
| 190 | + public function set_quantity($quantity) |
|
| 191 | + { |
|
| 192 | + $this->set('LIN_quantity', max($quantity, 0)); |
|
| 193 | + } |
|
| 194 | + |
|
| 195 | + |
|
| 196 | + /** |
|
| 197 | + * Gets item_id |
|
| 198 | + * |
|
| 199 | + * @return string |
|
| 200 | + * @throws EE_Error |
|
| 201 | + */ |
|
| 202 | + public function OBJ_ID() |
|
| 203 | + { |
|
| 204 | + return $this->get('OBJ_ID'); |
|
| 205 | + } |
|
| 206 | + |
|
| 207 | + |
|
| 208 | + /** |
|
| 209 | + * Sets item_id |
|
| 210 | + * |
|
| 211 | + * @param string $item_id |
|
| 212 | + * @throws EE_Error |
|
| 213 | + */ |
|
| 214 | + public function set_OBJ_ID($item_id) |
|
| 215 | + { |
|
| 216 | + $this->set('OBJ_ID', $item_id); |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + |
|
| 220 | + /** |
|
| 221 | + * Gets item_type |
|
| 222 | + * |
|
| 223 | + * @return string |
|
| 224 | + * @throws EE_Error |
|
| 225 | + */ |
|
| 226 | + public function OBJ_type() |
|
| 227 | + { |
|
| 228 | + return $this->get('OBJ_type'); |
|
| 229 | + } |
|
| 230 | + |
|
| 231 | + |
|
| 232 | + /** |
|
| 233 | + * Gets item_type |
|
| 234 | + * |
|
| 235 | + * @return string |
|
| 236 | + * @throws EE_Error |
|
| 237 | + */ |
|
| 238 | + public function OBJ_type_i18n() |
|
| 239 | + { |
|
| 240 | + $obj_type = $this->OBJ_type(); |
|
| 241 | + switch ($obj_type) { |
|
| 242 | + case 'Event': |
|
| 243 | + $obj_type = __('Event', 'event_espresso'); |
|
| 244 | + break; |
|
| 245 | + case 'Price': |
|
| 246 | + $obj_type = __('Price', 'event_espresso'); |
|
| 247 | + break; |
|
| 248 | + case 'Promotion': |
|
| 249 | + $obj_type = __('Promotion', 'event_espresso'); |
|
| 250 | + break; |
|
| 251 | + case 'Ticket': |
|
| 252 | + $obj_type = __('Ticket', 'event_espresso'); |
|
| 253 | + break; |
|
| 254 | + case 'Transaction': |
|
| 255 | + $obj_type = __('Transaction', 'event_espresso'); |
|
| 256 | + break; |
|
| 257 | + } |
|
| 258 | + return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
| 259 | + } |
|
| 260 | + |
|
| 261 | + |
|
| 262 | + /** |
|
| 263 | + * Sets item_type |
|
| 264 | + * |
|
| 265 | + * @param string $OBJ_type |
|
| 266 | + * @throws EE_Error |
|
| 267 | + */ |
|
| 268 | + public function set_OBJ_type($OBJ_type) |
|
| 269 | + { |
|
| 270 | + $this->set('OBJ_type', $OBJ_type); |
|
| 271 | + } |
|
| 272 | + |
|
| 273 | + |
|
| 274 | + /** |
|
| 275 | + * Gets unit_price |
|
| 276 | + * |
|
| 277 | + * @return float |
|
| 278 | + * @throws EE_Error |
|
| 279 | + */ |
|
| 280 | + public function unit_price() |
|
| 281 | + { |
|
| 282 | + return $this->get('LIN_unit_price'); |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + |
|
| 286 | + /** |
|
| 287 | + * Sets unit_price |
|
| 288 | + * |
|
| 289 | + * @param float $unit_price |
|
| 290 | + * @throws EE_Error |
|
| 291 | + */ |
|
| 292 | + public function set_unit_price($unit_price) |
|
| 293 | + { |
|
| 294 | + $this->set('LIN_unit_price', $unit_price); |
|
| 295 | + } |
|
| 296 | + |
|
| 297 | + |
|
| 298 | + /** |
|
| 299 | + * Checks if this item is a percentage modifier or not |
|
| 300 | + * |
|
| 301 | + * @return boolean |
|
| 302 | + * @throws EE_Error |
|
| 303 | + */ |
|
| 304 | + public function is_percent() |
|
| 305 | + { |
|
| 306 | + if ($this->is_tax_sub_total()) { |
|
| 307 | + //tax subtotals HAVE a percent on them, that percentage only applies |
|
| 308 | + //to taxable items, so its' an exception. Treat it like a flat line item |
|
| 309 | + return false; |
|
| 310 | + } |
|
| 311 | + $unit_price = abs($this->get('LIN_unit_price')); |
|
| 312 | + $percent = abs($this->get('LIN_percent')); |
|
| 313 | + if ($unit_price < .001 && $percent) { |
|
| 314 | + return true; |
|
| 315 | + } |
|
| 316 | + if ($unit_price >= .001 && !$percent) { |
|
| 317 | + return false; |
|
| 318 | + } |
|
| 319 | + if ($unit_price >= .001 && $percent) { |
|
| 320 | + throw new EE_Error( |
|
| 321 | + sprintf( |
|
| 322 | + esc_html__('A Line Item can not have a unit price of (%s) AND a percent (%s)!', 'event_espresso'), |
|
| 323 | + $unit_price, $percent |
|
| 324 | + ) |
|
| 325 | + ); |
|
| 326 | + } |
|
| 327 | + // if they're both 0, assume its not a percent item |
|
| 328 | + return false; |
|
| 329 | + } |
|
| 330 | + |
|
| 331 | + |
|
| 332 | + /** |
|
| 333 | + * Gets percent (between 100-.001) |
|
| 334 | + * |
|
| 335 | + * @return float |
|
| 336 | + * @throws EE_Error |
|
| 337 | + */ |
|
| 338 | + public function percent() |
|
| 339 | + { |
|
| 340 | + return $this->get('LIN_percent'); |
|
| 341 | + } |
|
| 342 | + |
|
| 343 | + |
|
| 344 | + /** |
|
| 345 | + * Sets percent (between 100-0.01) |
|
| 346 | + * |
|
| 347 | + * @param float $percent |
|
| 348 | + * @throws EE_Error |
|
| 349 | + */ |
|
| 350 | + public function set_percent($percent) |
|
| 351 | + { |
|
| 352 | + $this->set('LIN_percent', $percent); |
|
| 353 | + } |
|
| 354 | + |
|
| 355 | + |
|
| 356 | + /** |
|
| 357 | + * Gets total |
|
| 358 | + * |
|
| 359 | + * @return float |
|
| 360 | + * @throws EE_Error |
|
| 361 | + */ |
|
| 362 | + public function total() |
|
| 363 | + { |
|
| 364 | + return $this->get('LIN_total'); |
|
| 365 | + } |
|
| 366 | + |
|
| 367 | + |
|
| 368 | + /** |
|
| 369 | + * Sets total |
|
| 370 | + * |
|
| 371 | + * @param float $total |
|
| 372 | + * @throws EE_Error |
|
| 373 | + */ |
|
| 374 | + public function set_total($total) |
|
| 375 | + { |
|
| 376 | + $this->set('LIN_total', $total); |
|
| 377 | + } |
|
| 378 | + |
|
| 379 | + |
|
| 380 | + /** |
|
| 381 | + * Gets order |
|
| 382 | + * |
|
| 383 | + * @return int |
|
| 384 | + * @throws EE_Error |
|
| 385 | + */ |
|
| 386 | + public function order() |
|
| 387 | + { |
|
| 388 | + return $this->get('LIN_order'); |
|
| 389 | + } |
|
| 390 | + |
|
| 391 | + |
|
| 392 | + /** |
|
| 393 | + * Sets order |
|
| 394 | + * |
|
| 395 | + * @param int $order |
|
| 396 | + * @throws EE_Error |
|
| 397 | + */ |
|
| 398 | + public function set_order($order) |
|
| 399 | + { |
|
| 400 | + $this->set('LIN_order', $order); |
|
| 401 | + } |
|
| 402 | + |
|
| 403 | + |
|
| 404 | + /** |
|
| 405 | + * Gets parent |
|
| 406 | + * |
|
| 407 | + * @return int |
|
| 408 | + * @throws EE_Error |
|
| 409 | + */ |
|
| 410 | + public function parent_ID() |
|
| 411 | + { |
|
| 412 | + return $this->get('LIN_parent'); |
|
| 413 | + } |
|
| 414 | + |
|
| 415 | + |
|
| 416 | + /** |
|
| 417 | + * Sets parent |
|
| 418 | + * |
|
| 419 | + * @param int $parent |
|
| 420 | + * @throws EE_Error |
|
| 421 | + */ |
|
| 422 | + public function set_parent_ID($parent) |
|
| 423 | + { |
|
| 424 | + $this->set('LIN_parent', $parent); |
|
| 425 | + } |
|
| 426 | + |
|
| 427 | + |
|
| 428 | + /** |
|
| 429 | + * Gets type |
|
| 430 | + * |
|
| 431 | + * @return string |
|
| 432 | + * @throws EE_Error |
|
| 433 | + */ |
|
| 434 | + public function type() |
|
| 435 | + { |
|
| 436 | + return $this->get('LIN_type'); |
|
| 437 | + } |
|
| 438 | + |
|
| 439 | + |
|
| 440 | + /** |
|
| 441 | + * Sets type |
|
| 442 | + * |
|
| 443 | + * @param string $type |
|
| 444 | + * @throws EE_Error |
|
| 445 | + */ |
|
| 446 | + public function set_type($type) |
|
| 447 | + { |
|
| 448 | + $this->set('LIN_type', $type); |
|
| 449 | + } |
|
| 450 | + |
|
| 451 | + |
|
| 452 | + /** |
|
| 453 | + * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
| 454 | + * If this line item is saved to the DB, fetches the parent from the DB. However, if this line item isn't in the DB |
|
| 455 | + * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
| 456 | + * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
| 457 | + * |
|
| 458 | + * @return EE_Base_Class|EE_Line_Item |
|
| 459 | + * @throws EE_Error |
|
| 460 | + */ |
|
| 461 | + public function parent() |
|
| 462 | + { |
|
| 463 | + return $this->ID() |
|
| 464 | + ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
| 465 | + : $this->_parent; |
|
| 466 | + } |
|
| 467 | + |
|
| 468 | + |
|
| 469 | + /** |
|
| 470 | + * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
| 471 | + * |
|
| 472 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 473 | + * @throws EE_Error |
|
| 474 | + */ |
|
| 475 | + public function children() |
|
| 476 | + { |
|
| 477 | + if ($this->ID()) { |
|
| 478 | + return $this->get_model()->get_all( |
|
| 479 | + array( |
|
| 480 | + array('LIN_parent' => $this->ID()), |
|
| 481 | + 'order_by' => array('LIN_order' => 'ASC'), |
|
| 482 | + ) |
|
| 483 | + ); |
|
| 484 | + } |
|
| 485 | + if (!is_array($this->_children)) { |
|
| 486 | + $this->_children = array(); |
|
| 487 | + } |
|
| 488 | + return $this->_children; |
|
| 489 | + } |
|
| 490 | + |
|
| 491 | + |
|
| 492 | + /** |
|
| 493 | + * Gets code |
|
| 494 | + * |
|
| 495 | + * @return string |
|
| 496 | + * @throws EE_Error |
|
| 497 | + */ |
|
| 498 | + public function code() |
|
| 499 | + { |
|
| 500 | + return $this->get('LIN_code'); |
|
| 501 | + } |
|
| 502 | + |
|
| 503 | + |
|
| 504 | + /** |
|
| 505 | + * Sets code |
|
| 506 | + * |
|
| 507 | + * @param string $code |
|
| 508 | + * @throws EE_Error |
|
| 509 | + */ |
|
| 510 | + public function set_code($code) |
|
| 511 | + { |
|
| 512 | + $this->set('LIN_code', $code); |
|
| 513 | + } |
|
| 514 | + |
|
| 515 | + |
|
| 516 | + /** |
|
| 517 | + * Gets is_taxable |
|
| 518 | + * |
|
| 519 | + * @return boolean |
|
| 520 | + * @throws EE_Error |
|
| 521 | + */ |
|
| 522 | + public function is_taxable() |
|
| 523 | + { |
|
| 524 | + return $this->get('LIN_is_taxable'); |
|
| 525 | + } |
|
| 526 | + |
|
| 527 | + |
|
| 528 | + /** |
|
| 529 | + * Sets is_taxable |
|
| 530 | + * |
|
| 531 | + * @param boolean $is_taxable |
|
| 532 | + * @throws EE_Error |
|
| 533 | + */ |
|
| 534 | + public function set_is_taxable($is_taxable) |
|
| 535 | + { |
|
| 536 | + $this->set('LIN_is_taxable', $is_taxable); |
|
| 537 | + } |
|
| 538 | + |
|
| 539 | + |
|
| 540 | + /** |
|
| 541 | + * Gets the object that this model-joins-to. |
|
| 542 | + * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
| 543 | + * EEM_Promotion_Object |
|
| 544 | + * |
|
| 545 | + * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
| 546 | + * |
|
| 547 | + * @return EE_Base_Class | NULL |
|
| 548 | + * @throws EE_Error |
|
| 549 | + */ |
|
| 550 | + public function get_object() |
|
| 551 | + { |
|
| 552 | + $model_name_of_related_obj = $this->OBJ_type(); |
|
| 553 | + return $this->get_model()->has_relation($model_name_of_related_obj) |
|
| 554 | + ? $this->get_first_related($model_name_of_related_obj) |
|
| 555 | + : null; |
|
| 556 | + } |
|
| 557 | + |
|
| 558 | + |
|
| 559 | + /** |
|
| 560 | + * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
| 561 | + * (IE, if this line item is for a price or something else, will return NULL) |
|
| 562 | + * |
|
| 563 | + * @param array $query_params |
|
| 564 | + * @return EE_Base_Class|EE_Ticket |
|
| 565 | + * @throws EE_Error |
|
| 566 | + */ |
|
| 567 | + public function ticket($query_params = array()) |
|
| 568 | + { |
|
| 569 | + //we're going to assume that when this method is called we always want to receive the attached ticket EVEN if that ticket is archived. This can be overridden via the incoming $query_params argument |
|
| 570 | + $remove_defaults = array('default_where_conditions' => 'none'); |
|
| 571 | + $query_params = array_merge($remove_defaults, $query_params); |
|
| 572 | + return $this->get_first_related('Ticket', $query_params); |
|
| 573 | + } |
|
| 574 | + |
|
| 575 | + |
|
| 576 | + /** |
|
| 577 | + * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
| 578 | + * |
|
| 579 | + * @return EE_Datetime | NULL |
|
| 580 | + * @throws EE_Error |
|
| 581 | + */ |
|
| 582 | + public function get_ticket_datetime() |
|
| 583 | + { |
|
| 584 | + if ($this->OBJ_type() === 'Ticket') { |
|
| 585 | + $ticket = $this->ticket(); |
|
| 586 | + if ($ticket instanceof EE_Ticket) { |
|
| 587 | + $datetime = $ticket->first_datetime(); |
|
| 588 | + if ($datetime instanceof EE_Datetime) { |
|
| 589 | + return $datetime; |
|
| 590 | + } |
|
| 591 | + } |
|
| 592 | + } |
|
| 593 | + return null; |
|
| 594 | + } |
|
| 595 | + |
|
| 596 | + |
|
| 597 | + /** |
|
| 598 | + * Gets the event's name that's related to the ticket, if this is for |
|
| 599 | + * a ticket |
|
| 600 | + * |
|
| 601 | + * @return string |
|
| 602 | + * @throws EE_Error |
|
| 603 | + */ |
|
| 604 | + public function ticket_event_name() |
|
| 605 | + { |
|
| 606 | + $event_name = esc_html__('Unknown', 'event_espresso'); |
|
| 607 | + $event = $this->ticket_event(); |
|
| 608 | + if ($event instanceof EE_Event) { |
|
| 609 | + $event_name = $event->name(); |
|
| 610 | + } |
|
| 611 | + return $event_name; |
|
| 612 | + } |
|
| 613 | + |
|
| 614 | + |
|
| 615 | + /** |
|
| 616 | + * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
| 617 | + * |
|
| 618 | + * @return EE_Event|null |
|
| 619 | + * @throws EE_Error |
|
| 620 | + */ |
|
| 621 | + public function ticket_event() |
|
| 622 | + { |
|
| 623 | + $event = null; |
|
| 624 | + $ticket = $this->ticket(); |
|
| 625 | + if ($ticket instanceof EE_Ticket) { |
|
| 626 | + $datetime = $ticket->first_datetime(); |
|
| 627 | + if ($datetime instanceof EE_Datetime) { |
|
| 628 | + $event = $datetime->event(); |
|
| 629 | + } |
|
| 630 | + } |
|
| 631 | + return $event; |
|
| 632 | + } |
|
| 633 | + |
|
| 634 | + |
|
| 635 | + /** |
|
| 636 | + * Gets the first datetime for this lien item, assuming it's for a ticket |
|
| 637 | + * |
|
| 638 | + * @param string $date_format |
|
| 639 | + * @param string $time_format |
|
| 640 | + * @return string |
|
| 641 | + * @throws EE_Error |
|
| 642 | + */ |
|
| 643 | + public function ticket_datetime_start($date_format = '', $time_format = '') |
|
| 644 | + { |
|
| 645 | + $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
| 646 | + $datetime = $this->get_ticket_datetime(); |
|
| 647 | + if ($datetime) { |
|
| 648 | + $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
| 649 | + } |
|
| 650 | + return $first_datetime_string; |
|
| 651 | + } |
|
| 652 | + |
|
| 653 | + |
|
| 654 | + /** |
|
| 655 | + * Adds the line item as a child to this line item. If there is another child line |
|
| 656 | + * item with the same LIN_code, it is overwritten by this new one |
|
| 657 | + * |
|
| 658 | + * @param EEI_Line_Item $line_item |
|
| 659 | + * @param bool $set_order |
|
| 660 | + * @return bool success |
|
| 661 | + * @throws EE_Error |
|
| 662 | + */ |
|
| 663 | + public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
| 664 | + { |
|
| 665 | + // should we calculate the LIN_order for this line item ? |
|
| 666 | + if ($set_order || $line_item->order() === null) { |
|
| 667 | + $line_item->set_order(count($this->children())); |
|
| 668 | + } |
|
| 669 | + if ($this->ID()) { |
|
| 670 | + //check for any duplicate line items (with the same code), if so, this replaces it |
|
| 671 | + $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
| 672 | + if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
| 673 | + $this->delete_child_line_item($line_item_with_same_code->code()); |
|
| 674 | + } |
|
| 675 | + $line_item->set_parent_ID($this->ID()); |
|
| 676 | + if ($this->TXN_ID()) { |
|
| 677 | + $line_item->set_TXN_ID($this->TXN_ID()); |
|
| 678 | + } |
|
| 679 | + return $line_item->save(); |
|
| 680 | + } |
|
| 681 | + $this->_children[$line_item->code()] = $line_item; |
|
| 682 | + if ($line_item->parent() !== $this) { |
|
| 683 | + $line_item->set_parent($this); |
|
| 684 | + } |
|
| 685 | + return true; |
|
| 686 | + } |
|
| 687 | + |
|
| 688 | + |
|
| 689 | + /** |
|
| 690 | + * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
| 691 | + * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
| 692 | + * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
| 693 | + * the EE_Line_Item::_parent property. |
|
| 694 | + * |
|
| 695 | + * @param EE_Line_Item $line_item |
|
| 696 | + * @throws EE_Error |
|
| 697 | + */ |
|
| 698 | + public function set_parent($line_item) |
|
| 699 | + { |
|
| 700 | + if ($this->ID()) { |
|
| 701 | + if (!$line_item->ID()) { |
|
| 702 | + $line_item->save(); |
|
| 703 | + } |
|
| 704 | + $this->set_parent_ID($line_item->ID()); |
|
| 705 | + $this->save(); |
|
| 706 | + } else { |
|
| 707 | + $this->_parent = $line_item; |
|
| 708 | + $this->set_parent_ID($line_item->ID()); |
|
| 709 | + } |
|
| 710 | + } |
|
| 711 | + |
|
| 712 | + |
|
| 713 | + /** |
|
| 714 | + * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
| 715 | + * you can modify this child line item and the parent (this object) can know about them |
|
| 716 | + * because it also has a reference to that line item |
|
| 717 | + * |
|
| 718 | + * @param string $code |
|
| 719 | + * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 720 | + * @throws EE_Error |
|
| 721 | + */ |
|
| 722 | + public function get_child_line_item($code) |
|
| 723 | + { |
|
| 724 | + if ($this->ID()) { |
|
| 725 | + return $this->get_model()->get_one( |
|
| 726 | + array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
| 727 | + ); |
|
| 728 | + } |
|
| 729 | + return isset($this->_children[$code]) |
|
| 730 | + ? $this->_children[$code] |
|
| 731 | + : null; |
|
| 732 | + } |
|
| 733 | + |
|
| 734 | + |
|
| 735 | + /** |
|
| 736 | + * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
| 737 | + * cached on it) |
|
| 738 | + * |
|
| 739 | + * @return int |
|
| 740 | + * @throws EE_Error |
|
| 741 | + */ |
|
| 742 | + public function delete_children_line_items() |
|
| 743 | + { |
|
| 744 | + if ($this->ID()) { |
|
| 745 | + return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
| 746 | + } |
|
| 747 | + $count = count($this->_children); |
|
| 748 | + $this->_children = array(); |
|
| 749 | + return $count; |
|
| 750 | + } |
|
| 751 | + |
|
| 752 | + |
|
| 753 | + /** |
|
| 754 | + * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
| 755 | + * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
| 756 | + * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
| 757 | + * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
| 758 | + * deleted) |
|
| 759 | + * |
|
| 760 | + * @param string $code |
|
| 761 | + * @param bool $stop_search_once_found |
|
| 762 | + * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
| 763 | + * the DB yet) |
|
| 764 | + * @throws EE_Error |
|
| 765 | + */ |
|
| 766 | + public function delete_child_line_item($code, $stop_search_once_found = true) |
|
| 767 | + { |
|
| 768 | + if ($this->ID()) { |
|
| 769 | + $items_deleted = 0; |
|
| 770 | + if ($this->code() === $code) { |
|
| 771 | + $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
| 772 | + $items_deleted += (int)$this->delete(); |
|
| 773 | + if ($stop_search_once_found) { |
|
| 774 | + return $items_deleted; |
|
| 775 | + } |
|
| 776 | + } |
|
| 777 | + foreach ($this->children() as $child_line_item) { |
|
| 778 | + $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
| 779 | + } |
|
| 780 | + return $items_deleted; |
|
| 781 | + } |
|
| 782 | + if (isset($this->_children[$code])) { |
|
| 783 | + unset($this->_children[$code]); |
|
| 784 | + return 1; |
|
| 785 | + } |
|
| 786 | + return 0; |
|
| 787 | + } |
|
| 788 | + |
|
| 789 | + |
|
| 790 | + /** |
|
| 791 | + * If this line item is in the database, is of the type subtotal, and |
|
| 792 | + * has no children, why do we have it? It should be deleted so this function |
|
| 793 | + * does that |
|
| 794 | + * |
|
| 795 | + * @return boolean |
|
| 796 | + * @throws EE_Error |
|
| 797 | + */ |
|
| 798 | + public function delete_if_childless_subtotal() |
|
| 799 | + { |
|
| 800 | + if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && !$this->children()) { |
|
| 801 | + return $this->delete(); |
|
| 802 | + } |
|
| 803 | + return false; |
|
| 804 | + } |
|
| 805 | + |
|
| 806 | + |
|
| 807 | + /** |
|
| 808 | + * Creates a code and returns a string. doesn't assign the code to this model object |
|
| 809 | + * |
|
| 810 | + * @return string |
|
| 811 | + * @throws EE_Error |
|
| 812 | + */ |
|
| 813 | + public function generate_code() |
|
| 814 | + { |
|
| 815 | + // each line item in the cart requires a unique identifier |
|
| 816 | + return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
| 817 | + } |
|
| 818 | + |
|
| 819 | + |
|
| 820 | + /** |
|
| 821 | + * @return bool |
|
| 822 | + * @throws EE_Error |
|
| 823 | + */ |
|
| 824 | + public function is_tax() |
|
| 825 | + { |
|
| 826 | + return $this->type() === EEM_Line_Item::type_tax; |
|
| 827 | + } |
|
| 828 | + |
|
| 829 | + |
|
| 830 | + /** |
|
| 831 | + * @return bool |
|
| 832 | + * @throws EE_Error |
|
| 833 | + */ |
|
| 834 | + public function is_tax_sub_total() |
|
| 835 | + { |
|
| 836 | + return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
| 837 | + } |
|
| 838 | + |
|
| 839 | + |
|
| 840 | + /** |
|
| 841 | + * @return bool |
|
| 842 | + * @throws EE_Error |
|
| 843 | + */ |
|
| 844 | + public function is_line_item() |
|
| 845 | + { |
|
| 846 | + return $this->type() === EEM_Line_Item::type_line_item; |
|
| 847 | + } |
|
| 848 | + |
|
| 849 | + |
|
| 850 | + /** |
|
| 851 | + * @return bool |
|
| 852 | + * @throws EE_Error |
|
| 853 | + */ |
|
| 854 | + public function is_sub_line_item() |
|
| 855 | + { |
|
| 856 | + return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
| 857 | + } |
|
| 858 | + |
|
| 859 | + |
|
| 860 | + /** |
|
| 861 | + * @return bool |
|
| 862 | + * @throws EE_Error |
|
| 863 | + */ |
|
| 864 | + public function is_sub_total() |
|
| 865 | + { |
|
| 866 | + return $this->type() === EEM_Line_Item::type_sub_total; |
|
| 867 | + } |
|
| 868 | + |
|
| 869 | + |
|
| 870 | + /** |
|
| 871 | + * Whether or not this line item is a cancellation line item |
|
| 872 | + * |
|
| 873 | + * @return boolean |
|
| 874 | + * @throws EE_Error |
|
| 875 | + */ |
|
| 876 | + public function is_cancellation() |
|
| 877 | + { |
|
| 878 | + return EEM_Line_Item::type_cancellation === $this->type(); |
|
| 879 | + } |
|
| 880 | + |
|
| 881 | + |
|
| 882 | + /** |
|
| 883 | + * @return bool |
|
| 884 | + * @throws EE_Error |
|
| 885 | + */ |
|
| 886 | + public function is_total() |
|
| 887 | + { |
|
| 888 | + return $this->type() === EEM_Line_Item::type_total; |
|
| 889 | + } |
|
| 890 | + |
|
| 891 | + |
|
| 892 | + /** |
|
| 893 | + * @return bool |
|
| 894 | + * @throws EE_Error |
|
| 895 | + */ |
|
| 896 | + public function is_cancelled() |
|
| 897 | + { |
|
| 898 | + return $this->type() === EEM_Line_Item::type_cancellation; |
|
| 899 | + } |
|
| 900 | + |
|
| 901 | + |
|
| 902 | + /** |
|
| 903 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
| 904 | + * @throws EE_Error |
|
| 905 | + */ |
|
| 906 | + public function unit_price_no_code() |
|
| 907 | + { |
|
| 908 | + return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
| 909 | + } |
|
| 910 | + |
|
| 911 | + |
|
| 912 | + /** |
|
| 913 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
| 914 | + * @throws EE_Error |
|
| 915 | + */ |
|
| 916 | + public function total_no_code() |
|
| 917 | + { |
|
| 918 | + return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
| 919 | + } |
|
| 920 | + |
|
| 921 | + |
|
| 922 | + /** |
|
| 923 | + * Gets the final total on this item, taking taxes into account. |
|
| 924 | + * Has the side-effect of setting the sub-total as it was just calculated. |
|
| 925 | + * If this is used on a grand-total line item, also updates the transaction's |
|
| 926 | + * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
| 927 | + * want to change a persistable transaction with info from a non-persistent line item) |
|
| 928 | + * |
|
| 929 | + * @return float |
|
| 930 | + * @throws EE_Error |
|
| 931 | + * @throws InvalidArgumentException |
|
| 932 | + * @throws InvalidInterfaceException |
|
| 933 | + * @throws InvalidDataTypeException |
|
| 934 | + */ |
|
| 935 | + public function recalculate_total_including_taxes() |
|
| 936 | + { |
|
| 937 | + $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
| 938 | + $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
| 939 | + $total = $pre_tax_total + $tax_total; |
|
| 940 | + // no negative totals plz |
|
| 941 | + $total = max($total, 0); |
|
| 942 | + $this->set_total($total); |
|
| 943 | + //only update the related transaction's total |
|
| 944 | + //if we intend to save this line item and its a grand total |
|
| 945 | + if ( |
|
| 946 | + $this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
| 947 | + && $this->transaction() |
|
| 948 | + instanceof |
|
| 949 | + EE_Transaction |
|
| 950 | + ) { |
|
| 951 | + $this->transaction()->set_total($total); |
|
| 952 | + if ($this->transaction()->ID()) { |
|
| 953 | + $this->transaction()->save(); |
|
| 954 | + } |
|
| 955 | + } |
|
| 956 | + $this->maybe_save(); |
|
| 957 | + return $total; |
|
| 958 | + } |
|
| 959 | + |
|
| 960 | + |
|
| 961 | + /** |
|
| 962 | + * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
| 963 | + * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
| 964 | + * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
| 965 | + * when this is called on the grand total |
|
| 966 | + * |
|
| 967 | + * @return float |
|
| 968 | + * @throws InvalidArgumentException |
|
| 969 | + * @throws InvalidInterfaceException |
|
| 970 | + * @throws InvalidDataTypeException |
|
| 971 | + * @throws EE_Error |
|
| 972 | + */ |
|
| 973 | + public function recalculate_pre_tax_total() |
|
| 974 | + { |
|
| 975 | + $total = 0; |
|
| 976 | + $my_children = $this->children(); |
|
| 977 | + $has_children = !empty($my_children); |
|
| 978 | + if ($has_children && $this->is_line_item()) { |
|
| 979 | + $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
| 980 | + } elseif (!$has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 981 | + $total = $this->unit_price() * $this->quantity(); |
|
| 982 | + } elseif ($this->is_sub_total() || $this->is_total()) { |
|
| 983 | + $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
| 984 | + } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
| 985 | + // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
| 986 | + return 0; |
|
| 987 | + } |
|
| 988 | + // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
| 989 | + if ( |
|
| 990 | + !$this->is_line_item() && !$this->is_sub_line_item() && !$this->is_cancellation() |
|
| 991 | + ) { |
|
| 992 | + if ($this->OBJ_type() !== 'Event') { |
|
| 993 | + $this->set_quantity(1); |
|
| 994 | + } |
|
| 995 | + if (!$this->is_percent()) { |
|
| 996 | + $this->set_unit_price($total); |
|
| 997 | + } |
|
| 998 | + } |
|
| 999 | + //we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
| 1000 | + //so it ought to be |
|
| 1001 | + if (!$this->is_total()) { |
|
| 1002 | + $this->set_total($total); |
|
| 1003 | + //if not a percent line item, make sure we keep the unit price in sync |
|
| 1004 | + if ( |
|
| 1005 | + $has_children |
|
| 1006 | + && $this->is_line_item() |
|
| 1007 | + && !$this->is_percent() |
|
| 1008 | + ) { |
|
| 1009 | + if ($this->quantity() === 0) { |
|
| 1010 | + $new_unit_price = 0; |
|
| 1011 | + } else { |
|
| 1012 | + $new_unit_price = $this->total() / $this->quantity(); |
|
| 1013 | + } |
|
| 1014 | + $this->set_unit_price($new_unit_price); |
|
| 1015 | + } |
|
| 1016 | + $this->maybe_save(); |
|
| 1017 | + } |
|
| 1018 | + return $total; |
|
| 1019 | + } |
|
| 1020 | + |
|
| 1021 | + |
|
| 1022 | + /** |
|
| 1023 | + * Calculates the pretax total when this line item is a subtotal or total line item. |
|
| 1024 | + * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
| 1025 | + * will calculate their total based on the un-rounded total we're working with so far, and |
|
| 1026 | + * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
| 1027 | + * |
|
| 1028 | + * @param float $calculated_total_so_far |
|
| 1029 | + * @param EE_Line_Item[] $my_children |
|
| 1030 | + * @return float |
|
| 1031 | + * @throws InvalidArgumentException |
|
| 1032 | + * @throws InvalidInterfaceException |
|
| 1033 | + * @throws InvalidDataTypeException |
|
| 1034 | + * @throws EE_Error |
|
| 1035 | + */ |
|
| 1036 | + protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
| 1037 | + { |
|
| 1038 | + if ($my_children === null) { |
|
| 1039 | + $my_children = $this->children(); |
|
| 1040 | + } |
|
| 1041 | + $subtotal_quantity = 0; |
|
| 1042 | + //get the total of all its children |
|
| 1043 | + foreach ($my_children as $child_line_item) { |
|
| 1044 | + if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) { |
|
| 1045 | + // percentage line items are based on total so far |
|
| 1046 | + if ($child_line_item->is_percent()) { |
|
| 1047 | + //round as we go so that the line items add up ok |
|
| 1048 | + $percent_total = round( |
|
| 1049 | + $calculated_total_so_far * $child_line_item->percent() / 100, |
|
| 1050 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1051 | + ); |
|
| 1052 | + $child_line_item->set_total($percent_total); |
|
| 1053 | + //so far all percent line items should have a quantity of 1 |
|
| 1054 | + //(ie, no double percent discounts. Although that might be requested someday) |
|
| 1055 | + $child_line_item->set_quantity(1); |
|
| 1056 | + $child_line_item->maybe_save(); |
|
| 1057 | + $calculated_total_so_far += $percent_total; |
|
| 1058 | + } else { |
|
| 1059 | + //verify flat sub-line-item quantities match their parent |
|
| 1060 | + if ($child_line_item->is_sub_line_item()) { |
|
| 1061 | + $child_line_item->set_quantity($this->quantity()); |
|
| 1062 | + } |
|
| 1063 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1064 | + $subtotal_quantity += $child_line_item->quantity(); |
|
| 1065 | + } |
|
| 1066 | + } |
|
| 1067 | + } |
|
| 1068 | + if ($this->is_sub_total()) { |
|
| 1069 | + // no negative totals plz |
|
| 1070 | + $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
| 1071 | + $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
| 1072 | + $this->set_quantity($subtotal_quantity); |
|
| 1073 | + $this->maybe_save(); |
|
| 1074 | + } |
|
| 1075 | + return $calculated_total_so_far; |
|
| 1076 | + } |
|
| 1077 | + |
|
| 1078 | + |
|
| 1079 | + /** |
|
| 1080 | + * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
| 1081 | + * (where each sub-line-item is applied to the base price for the line item |
|
| 1082 | + * and the result is immediately rounded, rather than summing all the sub-line-items |
|
| 1083 | + * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
| 1084 | + * |
|
| 1085 | + * @param float $calculated_total_so_far |
|
| 1086 | + * @param EE_Line_Item[] $my_children |
|
| 1087 | + * @return float |
|
| 1088 | + * @throws InvalidArgumentException |
|
| 1089 | + * @throws InvalidInterfaceException |
|
| 1090 | + * @throws InvalidDataTypeException |
|
| 1091 | + * @throws EE_Error |
|
| 1092 | + */ |
|
| 1093 | + protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
| 1094 | + { |
|
| 1095 | + if ($my_children === null) { |
|
| 1096 | + $my_children = $this->children(); |
|
| 1097 | + } |
|
| 1098 | + //we need to keep track of the running total for a single item, |
|
| 1099 | + //because we need to round as we go |
|
| 1100 | + $unit_price_for_total = 0; |
|
| 1101 | + $quantity_for_total = 1; |
|
| 1102 | + //get the total of all its children |
|
| 1103 | + foreach ($my_children as $child_line_item) { |
|
| 1104 | + if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) { |
|
| 1105 | + if ($child_line_item->is_percent()) { |
|
| 1106 | + //it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
| 1107 | + //not total multiplied by percent, because that ignores rounding along-the-way |
|
| 1108 | + $percent_unit_price = round( |
|
| 1109 | + $unit_price_for_total * $child_line_item->percent() / 100, |
|
| 1110 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1111 | + ); |
|
| 1112 | + $percent_total = $percent_unit_price * $quantity_for_total; |
|
| 1113 | + $child_line_item->set_total($percent_total); |
|
| 1114 | + //so far all percent line items should have a quantity of 1 |
|
| 1115 | + //(ie, no double percent discounts. Although that might be requested someday) |
|
| 1116 | + $child_line_item->set_quantity(1); |
|
| 1117 | + $child_line_item->maybe_save(); |
|
| 1118 | + $calculated_total_so_far += $percent_total; |
|
| 1119 | + $unit_price_for_total += $percent_unit_price; |
|
| 1120 | + } else { |
|
| 1121 | + //verify flat sub-line-item quantities match their parent |
|
| 1122 | + if ($child_line_item->is_sub_line_item()) { |
|
| 1123 | + $child_line_item->set_quantity($this->quantity()); |
|
| 1124 | + } |
|
| 1125 | + $quantity_for_total = $child_line_item->quantity(); |
|
| 1126 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1127 | + $unit_price_for_total += $child_line_item->unit_price(); |
|
| 1128 | + } |
|
| 1129 | + } |
|
| 1130 | + } |
|
| 1131 | + return $calculated_total_so_far; |
|
| 1132 | + } |
|
| 1133 | + |
|
| 1134 | + |
|
| 1135 | + /** |
|
| 1136 | + * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
| 1137 | + * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
| 1138 | + * and tax sub-total if already in the DB |
|
| 1139 | + * |
|
| 1140 | + * @return float |
|
| 1141 | + * @throws EE_Error |
|
| 1142 | + */ |
|
| 1143 | + public function recalculate_taxes_and_tax_total() |
|
| 1144 | + { |
|
| 1145 | + //get all taxes |
|
| 1146 | + $taxes = $this->tax_descendants(); |
|
| 1147 | + //calculate the pretax total |
|
| 1148 | + $taxable_total = $this->taxable_total(); |
|
| 1149 | + $tax_total = 0; |
|
| 1150 | + foreach ($taxes as $tax) { |
|
| 1151 | + $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
| 1152 | + //remember the total on this line item |
|
| 1153 | + $tax->set_total($total_on_this_tax); |
|
| 1154 | + $tax->maybe_save(); |
|
| 1155 | + $tax_total += $tax->total(); |
|
| 1156 | + } |
|
| 1157 | + $this->_recalculate_tax_sub_total(); |
|
| 1158 | + return $tax_total; |
|
| 1159 | + } |
|
| 1160 | + |
|
| 1161 | + |
|
| 1162 | + /** |
|
| 1163 | + * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
| 1164 | + * |
|
| 1165 | + * @return void |
|
| 1166 | + * @throws EE_Error |
|
| 1167 | + */ |
|
| 1168 | + private function _recalculate_tax_sub_total() |
|
| 1169 | + { |
|
| 1170 | + if ($this->is_tax_sub_total()) { |
|
| 1171 | + $total = 0; |
|
| 1172 | + $total_percent = 0; |
|
| 1173 | + //simply loop through all its children (which should be taxes) and sum their total |
|
| 1174 | + foreach ($this->children() as $child_tax) { |
|
| 1175 | + if ($child_tax instanceof EE_Line_Item) { |
|
| 1176 | + $total += $child_tax->total(); |
|
| 1177 | + $total_percent += $child_tax->percent(); |
|
| 1178 | + } |
|
| 1179 | + } |
|
| 1180 | + $this->set_total($total); |
|
| 1181 | + $this->set_percent($total_percent); |
|
| 1182 | + $this->maybe_save(); |
|
| 1183 | + } elseif ($this->is_total()) { |
|
| 1184 | + foreach ($this->children() as $maybe_tax_subtotal) { |
|
| 1185 | + if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
| 1186 | + $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
| 1187 | + } |
|
| 1188 | + } |
|
| 1189 | + } |
|
| 1190 | + } |
|
| 1191 | + |
|
| 1192 | + |
|
| 1193 | + /** |
|
| 1194 | + * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
| 1195 | + * recalculate_taxes_and_total |
|
| 1196 | + * |
|
| 1197 | + * @return float |
|
| 1198 | + * @throws EE_Error |
|
| 1199 | + */ |
|
| 1200 | + public function get_total_tax() |
|
| 1201 | + { |
|
| 1202 | + $this->_recalculate_tax_sub_total(); |
|
| 1203 | + $total = 0; |
|
| 1204 | + foreach ($this->tax_descendants() as $tax_line_item) { |
|
| 1205 | + if ($tax_line_item instanceof EE_Line_Item) { |
|
| 1206 | + $total += $tax_line_item->total(); |
|
| 1207 | + } |
|
| 1208 | + } |
|
| 1209 | + return $total; |
|
| 1210 | + } |
|
| 1211 | + |
|
| 1212 | + |
|
| 1213 | + /** |
|
| 1214 | + * Gets the total for all the items purchased only |
|
| 1215 | + * |
|
| 1216 | + * @return float |
|
| 1217 | + * @throws EE_Error |
|
| 1218 | + */ |
|
| 1219 | + public function get_items_total() |
|
| 1220 | + { |
|
| 1221 | + //by default, let's make sure we're consistent with the existing line item |
|
| 1222 | + if ($this->is_total()) { |
|
| 1223 | + $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
| 1224 | + if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
| 1225 | + return $pretax_subtotal_li->total(); |
|
| 1226 | + } |
|
| 1227 | + } |
|
| 1228 | + $total = 0; |
|
| 1229 | + foreach ($this->get_items() as $item) { |
|
| 1230 | + if ($item instanceof EE_Line_Item) { |
|
| 1231 | + $total += $item->total(); |
|
| 1232 | + } |
|
| 1233 | + } |
|
| 1234 | + return $total; |
|
| 1235 | + } |
|
| 1236 | + |
|
| 1237 | + |
|
| 1238 | + /** |
|
| 1239 | + * Gets all the descendants (ie, children or children of children etc) that |
|
| 1240 | + * are of the type 'tax' |
|
| 1241 | + * |
|
| 1242 | + * @return EE_Line_Item[] |
|
| 1243 | + */ |
|
| 1244 | + public function tax_descendants() |
|
| 1245 | + { |
|
| 1246 | + return EEH_Line_Item::get_tax_descendants($this); |
|
| 1247 | + } |
|
| 1248 | + |
|
| 1249 | + |
|
| 1250 | + /** |
|
| 1251 | + * Gets all the real items purchased which are children of this item |
|
| 1252 | + * |
|
| 1253 | + * @return EE_Line_Item[] |
|
| 1254 | + */ |
|
| 1255 | + public function get_items() |
|
| 1256 | + { |
|
| 1257 | + return EEH_Line_Item::get_line_item_descendants($this); |
|
| 1258 | + } |
|
| 1259 | + |
|
| 1260 | + |
|
| 1261 | + /** |
|
| 1262 | + * Returns the amount taxable among this line item's children (or if it has no children, |
|
| 1263 | + * how much of it is taxable). Does not recalculate totals or subtotals. |
|
| 1264 | + * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
| 1265 | + * but there is a "Taxable" discount), returns 0. |
|
| 1266 | + * |
|
| 1267 | + * @return float |
|
| 1268 | + * @throws EE_Error |
|
| 1269 | + */ |
|
| 1270 | + public function taxable_total() |
|
| 1271 | + { |
|
| 1272 | + $total = 0; |
|
| 1273 | + if ($this->children()) { |
|
| 1274 | + foreach ($this->children() as $child_line_item) { |
|
| 1275 | + if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
| 1276 | + //if it's a percent item, only take into account the percent |
|
| 1277 | + //that's taxable too (the taxable total so far) |
|
| 1278 | + if ($child_line_item->is_percent()) { |
|
| 1279 | + $total += ($total * $child_line_item->percent() / 100); |
|
| 1280 | + } else { |
|
| 1281 | + $total += $child_line_item->total(); |
|
| 1282 | + } |
|
| 1283 | + } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
| 1284 | + $total += $child_line_item->taxable_total(); |
|
| 1285 | + } |
|
| 1286 | + } |
|
| 1287 | + } |
|
| 1288 | + return max($total, 0); |
|
| 1289 | + } |
|
| 1290 | + |
|
| 1291 | + |
|
| 1292 | + /** |
|
| 1293 | + * Gets the transaction for this line item |
|
| 1294 | + * |
|
| 1295 | + * @return EE_Base_Class|EE_Transaction |
|
| 1296 | + * @throws EE_Error |
|
| 1297 | + */ |
|
| 1298 | + public function transaction() |
|
| 1299 | + { |
|
| 1300 | + return $this->get_first_related('Transaction'); |
|
| 1301 | + } |
|
| 1302 | + |
|
| 1303 | + |
|
| 1304 | + /** |
|
| 1305 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1306 | + * Because there currently is no proper parent-child relation on the model, |
|
| 1307 | + * save_this_and_cached() will NOT save the descendants. |
|
| 1308 | + * Also sets the transaction on this line item and all its descendants before saving |
|
| 1309 | + * |
|
| 1310 | + * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
| 1311 | + * @return int count of items saved |
|
| 1312 | + * @throws EE_Error |
|
| 1313 | + */ |
|
| 1314 | + public function save_this_and_descendants_to_txn($txn_id = null) |
|
| 1315 | + { |
|
| 1316 | + $count = 0; |
|
| 1317 | + if (!$txn_id) { |
|
| 1318 | + $txn_id = $this->TXN_ID(); |
|
| 1319 | + } |
|
| 1320 | + $this->set_TXN_ID($txn_id); |
|
| 1321 | + $children = $this->children(); |
|
| 1322 | + $count += $this->save() |
|
| 1323 | + ? 1 |
|
| 1324 | + : 0; |
|
| 1325 | + foreach ($children as $child_line_item) { |
|
| 1326 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1327 | + $child_line_item->set_parent_ID($this->ID()); |
|
| 1328 | + $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
| 1329 | + } |
|
| 1330 | + } |
|
| 1331 | + return $count; |
|
| 1332 | + } |
|
| 1333 | + |
|
| 1334 | + |
|
| 1335 | + /** |
|
| 1336 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1337 | + * |
|
| 1338 | + * @return int count of items saved |
|
| 1339 | + * @throws EE_Error |
|
| 1340 | + */ |
|
| 1341 | + public function save_this_and_descendants() |
|
| 1342 | + { |
|
| 1343 | + $count = 0; |
|
| 1344 | + $children = $this->children(); |
|
| 1345 | + $count += $this->save() |
|
| 1346 | + ? 1 |
|
| 1347 | + : 0; |
|
| 1348 | + foreach ($children as $child_line_item) { |
|
| 1349 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1350 | + $child_line_item->set_parent_ID($this->ID()); |
|
| 1351 | + $count += $child_line_item->save_this_and_descendants(); |
|
| 1352 | + } |
|
| 1353 | + } |
|
| 1354 | + return $count; |
|
| 1355 | + } |
|
| 1356 | + |
|
| 1357 | + |
|
| 1358 | + /** |
|
| 1359 | + * returns the cancellation line item if this item was cancelled |
|
| 1360 | + * |
|
| 1361 | + * @return EE_Line_Item[] |
|
| 1362 | + * @throws InvalidArgumentException |
|
| 1363 | + * @throws InvalidInterfaceException |
|
| 1364 | + * @throws InvalidDataTypeException |
|
| 1365 | + * @throws ReflectionException |
|
| 1366 | + * @throws EE_Error |
|
| 1367 | + */ |
|
| 1368 | + public function get_cancellations() |
|
| 1369 | + { |
|
| 1370 | + EE_Registry::instance()->load_helper('Line_Item'); |
|
| 1371 | + return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
| 1372 | + } |
|
| 1373 | + |
|
| 1374 | + |
|
| 1375 | + /** |
|
| 1376 | + * If this item has an ID, then this saves it again to update the db |
|
| 1377 | + * |
|
| 1378 | + * @return int count of items saved |
|
| 1379 | + * @throws EE_Error |
|
| 1380 | + */ |
|
| 1381 | + public function maybe_save() |
|
| 1382 | + { |
|
| 1383 | + if ($this->ID()) { |
|
| 1384 | + return $this->save(); |
|
| 1385 | + } |
|
| 1386 | + return false; |
|
| 1387 | + } |
|
| 1388 | + |
|
| 1389 | + |
|
| 1390 | + /** |
|
| 1391 | + * clears the cached children and parent from the line item |
|
| 1392 | + * |
|
| 1393 | + * @return void |
|
| 1394 | + */ |
|
| 1395 | + public function clear_related_line_item_cache() |
|
| 1396 | + { |
|
| 1397 | + $this->_children = array(); |
|
| 1398 | + $this->_parent = null; |
|
| 1399 | + } |
|
| 1400 | + |
|
| 1401 | + |
|
| 1402 | + /** |
|
| 1403 | + * @param bool $raw |
|
| 1404 | + * @return int |
|
| 1405 | + * @throws EE_Error |
|
| 1406 | + */ |
|
| 1407 | + public function timestamp($raw = false) |
|
| 1408 | + { |
|
| 1409 | + return $raw |
|
| 1410 | + ? $this->get_raw('LIN_timestamp') |
|
| 1411 | + : $this->get('LIN_timestamp'); |
|
| 1412 | + } |
|
| 1413 | + |
|
| 1414 | + |
|
| 1415 | + |
|
| 1416 | + |
|
| 1417 | + /************************* DEPRECATED *************************/ |
|
| 1418 | + /** |
|
| 1419 | + * @deprecated 4.6.0 |
|
| 1420 | + * @param string $type one of the constants on EEM_Line_Item |
|
| 1421 | + * @return EE_Line_Item[] |
|
| 1422 | + */ |
|
| 1423 | + protected function _get_descendants_of_type($type) |
|
| 1424 | + { |
|
| 1425 | + EE_Error::doing_it_wrong( |
|
| 1426 | + 'EE_Line_Item::_get_descendants_of_type()', |
|
| 1427 | + __('Method replaced with EEH_Line_Item::get_descendants_of_type()', 'event_espresso'), '4.6.0' |
|
| 1428 | + ); |
|
| 1429 | + return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
| 1430 | + } |
|
| 1431 | + |
|
| 1432 | + |
|
| 1433 | + /** |
|
| 1434 | + * @deprecated 4.6.0 |
|
| 1435 | + * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1436 | + * @return EE_Line_Item |
|
| 1437 | + */ |
|
| 1438 | + public function get_nearest_descendant_of_type($type) |
|
| 1439 | + { |
|
| 1440 | + EE_Error::doing_it_wrong( |
|
| 1441 | + 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
| 1442 | + __('Method replaced with EEH_Line_Item::get_nearest_descendant_of_type()', 'event_espresso'), '4.6.0' |
|
| 1443 | + ); |
|
| 1444 | + return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
| 1445 | + } |
|
| 1446 | 1446 | |
| 1447 | 1447 | |
| 1448 | 1448 | } |
@@ -75,7 +75,7 @@ discard block |
||
| 75 | 75 | protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
| 76 | 76 | { |
| 77 | 77 | parent::__construct($fieldValues, $bydb, $timezone); |
| 78 | - if (!$this->get('LIN_code')) { |
|
| 78 | + if ( ! $this->get('LIN_code')) { |
|
| 79 | 79 | $this->set_code($this->generate_code()); |
| 80 | 80 | } |
| 81 | 81 | } |
@@ -126,7 +126,7 @@ discard block |
||
| 126 | 126 | public function name() |
| 127 | 127 | { |
| 128 | 128 | $name = $this->get('LIN_name'); |
| 129 | - if (!$name) { |
|
| 129 | + if ( ! $name) { |
|
| 130 | 130 | $name = ucwords(str_replace('-', ' ', $this->type())); |
| 131 | 131 | } |
| 132 | 132 | return $name; |
@@ -313,7 +313,7 @@ discard block |
||
| 313 | 313 | if ($unit_price < .001 && $percent) { |
| 314 | 314 | return true; |
| 315 | 315 | } |
| 316 | - if ($unit_price >= .001 && !$percent) { |
|
| 316 | + if ($unit_price >= .001 && ! $percent) { |
|
| 317 | 317 | return false; |
| 318 | 318 | } |
| 319 | 319 | if ($unit_price >= .001 && $percent) { |
@@ -482,7 +482,7 @@ discard block |
||
| 482 | 482 | ) |
| 483 | 483 | ); |
| 484 | 484 | } |
| 485 | - if (!is_array($this->_children)) { |
|
| 485 | + if ( ! is_array($this->_children)) { |
|
| 486 | 486 | $this->_children = array(); |
| 487 | 487 | } |
| 488 | 488 | return $this->_children; |
@@ -698,7 +698,7 @@ discard block |
||
| 698 | 698 | public function set_parent($line_item) |
| 699 | 699 | { |
| 700 | 700 | if ($this->ID()) { |
| 701 | - if (!$line_item->ID()) { |
|
| 701 | + if ( ! $line_item->ID()) { |
|
| 702 | 702 | $line_item->save(); |
| 703 | 703 | } |
| 704 | 704 | $this->set_parent_ID($line_item->ID()); |
@@ -769,7 +769,7 @@ discard block |
||
| 769 | 769 | $items_deleted = 0; |
| 770 | 770 | if ($this->code() === $code) { |
| 771 | 771 | $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
| 772 | - $items_deleted += (int)$this->delete(); |
|
| 772 | + $items_deleted += (int) $this->delete(); |
|
| 773 | 773 | if ($stop_search_once_found) { |
| 774 | 774 | return $items_deleted; |
| 775 | 775 | } |
@@ -797,7 +797,7 @@ discard block |
||
| 797 | 797 | */ |
| 798 | 798 | public function delete_if_childless_subtotal() |
| 799 | 799 | { |
| 800 | - if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && !$this->children()) { |
|
| 800 | + if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
| 801 | 801 | return $this->delete(); |
| 802 | 802 | } |
| 803 | 803 | return false; |
@@ -813,7 +813,7 @@ discard block |
||
| 813 | 813 | public function generate_code() |
| 814 | 814 | { |
| 815 | 815 | // each line item in the cart requires a unique identifier |
| 816 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
| 816 | + return md5($this->get('OBJ_type').$this->get('OBJ_ID').microtime()); |
|
| 817 | 817 | } |
| 818 | 818 | |
| 819 | 819 | |
@@ -974,10 +974,10 @@ discard block |
||
| 974 | 974 | { |
| 975 | 975 | $total = 0; |
| 976 | 976 | $my_children = $this->children(); |
| 977 | - $has_children = !empty($my_children); |
|
| 977 | + $has_children = ! empty($my_children); |
|
| 978 | 978 | if ($has_children && $this->is_line_item()) { |
| 979 | 979 | $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
| 980 | - } elseif (!$has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 980 | + } elseif ( ! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 981 | 981 | $total = $this->unit_price() * $this->quantity(); |
| 982 | 982 | } elseif ($this->is_sub_total() || $this->is_total()) { |
| 983 | 983 | $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
@@ -987,24 +987,24 @@ discard block |
||
| 987 | 987 | } |
| 988 | 988 | // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
| 989 | 989 | if ( |
| 990 | - !$this->is_line_item() && !$this->is_sub_line_item() && !$this->is_cancellation() |
|
| 990 | + ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
| 991 | 991 | ) { |
| 992 | 992 | if ($this->OBJ_type() !== 'Event') { |
| 993 | 993 | $this->set_quantity(1); |
| 994 | 994 | } |
| 995 | - if (!$this->is_percent()) { |
|
| 995 | + if ( ! $this->is_percent()) { |
|
| 996 | 996 | $this->set_unit_price($total); |
| 997 | 997 | } |
| 998 | 998 | } |
| 999 | 999 | //we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
| 1000 | 1000 | //so it ought to be |
| 1001 | - if (!$this->is_total()) { |
|
| 1001 | + if ( ! $this->is_total()) { |
|
| 1002 | 1002 | $this->set_total($total); |
| 1003 | 1003 | //if not a percent line item, make sure we keep the unit price in sync |
| 1004 | 1004 | if ( |
| 1005 | 1005 | $has_children |
| 1006 | 1006 | && $this->is_line_item() |
| 1007 | - && !$this->is_percent() |
|
| 1007 | + && ! $this->is_percent() |
|
| 1008 | 1008 | ) { |
| 1009 | 1009 | if ($this->quantity() === 0) { |
| 1010 | 1010 | $new_unit_price = 0; |
@@ -1041,7 +1041,7 @@ discard block |
||
| 1041 | 1041 | $subtotal_quantity = 0; |
| 1042 | 1042 | //get the total of all its children |
| 1043 | 1043 | foreach ($my_children as $child_line_item) { |
| 1044 | - if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) { |
|
| 1044 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
| 1045 | 1045 | // percentage line items are based on total so far |
| 1046 | 1046 | if ($child_line_item->is_percent()) { |
| 1047 | 1047 | //round as we go so that the line items add up ok |
@@ -1101,7 +1101,7 @@ discard block |
||
| 1101 | 1101 | $quantity_for_total = 1; |
| 1102 | 1102 | //get the total of all its children |
| 1103 | 1103 | foreach ($my_children as $child_line_item) { |
| 1104 | - if ($child_line_item instanceof EE_Line_Item && !$child_line_item->is_cancellation()) { |
|
| 1104 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
| 1105 | 1105 | if ($child_line_item->is_percent()) { |
| 1106 | 1106 | //it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
| 1107 | 1107 | //not total multiplied by percent, because that ignores rounding along-the-way |
@@ -1314,7 +1314,7 @@ discard block |
||
| 1314 | 1314 | public function save_this_and_descendants_to_txn($txn_id = null) |
| 1315 | 1315 | { |
| 1316 | 1316 | $count = 0; |
| 1317 | - if (!$txn_id) { |
|
| 1317 | + if ( ! $txn_id) { |
|
| 1318 | 1318 | $txn_id = $this->TXN_ID(); |
| 1319 | 1319 | } |
| 1320 | 1320 | $this->set_TXN_ID($txn_id); |
@@ -211,7 +211,7 @@ discard block |
||
| 211 | 211 | |
| 212 | 212 | /** |
| 213 | 213 | * @param EE_Registration $registration |
| 214 | - * @return EE_Form_Section_Base |
|
| 214 | + * @return EE_Form_Section_Proper|null |
|
| 215 | 215 | * @throws EE_Error |
| 216 | 216 | * @throws InvalidArgumentException |
| 217 | 217 | * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
@@ -610,6 +610,7 @@ discard block |
||
| 610 | 610 | * @param EE_Registration $registration |
| 611 | 611 | * @param EE_Question $question |
| 612 | 612 | * @param mixed EE_Answer|NULL $answer |
| 613 | + * @param EE_Answer $answer |
|
| 613 | 614 | * @return EE_Form_Input_Base |
| 614 | 615 | * @throws \EE_Error |
| 615 | 616 | */ |
@@ -17,1346 +17,1346 @@ |
||
| 17 | 17 | class EE_SPCO_Reg_Step_Attendee_Information extends EE_SPCO_Reg_Step |
| 18 | 18 | { |
| 19 | 19 | |
| 20 | - /** |
|
| 21 | - * @type bool $_print_copy_info |
|
| 22 | - */ |
|
| 23 | - private $_print_copy_info = false; |
|
| 24 | - |
|
| 25 | - /** |
|
| 26 | - * @type array $_attendee_data |
|
| 27 | - */ |
|
| 28 | - private $_attendee_data = array(); |
|
| 29 | - |
|
| 30 | - /** |
|
| 31 | - * @type array $_required_questions |
|
| 32 | - */ |
|
| 33 | - private $_required_questions = array(); |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * @type array $_registration_answers |
|
| 37 | - */ |
|
| 38 | - private $_registration_answers = array(); |
|
| 39 | - |
|
| 40 | - |
|
| 41 | - /** |
|
| 42 | - * class constructor |
|
| 43 | - * |
|
| 44 | - * @access public |
|
| 45 | - * @param EE_Checkout $checkout |
|
| 46 | - */ |
|
| 47 | - public function __construct(EE_Checkout $checkout) |
|
| 48 | - { |
|
| 49 | - $this->_slug = 'attendee_information'; |
|
| 50 | - $this->_name = esc_html__('Attendee Information', 'event_espresso'); |
|
| 51 | - $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php'; |
|
| 52 | - $this->checkout = $checkout; |
|
| 53 | - $this->_reset_success_message(); |
|
| 54 | - $this->set_instructions( |
|
| 55 | - esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso') |
|
| 56 | - ); |
|
| 57 | - } |
|
| 58 | - |
|
| 59 | - |
|
| 60 | - public function translate_js_strings() |
|
| 61 | - { |
|
| 62 | - EE_Registry::$i18n_js_strings['required_field'] = esc_html__( |
|
| 63 | - ' is a required question.', |
|
| 64 | - 'event_espresso' |
|
| 65 | - ); |
|
| 66 | - EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__( |
|
| 67 | - ' is a required question. Please enter a value for at least one of the options.', |
|
| 68 | - 'event_espresso' |
|
| 69 | - ); |
|
| 70 | - EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__( |
|
| 71 | - 'Please answer all required questions correctly before proceeding.', |
|
| 72 | - 'event_espresso' |
|
| 73 | - ); |
|
| 74 | - EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf( |
|
| 75 | - esc_html__( |
|
| 76 | - 'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.', |
|
| 77 | - 'event_espresso' |
|
| 78 | - ), |
|
| 79 | - '<br/>' |
|
| 80 | - ); |
|
| 81 | - EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__( |
|
| 82 | - 'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.', |
|
| 83 | - 'event_espresso' |
|
| 84 | - ); |
|
| 85 | - EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__( |
|
| 86 | - 'You must enter a valid email address.', |
|
| 87 | - 'event_espresso' |
|
| 88 | - ); |
|
| 89 | - EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__( |
|
| 90 | - 'You must enter a valid email address and answer all other required questions before you can proceed.', |
|
| 91 | - 'event_espresso' |
|
| 92 | - ); |
|
| 93 | - } |
|
| 94 | - |
|
| 95 | - |
|
| 96 | - public function enqueue_styles_and_scripts() |
|
| 97 | - { |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - |
|
| 101 | - /** |
|
| 102 | - * @return boolean |
|
| 103 | - */ |
|
| 104 | - public function initialize_reg_step() |
|
| 105 | - { |
|
| 106 | - return true; |
|
| 107 | - } |
|
| 108 | - |
|
| 109 | - |
|
| 110 | - /** |
|
| 111 | - * @return EE_Form_Section_Proper |
|
| 112 | - * @throws EE_Error |
|
| 113 | - * @throws InvalidArgumentException |
|
| 114 | - * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 115 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 116 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 117 | - */ |
|
| 118 | - public function generate_reg_form() |
|
| 119 | - { |
|
| 120 | - $this->_print_copy_info = false; |
|
| 121 | - $primary_registrant = null; |
|
| 122 | - // autoload Line_Item_Display classes |
|
| 123 | - EEH_Autoloader::register_line_item_display_autoloaders(); |
|
| 124 | - $Line_Item_Display = new EE_Line_Item_Display(); |
|
| 125 | - // calculate taxes |
|
| 126 | - $Line_Item_Display->display_line_item( |
|
| 127 | - $this->checkout->cart->get_grand_total(), |
|
| 128 | - array('set_tax_rate' => true) |
|
| 129 | - ); |
|
| 130 | - /** @var $subsections EE_Form_Section_Proper[] */ |
|
| 131 | - $subsections = array( |
|
| 132 | - 'default_hidden_inputs' => $this->reg_step_hidden_inputs(), |
|
| 133 | - ); |
|
| 134 | - $template_args = array( |
|
| 135 | - 'revisit' => $this->checkout->revisit, |
|
| 136 | - 'registrations' => array(), |
|
| 137 | - 'ticket_count' => array(), |
|
| 138 | - ); |
|
| 139 | - // grab the saved registrations from the transaction |
|
| 140 | - $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params); |
|
| 141 | - if ($registrations) { |
|
| 142 | - foreach ($registrations as $registration) { |
|
| 143 | - // can this registration be processed during this visit ? |
|
| 144 | - if ($registration instanceof EE_Registration |
|
| 145 | - && $this->checkout->visit_allows_processing_of_this_registration($registration) |
|
| 146 | - ) { |
|
| 147 | - $subsection = $this->_registrations_reg_form($registration); |
|
| 148 | - if(!$subsection instanceof EE_Form_Section_Proper) { |
|
| 149 | - continue; |
|
| 150 | - } |
|
| 151 | - $subsections[ $registration->reg_url_link() ] = $subsection; |
|
| 152 | - if (! $this->checkout->admin_request) { |
|
| 153 | - $template_args['registrations'][$registration->reg_url_link()] = $registration; |
|
| 154 | - $template_args['ticket_count'][$registration->ticket()->ID()] = isset( |
|
| 155 | - $template_args['ticket_count'][$registration->ticket()->ID()] |
|
| 156 | - ) |
|
| 157 | - ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1 |
|
| 158 | - : 1; |
|
| 159 | - $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs( |
|
| 160 | - $this->checkout->cart->get_grand_total(), |
|
| 161 | - 'Ticket', |
|
| 162 | - array($registration->ticket()->ID()) |
|
| 163 | - ); |
|
| 164 | - $ticket_line_item = is_array($ticket_line_item) |
|
| 165 | - ? reset($ticket_line_item) |
|
| 166 | - : $ticket_line_item; |
|
| 167 | - $template_args['ticket_line_item'][$registration->ticket()->ID()] = |
|
| 168 | - $Line_Item_Display->display_line_item($ticket_line_item); |
|
| 169 | - } |
|
| 170 | - if ($registration->is_primary_registrant()) { |
|
| 171 | - $primary_registrant = $registration->reg_url_link(); |
|
| 172 | - } |
|
| 173 | - } |
|
| 174 | - } |
|
| 175 | - // print_copy_info ? |
|
| 176 | - if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) { |
|
| 177 | - // TODO: add admin option for toggling copy attendee info, |
|
| 178 | - // then use that value to change $this->_print_copy_info |
|
| 179 | - $copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info |
|
| 180 | - ? $this->_copy_attendee_info_form() |
|
| 181 | - : $this->_auto_copy_attendee_info(); |
|
| 182 | - // generate hidden input |
|
| 183 | - if (isset($subsections[$primary_registrant]) |
|
| 184 | - && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper |
|
| 185 | - ) { |
|
| 186 | - $subsections[$primary_registrant]->add_subsections( |
|
| 187 | - $copy_options, |
|
| 188 | - 'primary_registrant', |
|
| 189 | - false |
|
| 190 | - ); |
|
| 191 | - } |
|
| 192 | - } |
|
| 193 | - } |
|
| 194 | - return new EE_Form_Section_Proper( |
|
| 195 | - array( |
|
| 196 | - 'name' => $this->reg_form_name(), |
|
| 197 | - 'html_id' => $this->reg_form_name(), |
|
| 198 | - 'subsections' => $subsections, |
|
| 199 | - 'layout_strategy' => $this->checkout->admin_request ? |
|
| 200 | - new EE_Div_Per_Section_Layout() : |
|
| 201 | - new EE_Template_Layout( |
|
| 202 | - array( |
|
| 203 | - 'layout_template_file' => $this->_template, // layout_template |
|
| 204 | - 'template_args' => $template_args, |
|
| 205 | - ) |
|
| 206 | - ), |
|
| 207 | - ) |
|
| 208 | - ); |
|
| 209 | - } |
|
| 210 | - |
|
| 211 | - |
|
| 212 | - /** |
|
| 213 | - * @param EE_Registration $registration |
|
| 214 | - * @return EE_Form_Section_Base |
|
| 215 | - * @throws EE_Error |
|
| 216 | - * @throws InvalidArgumentException |
|
| 217 | - * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 218 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 219 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 220 | - */ |
|
| 221 | - private function _registrations_reg_form(EE_Registration $registration) |
|
| 222 | - { |
|
| 223 | - static $attendee_nmbr = 1; |
|
| 224 | - $form_args = array(); |
|
| 225 | - // verify that registration has valid event |
|
| 226 | - if ($registration->event() instanceof EE_Event) { |
|
| 227 | - $question_groups = $registration->event()->question_groups( |
|
| 228 | - apply_filters( |
|
| 229 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters', |
|
| 230 | - array( |
|
| 231 | - array( |
|
| 232 | - 'Event.EVT_ID' => $registration->event()->ID(), |
|
| 233 | - 'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false, |
|
| 234 | - ), |
|
| 235 | - 'order_by' => array('QSG_order' => 'ASC'), |
|
| 236 | - ), |
|
| 237 | - $registration, |
|
| 238 | - $this |
|
| 239 | - ) |
|
| 240 | - ); |
|
| 241 | - if ($question_groups) { |
|
| 242 | - // array of params to pass to parent constructor |
|
| 243 | - $form_args = array( |
|
| 244 | - 'html_id' => 'ee-registration-' . $registration->reg_url_link(), |
|
| 245 | - 'html_class' => 'ee-reg-form-attendee-dv', |
|
| 246 | - 'html_style' => $this->checkout->admin_request |
|
| 247 | - ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;' |
|
| 248 | - : '', |
|
| 249 | - 'subsections' => array(), |
|
| 250 | - 'layout_strategy' => new EE_Fieldset_Section_Layout( |
|
| 251 | - array( |
|
| 252 | - 'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text', |
|
| 253 | - 'legend_text' => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr), |
|
| 254 | - ) |
|
| 255 | - ), |
|
| 256 | - ); |
|
| 257 | - foreach ($question_groups as $question_group) { |
|
| 258 | - if ($question_group instanceof EE_Question_Group) { |
|
| 259 | - $form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form( |
|
| 260 | - $registration, |
|
| 261 | - $question_group |
|
| 262 | - ); |
|
| 263 | - } |
|
| 264 | - } |
|
| 265 | - // add hidden input |
|
| 266 | - $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input( |
|
| 267 | - $registration |
|
| 268 | - ); |
|
| 269 | - // if we have question groups for additional attendees, then display the copy options |
|
| 270 | - $this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info; |
|
| 271 | - if ($registration->is_primary_registrant()) { |
|
| 272 | - // generate hidden input |
|
| 273 | - $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs( |
|
| 274 | - $registration |
|
| 275 | - ); |
|
| 276 | - } |
|
| 277 | - } |
|
| 278 | - } |
|
| 279 | - $attendee_nmbr++; |
|
| 280 | - return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : null; |
|
| 281 | - } |
|
| 282 | - |
|
| 283 | - |
|
| 284 | - /** |
|
| 285 | - * _additional_attendee_reg_info_input |
|
| 286 | - * |
|
| 287 | - * @access public |
|
| 288 | - * @param EE_Registration $registration |
|
| 289 | - * @param bool $additional_attendee_reg_info |
|
| 290 | - * @return EE_Form_Input_Base |
|
| 291 | - * @throws \EE_Error |
|
| 292 | - */ |
|
| 293 | - private function _additional_attendee_reg_info_input( |
|
| 294 | - EE_Registration $registration, |
|
| 295 | - $additional_attendee_reg_info = true |
|
| 296 | - ) { |
|
| 297 | - // generate hidden input |
|
| 298 | - return new EE_Hidden_Input( |
|
| 299 | - array( |
|
| 300 | - 'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(), |
|
| 301 | - 'default' => $additional_attendee_reg_info, |
|
| 302 | - ) |
|
| 303 | - ); |
|
| 304 | - } |
|
| 305 | - |
|
| 306 | - |
|
| 307 | - /** |
|
| 308 | - * @param EE_Registration $registration |
|
| 309 | - * @param EE_Question_Group $question_group |
|
| 310 | - * @return EE_Form_Section_Proper |
|
| 311 | - * @throws EE_Error |
|
| 312 | - * @throws InvalidArgumentException |
|
| 313 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 314 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 315 | - */ |
|
| 316 | - private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group) |
|
| 317 | - { |
|
| 318 | - // array of params to pass to parent constructor |
|
| 319 | - $form_args = array( |
|
| 320 | - 'html_id' => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(), |
|
| 321 | - 'html_class' => $this->checkout->admin_request |
|
| 322 | - ? 'form-table ee-reg-form-qstn-grp-dv' |
|
| 323 | - : 'ee-reg-form-qstn-grp-dv', |
|
| 324 | - 'html_label_id' => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID() . '-lbl', |
|
| 325 | - 'subsections' => array( |
|
| 326 | - 'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group), |
|
| 327 | - ), |
|
| 328 | - 'layout_strategy' => $this->checkout->admin_request |
|
| 329 | - ? new EE_Admin_Two_Column_Layout() |
|
| 330 | - : new EE_Div_Per_Section_Layout(), |
|
| 331 | - ); |
|
| 332 | - // where params |
|
| 333 | - $query_params = array('QST_deleted' => 0); |
|
| 334 | - // don't load admin only questions on the frontend |
|
| 335 | - if (! $this->checkout->admin_request) { |
|
| 336 | - $query_params['QST_admin_only'] = array('!=', true); |
|
| 337 | - } |
|
| 338 | - $questions = $question_group->get_many_related( |
|
| 339 | - 'Question', |
|
| 340 | - apply_filters( |
|
| 341 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params', |
|
| 342 | - array( |
|
| 343 | - $query_params, |
|
| 344 | - 'order_by' => array( |
|
| 345 | - 'Question_Group_Question.QGQ_order' => 'ASC', |
|
| 346 | - ), |
|
| 347 | - ), |
|
| 348 | - $question_group, |
|
| 349 | - $registration, |
|
| 350 | - $this |
|
| 351 | - ) |
|
| 352 | - ); |
|
| 353 | - // filter for additional content before questions |
|
| 354 | - $form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML( |
|
| 355 | - apply_filters( |
|
| 356 | - 'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', |
|
| 357 | - '', |
|
| 358 | - $registration, |
|
| 359 | - $question_group, |
|
| 360 | - $this |
|
| 361 | - ) |
|
| 362 | - ); |
|
| 363 | - // loop thru questions |
|
| 364 | - foreach ($questions as $question) { |
|
| 365 | - if ($question instanceof EE_Question) { |
|
| 366 | - $identifier = $question->is_system_question() |
|
| 367 | - ? $question->system_ID() |
|
| 368 | - : $question->ID(); |
|
| 369 | - $form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question); |
|
| 370 | - } |
|
| 371 | - } |
|
| 372 | - $form_args['subsections'] = apply_filters( |
|
| 373 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array', |
|
| 374 | - $form_args['subsections'], |
|
| 375 | - $registration, |
|
| 376 | - $question_group, |
|
| 377 | - $this |
|
| 378 | - ); |
|
| 379 | - // filter for additional content after questions |
|
| 380 | - $form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML( |
|
| 381 | - apply_filters( |
|
| 382 | - 'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', |
|
| 383 | - '', |
|
| 384 | - $registration, |
|
| 385 | - $question_group, |
|
| 386 | - $this |
|
| 387 | - ) |
|
| 388 | - ); |
|
| 20 | + /** |
|
| 21 | + * @type bool $_print_copy_info |
|
| 22 | + */ |
|
| 23 | + private $_print_copy_info = false; |
|
| 24 | + |
|
| 25 | + /** |
|
| 26 | + * @type array $_attendee_data |
|
| 27 | + */ |
|
| 28 | + private $_attendee_data = array(); |
|
| 29 | + |
|
| 30 | + /** |
|
| 31 | + * @type array $_required_questions |
|
| 32 | + */ |
|
| 33 | + private $_required_questions = array(); |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * @type array $_registration_answers |
|
| 37 | + */ |
|
| 38 | + private $_registration_answers = array(); |
|
| 39 | + |
|
| 40 | + |
|
| 41 | + /** |
|
| 42 | + * class constructor |
|
| 43 | + * |
|
| 44 | + * @access public |
|
| 45 | + * @param EE_Checkout $checkout |
|
| 46 | + */ |
|
| 47 | + public function __construct(EE_Checkout $checkout) |
|
| 48 | + { |
|
| 49 | + $this->_slug = 'attendee_information'; |
|
| 50 | + $this->_name = esc_html__('Attendee Information', 'event_espresso'); |
|
| 51 | + $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php'; |
|
| 52 | + $this->checkout = $checkout; |
|
| 53 | + $this->_reset_success_message(); |
|
| 54 | + $this->set_instructions( |
|
| 55 | + esc_html__('Please answer the following registration questions before proceeding.', 'event_espresso') |
|
| 56 | + ); |
|
| 57 | + } |
|
| 58 | + |
|
| 59 | + |
|
| 60 | + public function translate_js_strings() |
|
| 61 | + { |
|
| 62 | + EE_Registry::$i18n_js_strings['required_field'] = esc_html__( |
|
| 63 | + ' is a required question.', |
|
| 64 | + 'event_espresso' |
|
| 65 | + ); |
|
| 66 | + EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__( |
|
| 67 | + ' is a required question. Please enter a value for at least one of the options.', |
|
| 68 | + 'event_espresso' |
|
| 69 | + ); |
|
| 70 | + EE_Registry::$i18n_js_strings['answer_required_questions'] = esc_html__( |
|
| 71 | + 'Please answer all required questions correctly before proceeding.', |
|
| 72 | + 'event_espresso' |
|
| 73 | + ); |
|
| 74 | + EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf( |
|
| 75 | + esc_html__( |
|
| 76 | + 'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.', |
|
| 77 | + 'event_espresso' |
|
| 78 | + ), |
|
| 79 | + '<br/>' |
|
| 80 | + ); |
|
| 81 | + EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__( |
|
| 82 | + 'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.', |
|
| 83 | + 'event_espresso' |
|
| 84 | + ); |
|
| 85 | + EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__( |
|
| 86 | + 'You must enter a valid email address.', |
|
| 87 | + 'event_espresso' |
|
| 88 | + ); |
|
| 89 | + EE_Registry::$i18n_js_strings['valid_email_and_questions'] = esc_html__( |
|
| 90 | + 'You must enter a valid email address and answer all other required questions before you can proceed.', |
|
| 91 | + 'event_espresso' |
|
| 92 | + ); |
|
| 93 | + } |
|
| 94 | + |
|
| 95 | + |
|
| 96 | + public function enqueue_styles_and_scripts() |
|
| 97 | + { |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + |
|
| 101 | + /** |
|
| 102 | + * @return boolean |
|
| 103 | + */ |
|
| 104 | + public function initialize_reg_step() |
|
| 105 | + { |
|
| 106 | + return true; |
|
| 107 | + } |
|
| 108 | + |
|
| 109 | + |
|
| 110 | + /** |
|
| 111 | + * @return EE_Form_Section_Proper |
|
| 112 | + * @throws EE_Error |
|
| 113 | + * @throws InvalidArgumentException |
|
| 114 | + * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 115 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 116 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 117 | + */ |
|
| 118 | + public function generate_reg_form() |
|
| 119 | + { |
|
| 120 | + $this->_print_copy_info = false; |
|
| 121 | + $primary_registrant = null; |
|
| 122 | + // autoload Line_Item_Display classes |
|
| 123 | + EEH_Autoloader::register_line_item_display_autoloaders(); |
|
| 124 | + $Line_Item_Display = new EE_Line_Item_Display(); |
|
| 125 | + // calculate taxes |
|
| 126 | + $Line_Item_Display->display_line_item( |
|
| 127 | + $this->checkout->cart->get_grand_total(), |
|
| 128 | + array('set_tax_rate' => true) |
|
| 129 | + ); |
|
| 130 | + /** @var $subsections EE_Form_Section_Proper[] */ |
|
| 131 | + $subsections = array( |
|
| 132 | + 'default_hidden_inputs' => $this->reg_step_hidden_inputs(), |
|
| 133 | + ); |
|
| 134 | + $template_args = array( |
|
| 135 | + 'revisit' => $this->checkout->revisit, |
|
| 136 | + 'registrations' => array(), |
|
| 137 | + 'ticket_count' => array(), |
|
| 138 | + ); |
|
| 139 | + // grab the saved registrations from the transaction |
|
| 140 | + $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params); |
|
| 141 | + if ($registrations) { |
|
| 142 | + foreach ($registrations as $registration) { |
|
| 143 | + // can this registration be processed during this visit ? |
|
| 144 | + if ($registration instanceof EE_Registration |
|
| 145 | + && $this->checkout->visit_allows_processing_of_this_registration($registration) |
|
| 146 | + ) { |
|
| 147 | + $subsection = $this->_registrations_reg_form($registration); |
|
| 148 | + if(!$subsection instanceof EE_Form_Section_Proper) { |
|
| 149 | + continue; |
|
| 150 | + } |
|
| 151 | + $subsections[ $registration->reg_url_link() ] = $subsection; |
|
| 152 | + if (! $this->checkout->admin_request) { |
|
| 153 | + $template_args['registrations'][$registration->reg_url_link()] = $registration; |
|
| 154 | + $template_args['ticket_count'][$registration->ticket()->ID()] = isset( |
|
| 155 | + $template_args['ticket_count'][$registration->ticket()->ID()] |
|
| 156 | + ) |
|
| 157 | + ? $template_args['ticket_count'][$registration->ticket()->ID()] + 1 |
|
| 158 | + : 1; |
|
| 159 | + $ticket_line_item = EEH_Line_Item::get_line_items_by_object_type_and_IDs( |
|
| 160 | + $this->checkout->cart->get_grand_total(), |
|
| 161 | + 'Ticket', |
|
| 162 | + array($registration->ticket()->ID()) |
|
| 163 | + ); |
|
| 164 | + $ticket_line_item = is_array($ticket_line_item) |
|
| 165 | + ? reset($ticket_line_item) |
|
| 166 | + : $ticket_line_item; |
|
| 167 | + $template_args['ticket_line_item'][$registration->ticket()->ID()] = |
|
| 168 | + $Line_Item_Display->display_line_item($ticket_line_item); |
|
| 169 | + } |
|
| 170 | + if ($registration->is_primary_registrant()) { |
|
| 171 | + $primary_registrant = $registration->reg_url_link(); |
|
| 172 | + } |
|
| 173 | + } |
|
| 174 | + } |
|
| 175 | + // print_copy_info ? |
|
| 176 | + if ($primary_registrant && ! $this->checkout->admin_request && count($registrations) > 1) { |
|
| 177 | + // TODO: add admin option for toggling copy attendee info, |
|
| 178 | + // then use that value to change $this->_print_copy_info |
|
| 179 | + $copy_options['spco_copy_attendee_chk'] = $this->_print_copy_info |
|
| 180 | + ? $this->_copy_attendee_info_form() |
|
| 181 | + : $this->_auto_copy_attendee_info(); |
|
| 182 | + // generate hidden input |
|
| 183 | + if (isset($subsections[$primary_registrant]) |
|
| 184 | + && $subsections[$primary_registrant] instanceof EE_Form_Section_Proper |
|
| 185 | + ) { |
|
| 186 | + $subsections[$primary_registrant]->add_subsections( |
|
| 187 | + $copy_options, |
|
| 188 | + 'primary_registrant', |
|
| 189 | + false |
|
| 190 | + ); |
|
| 191 | + } |
|
| 192 | + } |
|
| 193 | + } |
|
| 194 | + return new EE_Form_Section_Proper( |
|
| 195 | + array( |
|
| 196 | + 'name' => $this->reg_form_name(), |
|
| 197 | + 'html_id' => $this->reg_form_name(), |
|
| 198 | + 'subsections' => $subsections, |
|
| 199 | + 'layout_strategy' => $this->checkout->admin_request ? |
|
| 200 | + new EE_Div_Per_Section_Layout() : |
|
| 201 | + new EE_Template_Layout( |
|
| 202 | + array( |
|
| 203 | + 'layout_template_file' => $this->_template, // layout_template |
|
| 204 | + 'template_args' => $template_args, |
|
| 205 | + ) |
|
| 206 | + ), |
|
| 207 | + ) |
|
| 208 | + ); |
|
| 209 | + } |
|
| 210 | + |
|
| 211 | + |
|
| 212 | + /** |
|
| 213 | + * @param EE_Registration $registration |
|
| 214 | + * @return EE_Form_Section_Base |
|
| 215 | + * @throws EE_Error |
|
| 216 | + * @throws InvalidArgumentException |
|
| 217 | + * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 218 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 219 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 220 | + */ |
|
| 221 | + private function _registrations_reg_form(EE_Registration $registration) |
|
| 222 | + { |
|
| 223 | + static $attendee_nmbr = 1; |
|
| 224 | + $form_args = array(); |
|
| 225 | + // verify that registration has valid event |
|
| 226 | + if ($registration->event() instanceof EE_Event) { |
|
| 227 | + $question_groups = $registration->event()->question_groups( |
|
| 228 | + apply_filters( |
|
| 229 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___registrations_reg_form__question_groups_query_parameters', |
|
| 230 | + array( |
|
| 231 | + array( |
|
| 232 | + 'Event.EVT_ID' => $registration->event()->ID(), |
|
| 233 | + 'Event_Question_Group.EQG_primary' => $registration->count() === 1 ? true : false, |
|
| 234 | + ), |
|
| 235 | + 'order_by' => array('QSG_order' => 'ASC'), |
|
| 236 | + ), |
|
| 237 | + $registration, |
|
| 238 | + $this |
|
| 239 | + ) |
|
| 240 | + ); |
|
| 241 | + if ($question_groups) { |
|
| 242 | + // array of params to pass to parent constructor |
|
| 243 | + $form_args = array( |
|
| 244 | + 'html_id' => 'ee-registration-' . $registration->reg_url_link(), |
|
| 245 | + 'html_class' => 'ee-reg-form-attendee-dv', |
|
| 246 | + 'html_style' => $this->checkout->admin_request |
|
| 247 | + ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;' |
|
| 248 | + : '', |
|
| 249 | + 'subsections' => array(), |
|
| 250 | + 'layout_strategy' => new EE_Fieldset_Section_Layout( |
|
| 251 | + array( |
|
| 252 | + 'legend_class' => 'spco-attendee-lgnd smaller-text lt-grey-text', |
|
| 253 | + 'legend_text' => sprintf(__('Attendee %d', 'event_espresso'), $attendee_nmbr), |
|
| 254 | + ) |
|
| 255 | + ), |
|
| 256 | + ); |
|
| 257 | + foreach ($question_groups as $question_group) { |
|
| 258 | + if ($question_group instanceof EE_Question_Group) { |
|
| 259 | + $form_args['subsections'][$question_group->identifier()] = $this->_question_group_reg_form( |
|
| 260 | + $registration, |
|
| 261 | + $question_group |
|
| 262 | + ); |
|
| 263 | + } |
|
| 264 | + } |
|
| 265 | + // add hidden input |
|
| 266 | + $form_args['subsections']['additional_attendee_reg_info'] = $this->_additional_attendee_reg_info_input( |
|
| 267 | + $registration |
|
| 268 | + ); |
|
| 269 | + // if we have question groups for additional attendees, then display the copy options |
|
| 270 | + $this->_print_copy_info = $attendee_nmbr > 1 ? true : $this->_print_copy_info; |
|
| 271 | + if ($registration->is_primary_registrant()) { |
|
| 272 | + // generate hidden input |
|
| 273 | + $form_args['subsections']['primary_registrant'] = $this->_additional_primary_registrant_inputs( |
|
| 274 | + $registration |
|
| 275 | + ); |
|
| 276 | + } |
|
| 277 | + } |
|
| 278 | + } |
|
| 279 | + $attendee_nmbr++; |
|
| 280 | + return ! empty($form_args) ? new EE_Form_Section_Proper($form_args) : null; |
|
| 281 | + } |
|
| 282 | + |
|
| 283 | + |
|
| 284 | + /** |
|
| 285 | + * _additional_attendee_reg_info_input |
|
| 286 | + * |
|
| 287 | + * @access public |
|
| 288 | + * @param EE_Registration $registration |
|
| 289 | + * @param bool $additional_attendee_reg_info |
|
| 290 | + * @return EE_Form_Input_Base |
|
| 291 | + * @throws \EE_Error |
|
| 292 | + */ |
|
| 293 | + private function _additional_attendee_reg_info_input( |
|
| 294 | + EE_Registration $registration, |
|
| 295 | + $additional_attendee_reg_info = true |
|
| 296 | + ) { |
|
| 297 | + // generate hidden input |
|
| 298 | + return new EE_Hidden_Input( |
|
| 299 | + array( |
|
| 300 | + 'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(), |
|
| 301 | + 'default' => $additional_attendee_reg_info, |
|
| 302 | + ) |
|
| 303 | + ); |
|
| 304 | + } |
|
| 305 | + |
|
| 306 | + |
|
| 307 | + /** |
|
| 308 | + * @param EE_Registration $registration |
|
| 309 | + * @param EE_Question_Group $question_group |
|
| 310 | + * @return EE_Form_Section_Proper |
|
| 311 | + * @throws EE_Error |
|
| 312 | + * @throws InvalidArgumentException |
|
| 313 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 314 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 315 | + */ |
|
| 316 | + private function _question_group_reg_form(EE_Registration $registration, EE_Question_Group $question_group) |
|
| 317 | + { |
|
| 318 | + // array of params to pass to parent constructor |
|
| 319 | + $form_args = array( |
|
| 320 | + 'html_id' => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(), |
|
| 321 | + 'html_class' => $this->checkout->admin_request |
|
| 322 | + ? 'form-table ee-reg-form-qstn-grp-dv' |
|
| 323 | + : 'ee-reg-form-qstn-grp-dv', |
|
| 324 | + 'html_label_id' => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID() . '-lbl', |
|
| 325 | + 'subsections' => array( |
|
| 326 | + 'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group), |
|
| 327 | + ), |
|
| 328 | + 'layout_strategy' => $this->checkout->admin_request |
|
| 329 | + ? new EE_Admin_Two_Column_Layout() |
|
| 330 | + : new EE_Div_Per_Section_Layout(), |
|
| 331 | + ); |
|
| 332 | + // where params |
|
| 333 | + $query_params = array('QST_deleted' => 0); |
|
| 334 | + // don't load admin only questions on the frontend |
|
| 335 | + if (! $this->checkout->admin_request) { |
|
| 336 | + $query_params['QST_admin_only'] = array('!=', true); |
|
| 337 | + } |
|
| 338 | + $questions = $question_group->get_many_related( |
|
| 339 | + 'Question', |
|
| 340 | + apply_filters( |
|
| 341 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__related_questions_query_params', |
|
| 342 | + array( |
|
| 343 | + $query_params, |
|
| 344 | + 'order_by' => array( |
|
| 345 | + 'Question_Group_Question.QGQ_order' => 'ASC', |
|
| 346 | + ), |
|
| 347 | + ), |
|
| 348 | + $question_group, |
|
| 349 | + $registration, |
|
| 350 | + $this |
|
| 351 | + ) |
|
| 352 | + ); |
|
| 353 | + // filter for additional content before questions |
|
| 354 | + $form_args['subsections']['reg_form_questions_before'] = new EE_Form_Section_HTML( |
|
| 355 | + apply_filters( |
|
| 356 | + 'FHEE__EEH_Form_Fields__generate_question_groups_html__before_question_group_questions', |
|
| 357 | + '', |
|
| 358 | + $registration, |
|
| 359 | + $question_group, |
|
| 360 | + $this |
|
| 361 | + ) |
|
| 362 | + ); |
|
| 363 | + // loop thru questions |
|
| 364 | + foreach ($questions as $question) { |
|
| 365 | + if ($question instanceof EE_Question) { |
|
| 366 | + $identifier = $question->is_system_question() |
|
| 367 | + ? $question->system_ID() |
|
| 368 | + : $question->ID(); |
|
| 369 | + $form_args['subsections'][$identifier] = $this->reg_form_question($registration, $question); |
|
| 370 | + } |
|
| 371 | + } |
|
| 372 | + $form_args['subsections'] = apply_filters( |
|
| 373 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__question_group_reg_form__subsections_array', |
|
| 374 | + $form_args['subsections'], |
|
| 375 | + $registration, |
|
| 376 | + $question_group, |
|
| 377 | + $this |
|
| 378 | + ); |
|
| 379 | + // filter for additional content after questions |
|
| 380 | + $form_args['subsections']['reg_form_questions_after'] = new EE_Form_Section_HTML( |
|
| 381 | + apply_filters( |
|
| 382 | + 'FHEE__EEH_Form_Fields__generate_question_groups_html__after_question_group_questions', |
|
| 383 | + '', |
|
| 384 | + $registration, |
|
| 385 | + $question_group, |
|
| 386 | + $this |
|
| 387 | + ) |
|
| 388 | + ); |
|
| 389 | 389 | // d( $form_args ); |
| 390 | - $question_group_reg_form = new EE_Form_Section_Proper($form_args); |
|
| 391 | - return apply_filters( |
|
| 392 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form', |
|
| 393 | - $question_group_reg_form, |
|
| 394 | - $registration, |
|
| 395 | - $question_group, |
|
| 396 | - $this |
|
| 397 | - ); |
|
| 398 | - } |
|
| 399 | - |
|
| 400 | - |
|
| 401 | - /** |
|
| 402 | - * @access public |
|
| 403 | - * @param EE_Question_Group $question_group |
|
| 404 | - * @return EE_Form_Section_HTML |
|
| 405 | - */ |
|
| 406 | - private function _question_group_header(EE_Question_Group $question_group) |
|
| 407 | - { |
|
| 408 | - $html = ''; |
|
| 409 | - // group_name |
|
| 410 | - if ($question_group->show_group_name() && $question_group->name() !== '') { |
|
| 411 | - if ($this->checkout->admin_request) { |
|
| 412 | - $html .= EEH_HTML::br(); |
|
| 413 | - $html .= EEH_HTML::h3( |
|
| 414 | - $question_group->name(), |
|
| 415 | - '', |
|
| 416 | - 'ee-reg-form-qstn-grp-title title', |
|
| 417 | - 'font-size: 1.3em; padding-left:0;' |
|
| 418 | - ); |
|
| 419 | - } else { |
|
| 420 | - $html .= EEH_HTML::h4( |
|
| 421 | - $question_group->name(), |
|
| 422 | - '', |
|
| 423 | - 'ee-reg-form-qstn-grp-title section-title' |
|
| 424 | - ); |
|
| 425 | - } |
|
| 426 | - } |
|
| 427 | - // group_desc |
|
| 428 | - if ($question_group->show_group_desc() && $question_group->desc() !== '') { |
|
| 429 | - $html .= EEH_HTML::p( |
|
| 430 | - $question_group->desc(), |
|
| 431 | - '', |
|
| 432 | - $this->checkout->admin_request |
|
| 433 | - ? 'ee-reg-form-qstn-grp-desc-pg' |
|
| 434 | - : 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text' |
|
| 435 | - ); |
|
| 436 | - } |
|
| 437 | - return new EE_Form_Section_HTML($html); |
|
| 438 | - } |
|
| 439 | - |
|
| 440 | - |
|
| 441 | - /** |
|
| 442 | - * @access public |
|
| 443 | - * @return EE_Form_Section_Proper |
|
| 444 | - * @throws \EE_Error |
|
| 445 | - */ |
|
| 446 | - private function _copy_attendee_info_form() |
|
| 447 | - { |
|
| 448 | - // array of params to pass to parent constructor |
|
| 449 | - return new EE_Form_Section_Proper( |
|
| 450 | - array( |
|
| 451 | - 'subsections' => $this->_copy_attendee_info_inputs(), |
|
| 452 | - 'layout_strategy' => new EE_Template_Layout( |
|
| 453 | - array( |
|
| 454 | - 'layout_template_file' => SPCO_REG_STEPS_PATH |
|
| 455 | - . $this->_slug |
|
| 456 | - . DS |
|
| 457 | - . 'copy_attendee_info.template.php', |
|
| 458 | - 'begin_template_file' => null, |
|
| 459 | - 'input_template_file' => null, |
|
| 460 | - 'subsection_template_file' => null, |
|
| 461 | - 'end_template_file' => null, |
|
| 462 | - ) |
|
| 463 | - ), |
|
| 464 | - ) |
|
| 465 | - ); |
|
| 466 | - } |
|
| 467 | - |
|
| 468 | - |
|
| 469 | - /** |
|
| 470 | - * _auto_copy_attendee_info |
|
| 471 | - * |
|
| 472 | - * @access public |
|
| 473 | - * @return EE_Form_Section_HTML |
|
| 474 | - */ |
|
| 475 | - private function _auto_copy_attendee_info() |
|
| 476 | - { |
|
| 477 | - return new EE_Form_Section_HTML( |
|
| 478 | - EEH_Template::locate_template( |
|
| 479 | - SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php', |
|
| 480 | - apply_filters( |
|
| 481 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args', |
|
| 482 | - array() |
|
| 483 | - ), |
|
| 484 | - true, |
|
| 485 | - true |
|
| 486 | - ) |
|
| 487 | - ); |
|
| 488 | - } |
|
| 489 | - |
|
| 490 | - |
|
| 491 | - /** |
|
| 492 | - * _copy_attendee_info_inputs |
|
| 493 | - * |
|
| 494 | - * @access public |
|
| 495 | - * @return array |
|
| 496 | - * @throws \EE_Error |
|
| 497 | - */ |
|
| 498 | - private function _copy_attendee_info_inputs() |
|
| 499 | - { |
|
| 500 | - $copy_attendee_info_inputs = array(); |
|
| 501 | - $prev_ticket = null; |
|
| 502 | - // grab the saved registrations from the transaction |
|
| 503 | - $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params); |
|
| 504 | - foreach ($registrations as $registration) { |
|
| 505 | - // for all attendees other than the primary attendee |
|
| 506 | - if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) { |
|
| 507 | - // if this is a new ticket OR if this is the very first additional attendee after the primary attendee |
|
| 508 | - if ($registration->ticket()->ID() !== $prev_ticket) { |
|
| 509 | - $item_name = $registration->ticket()->name(); |
|
| 510 | - $item_name .= $registration->ticket()->description() !== '' |
|
| 511 | - ? ' - ' . $registration->ticket()->description() |
|
| 512 | - : ''; |
|
| 513 | - $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] = |
|
| 514 | - new EE_Form_Section_HTML( |
|
| 515 | - '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>' |
|
| 516 | - ); |
|
| 517 | - $prev_ticket = $registration->ticket()->ID(); |
|
| 518 | - } |
|
| 519 | - |
|
| 520 | - $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] = |
|
| 521 | - new EE_Checkbox_Multi_Input( |
|
| 522 | - array( |
|
| 523 | - $registration->ID() => sprintf( |
|
| 524 | - esc_html__('Attendee #%s', 'event_espresso'), |
|
| 525 | - $registration->count() |
|
| 526 | - ), |
|
| 527 | - ), |
|
| 528 | - array( |
|
| 529 | - 'html_id' => 'spco-copy-attendee-chk-' . $registration->reg_url_link(), |
|
| 530 | - 'html_class' => 'spco-copy-attendee-chk ee-do-not-validate', |
|
| 531 | - 'display_html_label_text' => false, |
|
| 532 | - ) |
|
| 533 | - ); |
|
| 534 | - } |
|
| 535 | - } |
|
| 536 | - return $copy_attendee_info_inputs; |
|
| 537 | - } |
|
| 538 | - |
|
| 539 | - |
|
| 540 | - /** |
|
| 541 | - * _additional_primary_registrant_inputs |
|
| 542 | - * |
|
| 543 | - * @access public |
|
| 544 | - * @param EE_Registration $registration |
|
| 545 | - * @return EE_Form_Input_Base |
|
| 546 | - * @throws \EE_Error |
|
| 547 | - */ |
|
| 548 | - private function _additional_primary_registrant_inputs(EE_Registration $registration) |
|
| 549 | - { |
|
| 550 | - // generate hidden input |
|
| 551 | - return new EE_Hidden_Input( |
|
| 552 | - array( |
|
| 553 | - 'html_id' => 'primary_registrant', |
|
| 554 | - 'default' => $registration->reg_url_link(), |
|
| 555 | - ) |
|
| 556 | - ); |
|
| 557 | - } |
|
| 558 | - |
|
| 559 | - |
|
| 560 | - /** |
|
| 561 | - * @access public |
|
| 562 | - * @param EE_Registration $registration |
|
| 563 | - * @param EE_Question $question |
|
| 564 | - * @return EE_Form_Input_Base |
|
| 565 | - * @throws EE_Error |
|
| 566 | - * @throws InvalidArgumentException |
|
| 567 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 568 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 569 | - */ |
|
| 570 | - public function reg_form_question(EE_Registration $registration, EE_Question $question) |
|
| 571 | - { |
|
| 572 | - |
|
| 573 | - // if this question was for an attendee detail, then check for that answer |
|
| 574 | - $answer_value = EEM_Answer::instance()->get_attendee_property_answer_value( |
|
| 575 | - $registration, |
|
| 576 | - $question->system_ID() |
|
| 577 | - ); |
|
| 578 | - $answer = $answer_value === null |
|
| 579 | - ? EEM_Answer::instance()->get_one( |
|
| 580 | - array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID())) |
|
| 581 | - ) |
|
| 582 | - : null; |
|
| 583 | - // if NOT returning to edit an existing registration |
|
| 584 | - // OR if this question is for an attendee property |
|
| 585 | - // OR we still don't have an EE_Answer object |
|
| 586 | - if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) { |
|
| 587 | - // create an EE_Answer object for storing everything in |
|
| 588 | - $answer = EE_Answer::new_instance(array( |
|
| 589 | - 'QST_ID' => $question->ID(), |
|
| 590 | - 'REG_ID' => $registration->ID(), |
|
| 591 | - )); |
|
| 592 | - } |
|
| 593 | - // verify instance |
|
| 594 | - if ($answer instanceof EE_Answer) { |
|
| 595 | - if (! empty($answer_value)) { |
|
| 596 | - $answer->set('ANS_value', $answer_value); |
|
| 597 | - } |
|
| 598 | - $answer->cache('Question', $question); |
|
| 599 | - //remember system ID had a bug where sometimes it could be null |
|
| 600 | - $answer_cache_id = $question->is_system_question() |
|
| 601 | - ? $question->system_ID() . '-' . $registration->reg_url_link() |
|
| 602 | - : $question->ID() . '-' . $registration->reg_url_link(); |
|
| 603 | - $registration->cache('Answer', $answer, $answer_cache_id); |
|
| 604 | - } |
|
| 605 | - return $this->_generate_question_input($registration, $question, $answer); |
|
| 606 | - } |
|
| 607 | - |
|
| 608 | - |
|
| 609 | - /** |
|
| 610 | - * @param EE_Registration $registration |
|
| 611 | - * @param EE_Question $question |
|
| 612 | - * @param mixed EE_Answer|NULL $answer |
|
| 613 | - * @return EE_Form_Input_Base |
|
| 614 | - * @throws \EE_Error |
|
| 615 | - */ |
|
| 616 | - private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer) |
|
| 617 | - { |
|
| 618 | - $identifier = $question->is_system_question() |
|
| 619 | - ? $question->system_ID() |
|
| 620 | - : $question->ID(); |
|
| 621 | - $this->_required_questions[$identifier] = $question->required() ? true : false; |
|
| 622 | - add_filter( |
|
| 623 | - 'FHEE__EE_Question__generate_form_input__country_options', |
|
| 624 | - array($this, 'use_cached_countries_for_form_input'), |
|
| 625 | - 10, |
|
| 626 | - 4 |
|
| 627 | - ); |
|
| 628 | - add_filter( |
|
| 629 | - 'FHEE__EE_Question__generate_form_input__state_options', |
|
| 630 | - array($this, 'use_cached_states_for_form_input'), |
|
| 631 | - 10, |
|
| 632 | - 4 |
|
| 633 | - ); |
|
| 634 | - $input_constructor_args = array( |
|
| 635 | - 'html_name' => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']', |
|
| 636 | - 'html_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier, |
|
| 637 | - 'html_class' => 'ee-reg-qstn ee-reg-qstn-' . $identifier, |
|
| 638 | - 'html_label_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier, |
|
| 639 | - 'html_label_class' => 'ee-reg-qstn', |
|
| 640 | - ); |
|
| 641 | - $input_constructor_args['html_label_id'] .= '-lbl'; |
|
| 642 | - if ($answer instanceof EE_Answer && $answer->ID()) { |
|
| 643 | - $input_constructor_args['html_name'] .= '[' . $answer->ID() . ']'; |
|
| 644 | - $input_constructor_args['html_id'] .= '-' . $answer->ID(); |
|
| 645 | - $input_constructor_args['html_label_id'] .= '-' . $answer->ID(); |
|
| 646 | - } |
|
| 647 | - $form_input = $question->generate_form_input( |
|
| 648 | - $registration, |
|
| 649 | - $answer, |
|
| 650 | - $input_constructor_args |
|
| 651 | - ); |
|
| 652 | - remove_filter( |
|
| 653 | - 'FHEE__EE_Question__generate_form_input__country_options', |
|
| 654 | - array($this, 'use_cached_countries_for_form_input') |
|
| 655 | - ); |
|
| 656 | - remove_filter( |
|
| 657 | - 'FHEE__EE_Question__generate_form_input__state_options', |
|
| 658 | - array($this, 'use_cached_states_for_form_input') |
|
| 659 | - ); |
|
| 660 | - return $form_input; |
|
| 661 | - } |
|
| 662 | - |
|
| 663 | - |
|
| 664 | - /** |
|
| 665 | - * Gets the list of countries for the form input |
|
| 666 | - * |
|
| 667 | - * @param array|null $countries_list |
|
| 668 | - * @param \EE_Question $question |
|
| 669 | - * @param \EE_Registration $registration |
|
| 670 | - * @param \EE_Answer $answer |
|
| 671 | - * @return array 2d keys are country IDs, values are their names |
|
| 672 | - * @throws EE_Error |
|
| 673 | - * @throws InvalidArgumentException |
|
| 674 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 675 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 676 | - */ |
|
| 677 | - public function use_cached_countries_for_form_input( |
|
| 678 | - $countries_list, |
|
| 679 | - \EE_Question $question = null, |
|
| 680 | - \EE_Registration $registration = null, |
|
| 681 | - \EE_Answer $answer = null |
|
| 682 | - ) { |
|
| 683 | - $country_options = array('' => ''); |
|
| 684 | - // get possibly cached list of countries |
|
| 685 | - $countries = $this->checkout->action === 'process_reg_step' |
|
| 686 | - ? EEM_Country::instance()->get_all_countries() |
|
| 687 | - : EEM_Country::instance()->get_all_active_countries(); |
|
| 688 | - if (! empty($countries)) { |
|
| 689 | - foreach ($countries as $country) { |
|
| 690 | - if ($country instanceof EE_Country) { |
|
| 691 | - $country_options[$country->ID()] = $country->name(); |
|
| 692 | - } |
|
| 693 | - } |
|
| 694 | - } |
|
| 695 | - if ($question instanceof EE_Question |
|
| 696 | - && $registration instanceof EE_Registration) { |
|
| 697 | - $answer = EEM_Answer::instance()->get_one( |
|
| 698 | - array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID())) |
|
| 699 | - ); |
|
| 700 | - } else { |
|
| 701 | - $answer = EE_Answer::new_instance(); |
|
| 702 | - } |
|
| 703 | - $country_options = apply_filters( |
|
| 704 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options', |
|
| 705 | - $country_options, |
|
| 706 | - $this, |
|
| 707 | - $registration, |
|
| 708 | - $question, |
|
| 709 | - $answer |
|
| 710 | - ); |
|
| 711 | - return $country_options; |
|
| 712 | - } |
|
| 713 | - |
|
| 714 | - |
|
| 715 | - /** |
|
| 716 | - * Gets the list of states for the form input |
|
| 717 | - * |
|
| 718 | - * @param array|null $states_list |
|
| 719 | - * @param \EE_Question $question |
|
| 720 | - * @param \EE_Registration $registration |
|
| 721 | - * @param \EE_Answer $answer |
|
| 722 | - * @return array 2d keys are state IDs, values are their names |
|
| 723 | - * @throws EE_Error |
|
| 724 | - * @throws InvalidArgumentException |
|
| 725 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 726 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 727 | - */ |
|
| 728 | - public function use_cached_states_for_form_input( |
|
| 729 | - $states_list, |
|
| 730 | - \EE_Question $question = null, |
|
| 731 | - \EE_Registration $registration = null, |
|
| 732 | - \EE_Answer $answer = null |
|
| 733 | - ) { |
|
| 734 | - $state_options = array('' => array('' => '')); |
|
| 735 | - $states = $this->checkout->action === 'process_reg_step' |
|
| 736 | - ? EEM_State::instance()->get_all_states() |
|
| 737 | - : EEM_State::instance()->get_all_active_states(); |
|
| 738 | - if (! empty($states)) { |
|
| 739 | - foreach ($states as $state) { |
|
| 740 | - if ($state instanceof EE_State) { |
|
| 741 | - $state_options[$state->country()->name()][$state->ID()] = $state->name(); |
|
| 742 | - } |
|
| 743 | - } |
|
| 744 | - } |
|
| 745 | - $state_options = apply_filters( |
|
| 746 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options', |
|
| 747 | - $state_options, |
|
| 748 | - $this, |
|
| 749 | - $registration, |
|
| 750 | - $question, |
|
| 751 | - $answer |
|
| 752 | - ); |
|
| 753 | - return $state_options; |
|
| 754 | - } |
|
| 755 | - |
|
| 756 | - |
|
| 757 | - |
|
| 758 | - |
|
| 759 | - |
|
| 760 | - |
|
| 761 | - /********************************************************************************************************/ |
|
| 762 | - /**************************************** PROCESS REG STEP ****************************************/ |
|
| 763 | - /********************************************************************************************************/ |
|
| 764 | - /** |
|
| 765 | - * @return bool |
|
| 766 | - * @throws EE_Error |
|
| 767 | - * @throws InvalidArgumentException |
|
| 768 | - * @throws ReflectionException |
|
| 769 | - * @throws RuntimeException |
|
| 770 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 771 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 772 | - */ |
|
| 773 | - public function process_reg_step() |
|
| 774 | - { |
|
| 775 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 776 | - // grab validated data from form |
|
| 777 | - $valid_data = $this->checkout->current_step->valid_data(); |
|
| 778 | - // EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ ); |
|
| 779 | - // EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ ); |
|
| 780 | - // if we don't have any $valid_data then something went TERRIBLY WRONG !!! |
|
| 781 | - if (empty($valid_data)) { |
|
| 782 | - EE_Error::add_error( |
|
| 783 | - esc_html__('No valid question responses were received.', 'event_espresso'), |
|
| 784 | - __FILE__, |
|
| 785 | - __FUNCTION__, |
|
| 786 | - __LINE__ |
|
| 787 | - ); |
|
| 788 | - return false; |
|
| 789 | - } |
|
| 790 | - if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) { |
|
| 791 | - EE_Error::add_error( |
|
| 792 | - esc_html__( |
|
| 793 | - 'A valid transaction could not be initiated for processing your registrations.', |
|
| 794 | - 'event_espresso' |
|
| 795 | - ), |
|
| 796 | - __FILE__, |
|
| 797 | - __FUNCTION__, |
|
| 798 | - __LINE__ |
|
| 799 | - ); |
|
| 800 | - return false; |
|
| 801 | - } |
|
| 802 | - // get cached registrations |
|
| 803 | - $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params); |
|
| 804 | - // verify we got the goods |
|
| 805 | - if (empty($registrations)) { |
|
| 806 | - //combine the old translated string with a new one, in order to not break translations |
|
| 807 | - $error_message = esc_html__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' ) |
|
| 808 | - . sprintf( |
|
| 809 | - esc_html__('%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.', 'event_espresso'), |
|
| 810 | - '<a href="' . get_post_type_archive_link('espresso_events') . '" >', |
|
| 811 | - '</a>', |
|
| 812 | - '<br />' |
|
| 813 | - ); |
|
| 814 | - EE_Error::add_error( |
|
| 815 | - $error_message, |
|
| 816 | - __FILE__, |
|
| 817 | - __FUNCTION__, |
|
| 818 | - __LINE__ |
|
| 819 | - ); |
|
| 820 | - return false; |
|
| 821 | - } |
|
| 822 | - // extract attendee info from form data and save to model objects |
|
| 823 | - $registrations_processed = $this->_process_registrations($registrations, $valid_data); |
|
| 824 | - // if first pass thru SPCO, |
|
| 825 | - // then let's check processed registrations against the total number of tickets in the cart |
|
| 826 | - if ($registrations_processed === false) { |
|
| 827 | - // but return immediately if the previous step exited early due to errors |
|
| 828 | - return false; |
|
| 829 | - } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) { |
|
| 830 | - // generate a correctly translated string for all possible singular/plural combinations |
|
| 831 | - if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) { |
|
| 832 | - $error_msg = sprintf( |
|
| 833 | - esc_html__( |
|
| 834 | - 'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed', |
|
| 835 | - 'event_espresso' |
|
| 836 | - ), |
|
| 837 | - $this->checkout->total_ticket_count, |
|
| 838 | - $registrations_processed |
|
| 839 | - ); |
|
| 840 | - } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) { |
|
| 841 | - $error_msg = sprintf( |
|
| 842 | - esc_html__( |
|
| 843 | - 'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed', |
|
| 844 | - 'event_espresso' |
|
| 845 | - ), |
|
| 846 | - $this->checkout->total_ticket_count, |
|
| 847 | - $registrations_processed |
|
| 848 | - ); |
|
| 849 | - } else { |
|
| 850 | - $error_msg = sprintf( |
|
| 851 | - esc_html__( |
|
| 852 | - 'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed', |
|
| 853 | - 'event_espresso' |
|
| 854 | - ), |
|
| 855 | - $this->checkout->total_ticket_count, |
|
| 856 | - $registrations_processed |
|
| 857 | - ); |
|
| 858 | - } |
|
| 859 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 860 | - return false; |
|
| 861 | - } |
|
| 862 | - // mark this reg step as completed |
|
| 863 | - $this->set_completed(); |
|
| 864 | - $this->_set_success_message( |
|
| 865 | - esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso') |
|
| 866 | - ); |
|
| 867 | - //do action in case a plugin wants to do something with the data submitted in step 1. |
|
| 868 | - //passes EE_Single_Page_Checkout, and it's posted data |
|
| 869 | - do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data); |
|
| 870 | - return true; |
|
| 871 | - } |
|
| 872 | - |
|
| 873 | - |
|
| 874 | - /** |
|
| 875 | - * _process_registrations |
|
| 876 | - * |
|
| 877 | - * @param EE_Registration[] $registrations |
|
| 878 | - * @param array $valid_data |
|
| 879 | - * @return bool|int |
|
| 880 | - * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 881 | - * @throws EE_Error |
|
| 882 | - * @throws InvalidArgumentException |
|
| 883 | - * @throws ReflectionException |
|
| 884 | - * @throws RuntimeException |
|
| 885 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 886 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 887 | - */ |
|
| 888 | - private function _process_registrations($registrations = array(), $valid_data = array()) |
|
| 889 | - { |
|
| 890 | - // load resources and set some defaults |
|
| 891 | - EE_Registry::instance()->load_model('Attendee'); |
|
| 892 | - // holder for primary registrant attendee object |
|
| 893 | - $this->checkout->primary_attendee_obj = null; |
|
| 894 | - // array for tracking reg form data for the primary registrant |
|
| 895 | - $primary_registrant = array( |
|
| 896 | - 'line_item_id' => null, |
|
| 897 | - ); |
|
| 898 | - $copy_primary = false; |
|
| 899 | - // reg form sections that do not contain inputs |
|
| 900 | - $non_input_form_sections = array( |
|
| 901 | - 'primary_registrant', |
|
| 902 | - 'additional_attendee_reg_info', |
|
| 903 | - 'spco_copy_attendee_chk', |
|
| 904 | - ); |
|
| 905 | - // attendee counter |
|
| 906 | - $att_nmbr = 0; |
|
| 907 | - // grab the saved registrations from the transaction |
|
| 908 | - foreach ($registrations as $registration) { |
|
| 909 | - // verify EE_Registration object |
|
| 910 | - if (! $registration instanceof EE_Registration) { |
|
| 911 | - EE_Error::add_error( |
|
| 912 | - esc_html__( |
|
| 913 | - 'An invalid Registration object was discovered when attempting to process your registration information.', |
|
| 914 | - 'event_espresso' |
|
| 915 | - ), |
|
| 916 | - __FILE__, |
|
| 917 | - __FUNCTION__, |
|
| 918 | - __LINE__ |
|
| 919 | - ); |
|
| 920 | - return false; |
|
| 921 | - } |
|
| 922 | - /** @var string $reg_url_link */ |
|
| 923 | - $reg_url_link = $registration->reg_url_link(); |
|
| 924 | - // reg_url_link exists ? |
|
| 925 | - if (! empty($reg_url_link)) { |
|
| 926 | - // should this registration be processed during this visit ? |
|
| 927 | - if ($this->checkout->visit_allows_processing_of_this_registration($registration)) { |
|
| 928 | - // if NOT revisiting, then let's save the registration now, |
|
| 929 | - // so that we have a REG_ID to use when generating other objects |
|
| 930 | - if (! $this->checkout->revisit) { |
|
| 931 | - $registration->save(); |
|
| 932 | - } |
|
| 933 | - /** |
|
| 934 | - * This allows plugins to trigger a fail on processing of a |
|
| 935 | - * registration for any conditions they may have for it to pass. |
|
| 936 | - * |
|
| 937 | - * @var bool if true is returned by the plugin then the |
|
| 938 | - * registration processing is halted. |
|
| 939 | - */ |
|
| 940 | - if (apply_filters( |
|
| 941 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process', |
|
| 942 | - false, |
|
| 943 | - $att_nmbr, |
|
| 944 | - $registration, |
|
| 945 | - $registrations, |
|
| 946 | - $valid_data, |
|
| 947 | - $this |
|
| 948 | - )) { |
|
| 949 | - return false; |
|
| 950 | - } |
|
| 951 | - |
|
| 952 | - // Houston, we have a registration! |
|
| 953 | - $att_nmbr++; |
|
| 954 | - $this->_attendee_data[$reg_url_link] = array(); |
|
| 955 | - // grab any existing related answer objects |
|
| 956 | - $this->_registration_answers = $registration->answers(); |
|
| 957 | - // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ); |
|
| 958 | - if (isset($valid_data[$reg_url_link])) { |
|
| 959 | - // do we need to copy basic info from primary attendee ? |
|
| 960 | - $copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info']) |
|
| 961 | - && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0 |
|
| 962 | - ? true |
|
| 963 | - : false; |
|
| 964 | - // filter form input data for this registration |
|
| 965 | - $valid_data[$reg_url_link] = (array)apply_filters( |
|
| 966 | - 'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item', |
|
| 967 | - $valid_data[$reg_url_link] |
|
| 968 | - ); |
|
| 969 | - if (isset($valid_data['primary_attendee'])) { |
|
| 970 | - $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee']) |
|
| 971 | - ? $valid_data['primary_attendee'] |
|
| 972 | - : false; |
|
| 973 | - unset($valid_data['primary_attendee']); |
|
| 974 | - } |
|
| 975 | - // now loop through our array of valid post data && process attendee reg forms |
|
| 976 | - foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) { |
|
| 977 | - if (! in_array($form_section, $non_input_form_sections)) { |
|
| 978 | - foreach ($form_inputs as $form_input => $input_value) { |
|
| 979 | - // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ ); |
|
| 980 | - // check for critical inputs |
|
| 981 | - if (! $this->_verify_critical_attendee_details_are_set_and_validate_email( |
|
| 982 | - $form_input, |
|
| 983 | - $input_value |
|
| 984 | - ) |
|
| 985 | - ) { |
|
| 986 | - return false; |
|
| 987 | - } |
|
| 988 | - // store a bit of data about the primary attendee |
|
| 989 | - if ($att_nmbr === 1 |
|
| 990 | - && ! empty($input_value) |
|
| 991 | - && $reg_url_link === $primary_registrant['line_item_id'] |
|
| 992 | - ) { |
|
| 993 | - $primary_registrant[$form_input] = $input_value; |
|
| 994 | - } elseif ($copy_primary |
|
| 995 | - && $input_value === null |
|
| 996 | - && isset($primary_registrant[$form_input]) |
|
| 997 | - ) { |
|
| 998 | - $input_value = $primary_registrant[$form_input]; |
|
| 999 | - } |
|
| 1000 | - // now attempt to save the input data |
|
| 1001 | - if (! $this->_save_registration_form_input( |
|
| 1002 | - $registration, |
|
| 1003 | - $form_input, |
|
| 1004 | - $input_value |
|
| 1005 | - ) |
|
| 1006 | - ) { |
|
| 1007 | - EE_Error::add_error( |
|
| 1008 | - sprintf( |
|
| 1009 | - esc_html__( |
|
| 1010 | - 'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"', |
|
| 1011 | - 'event_espresso' |
|
| 1012 | - ), |
|
| 1013 | - $form_input, |
|
| 1014 | - $input_value |
|
| 1015 | - ), |
|
| 1016 | - __FILE__, |
|
| 1017 | - __FUNCTION__, |
|
| 1018 | - __LINE__ |
|
| 1019 | - ); |
|
| 1020 | - return false; |
|
| 1021 | - } |
|
| 1022 | - } |
|
| 1023 | - } |
|
| 1024 | - } // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs ) |
|
| 1025 | - } |
|
| 1026 | - //EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ ); |
|
| 1027 | - // this registration does not require additional attendee information ? |
|
| 1028 | - if ($copy_primary |
|
| 1029 | - && $att_nmbr > 1 |
|
| 1030 | - && $this->checkout->primary_attendee_obj instanceof EE_Attendee |
|
| 1031 | - ) { |
|
| 1032 | - // just copy the primary registrant |
|
| 1033 | - $attendee = $this->checkout->primary_attendee_obj; |
|
| 1034 | - } else { |
|
| 1035 | - // ensure critical details are set for additional attendees |
|
| 1036 | - $this->_attendee_data[$reg_url_link] = $att_nmbr > 1 |
|
| 1037 | - ? $this->_copy_critical_attendee_details_from_primary_registrant( |
|
| 1038 | - $this->_attendee_data[$reg_url_link] |
|
| 1039 | - ) |
|
| 1040 | - : $this->_attendee_data[$reg_url_link]; |
|
| 1041 | - // execute create attendee command (which may return an existing attendee) |
|
| 1042 | - $attendee = EE_Registry::instance()->BUS->execute( |
|
| 1043 | - new CreateAttendeeCommand( |
|
| 1044 | - $this->_attendee_data[$reg_url_link], |
|
| 1045 | - $registration |
|
| 1046 | - ) |
|
| 1047 | - ); |
|
| 1048 | - // who's #1 ? |
|
| 1049 | - if ($att_nmbr === 1) { |
|
| 1050 | - $this->checkout->primary_attendee_obj = $attendee; |
|
| 1051 | - } |
|
| 1052 | - } |
|
| 1053 | - // EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ ); |
|
| 1054 | - // add relation to registration, set attendee ID, and cache attendee |
|
| 1055 | - $this->_associate_attendee_with_registration($registration, $attendee); |
|
| 1056 | - // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ ); |
|
| 1057 | - if (! $registration->attendee() instanceof EE_Attendee) { |
|
| 1058 | - EE_Error::add_error( |
|
| 1059 | - sprintf( |
|
| 1060 | - esc_html__( |
|
| 1061 | - 'Registration %s has an invalid or missing Attendee object.', |
|
| 1062 | - 'event_espresso' |
|
| 1063 | - ), |
|
| 1064 | - $reg_url_link |
|
| 1065 | - ), |
|
| 1066 | - __FILE__, |
|
| 1067 | - __FUNCTION__, |
|
| 1068 | - __LINE__ |
|
| 1069 | - ); |
|
| 1070 | - return false; |
|
| 1071 | - } |
|
| 1072 | - /** @type EE_Registration_Processor $registration_processor */ |
|
| 1073 | - $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
| 1074 | - // at this point, we should have enough details about the registrant to consider the registration |
|
| 1075 | - // NOT incomplete |
|
| 1076 | - $registration_processor->toggle_incomplete_registration_status_to_default( |
|
| 1077 | - $registration, |
|
| 1078 | - false, |
|
| 1079 | - new Context( |
|
| 1080 | - 'spco_reg_step_attendee_information_process_registrations', |
|
| 1081 | - esc_html__( |
|
| 1082 | - 'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.', |
|
| 1083 | - 'event_espresso' |
|
| 1084 | - ) |
|
| 1085 | - ) |
|
| 1086 | - ); |
|
| 1087 | - // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to |
|
| 1088 | - // abandoned |
|
| 1089 | - $this->checkout->transaction->toggle_failed_transaction_status(); |
|
| 1090 | - // if we've gotten this far, then let's save what we have |
|
| 1091 | - $registration->save(); |
|
| 1092 | - // add relation between TXN and registration |
|
| 1093 | - $this->_associate_registration_with_transaction($registration); |
|
| 1094 | - } |
|
| 1095 | - } else { |
|
| 1096 | - EE_Error::add_error( |
|
| 1097 | - esc_html__( |
|
| 1098 | - 'An invalid or missing line item ID was encountered while attempting to process the registration form.', |
|
| 1099 | - 'event_espresso' |
|
| 1100 | - ), |
|
| 1101 | - __FILE__, |
|
| 1102 | - __FUNCTION__, |
|
| 1103 | - __LINE__ |
|
| 1104 | - ); |
|
| 1105 | - // remove malformed data |
|
| 1106 | - unset($valid_data[$reg_url_link]); |
|
| 1107 | - return false; |
|
| 1108 | - } |
|
| 1109 | - |
|
| 1110 | - } // end of foreach ( $this->checkout->transaction->registrations() as $registration ) |
|
| 1111 | - return $att_nmbr; |
|
| 1112 | - } |
|
| 1113 | - |
|
| 1114 | - |
|
| 1115 | - /** |
|
| 1116 | - * _save_registration_form_input |
|
| 1117 | - * |
|
| 1118 | - * @param EE_Registration $registration |
|
| 1119 | - * @param string $form_input |
|
| 1120 | - * @param string $input_value |
|
| 1121 | - * @return bool |
|
| 1122 | - * @throws EE_Error |
|
| 1123 | - * @throws InvalidArgumentException |
|
| 1124 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 1125 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 1126 | - */ |
|
| 1127 | - private function _save_registration_form_input( |
|
| 1128 | - EE_Registration $registration, |
|
| 1129 | - $form_input = '', |
|
| 1130 | - $input_value = '' |
|
| 1131 | - ) { |
|
| 1132 | - // \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 ); |
|
| 1133 | - // \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ ); |
|
| 1134 | - // \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ ); |
|
| 1135 | - // allow for plugins to hook in and do their own processing of the form input. |
|
| 1136 | - // For plugins to bypass normal processing here, they just need to return a boolean value. |
|
| 1137 | - if (apply_filters( |
|
| 1138 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input', |
|
| 1139 | - false, |
|
| 1140 | - $registration, |
|
| 1141 | - $form_input, |
|
| 1142 | - $input_value, |
|
| 1143 | - $this |
|
| 1144 | - )) { |
|
| 1145 | - return true; |
|
| 1146 | - } |
|
| 1147 | - /* |
|
| 390 | + $question_group_reg_form = new EE_Form_Section_Proper($form_args); |
|
| 391 | + return apply_filters( |
|
| 392 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___question_group_reg_form__question_group_reg_form', |
|
| 393 | + $question_group_reg_form, |
|
| 394 | + $registration, |
|
| 395 | + $question_group, |
|
| 396 | + $this |
|
| 397 | + ); |
|
| 398 | + } |
|
| 399 | + |
|
| 400 | + |
|
| 401 | + /** |
|
| 402 | + * @access public |
|
| 403 | + * @param EE_Question_Group $question_group |
|
| 404 | + * @return EE_Form_Section_HTML |
|
| 405 | + */ |
|
| 406 | + private function _question_group_header(EE_Question_Group $question_group) |
|
| 407 | + { |
|
| 408 | + $html = ''; |
|
| 409 | + // group_name |
|
| 410 | + if ($question_group->show_group_name() && $question_group->name() !== '') { |
|
| 411 | + if ($this->checkout->admin_request) { |
|
| 412 | + $html .= EEH_HTML::br(); |
|
| 413 | + $html .= EEH_HTML::h3( |
|
| 414 | + $question_group->name(), |
|
| 415 | + '', |
|
| 416 | + 'ee-reg-form-qstn-grp-title title', |
|
| 417 | + 'font-size: 1.3em; padding-left:0;' |
|
| 418 | + ); |
|
| 419 | + } else { |
|
| 420 | + $html .= EEH_HTML::h4( |
|
| 421 | + $question_group->name(), |
|
| 422 | + '', |
|
| 423 | + 'ee-reg-form-qstn-grp-title section-title' |
|
| 424 | + ); |
|
| 425 | + } |
|
| 426 | + } |
|
| 427 | + // group_desc |
|
| 428 | + if ($question_group->show_group_desc() && $question_group->desc() !== '') { |
|
| 429 | + $html .= EEH_HTML::p( |
|
| 430 | + $question_group->desc(), |
|
| 431 | + '', |
|
| 432 | + $this->checkout->admin_request |
|
| 433 | + ? 'ee-reg-form-qstn-grp-desc-pg' |
|
| 434 | + : 'ee-reg-form-qstn-grp-desc-pg small-text lt-grey-text' |
|
| 435 | + ); |
|
| 436 | + } |
|
| 437 | + return new EE_Form_Section_HTML($html); |
|
| 438 | + } |
|
| 439 | + |
|
| 440 | + |
|
| 441 | + /** |
|
| 442 | + * @access public |
|
| 443 | + * @return EE_Form_Section_Proper |
|
| 444 | + * @throws \EE_Error |
|
| 445 | + */ |
|
| 446 | + private function _copy_attendee_info_form() |
|
| 447 | + { |
|
| 448 | + // array of params to pass to parent constructor |
|
| 449 | + return new EE_Form_Section_Proper( |
|
| 450 | + array( |
|
| 451 | + 'subsections' => $this->_copy_attendee_info_inputs(), |
|
| 452 | + 'layout_strategy' => new EE_Template_Layout( |
|
| 453 | + array( |
|
| 454 | + 'layout_template_file' => SPCO_REG_STEPS_PATH |
|
| 455 | + . $this->_slug |
|
| 456 | + . DS |
|
| 457 | + . 'copy_attendee_info.template.php', |
|
| 458 | + 'begin_template_file' => null, |
|
| 459 | + 'input_template_file' => null, |
|
| 460 | + 'subsection_template_file' => null, |
|
| 461 | + 'end_template_file' => null, |
|
| 462 | + ) |
|
| 463 | + ), |
|
| 464 | + ) |
|
| 465 | + ); |
|
| 466 | + } |
|
| 467 | + |
|
| 468 | + |
|
| 469 | + /** |
|
| 470 | + * _auto_copy_attendee_info |
|
| 471 | + * |
|
| 472 | + * @access public |
|
| 473 | + * @return EE_Form_Section_HTML |
|
| 474 | + */ |
|
| 475 | + private function _auto_copy_attendee_info() |
|
| 476 | + { |
|
| 477 | + return new EE_Form_Section_HTML( |
|
| 478 | + EEH_Template::locate_template( |
|
| 479 | + SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php', |
|
| 480 | + apply_filters( |
|
| 481 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args', |
|
| 482 | + array() |
|
| 483 | + ), |
|
| 484 | + true, |
|
| 485 | + true |
|
| 486 | + ) |
|
| 487 | + ); |
|
| 488 | + } |
|
| 489 | + |
|
| 490 | + |
|
| 491 | + /** |
|
| 492 | + * _copy_attendee_info_inputs |
|
| 493 | + * |
|
| 494 | + * @access public |
|
| 495 | + * @return array |
|
| 496 | + * @throws \EE_Error |
|
| 497 | + */ |
|
| 498 | + private function _copy_attendee_info_inputs() |
|
| 499 | + { |
|
| 500 | + $copy_attendee_info_inputs = array(); |
|
| 501 | + $prev_ticket = null; |
|
| 502 | + // grab the saved registrations from the transaction |
|
| 503 | + $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params); |
|
| 504 | + foreach ($registrations as $registration) { |
|
| 505 | + // for all attendees other than the primary attendee |
|
| 506 | + if ($registration instanceof EE_Registration && ! $registration->is_primary_registrant()) { |
|
| 507 | + // if this is a new ticket OR if this is the very first additional attendee after the primary attendee |
|
| 508 | + if ($registration->ticket()->ID() !== $prev_ticket) { |
|
| 509 | + $item_name = $registration->ticket()->name(); |
|
| 510 | + $item_name .= $registration->ticket()->description() !== '' |
|
| 511 | + ? ' - ' . $registration->ticket()->description() |
|
| 512 | + : ''; |
|
| 513 | + $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] = |
|
| 514 | + new EE_Form_Section_HTML( |
|
| 515 | + '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>' |
|
| 516 | + ); |
|
| 517 | + $prev_ticket = $registration->ticket()->ID(); |
|
| 518 | + } |
|
| 519 | + |
|
| 520 | + $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] = |
|
| 521 | + new EE_Checkbox_Multi_Input( |
|
| 522 | + array( |
|
| 523 | + $registration->ID() => sprintf( |
|
| 524 | + esc_html__('Attendee #%s', 'event_espresso'), |
|
| 525 | + $registration->count() |
|
| 526 | + ), |
|
| 527 | + ), |
|
| 528 | + array( |
|
| 529 | + 'html_id' => 'spco-copy-attendee-chk-' . $registration->reg_url_link(), |
|
| 530 | + 'html_class' => 'spco-copy-attendee-chk ee-do-not-validate', |
|
| 531 | + 'display_html_label_text' => false, |
|
| 532 | + ) |
|
| 533 | + ); |
|
| 534 | + } |
|
| 535 | + } |
|
| 536 | + return $copy_attendee_info_inputs; |
|
| 537 | + } |
|
| 538 | + |
|
| 539 | + |
|
| 540 | + /** |
|
| 541 | + * _additional_primary_registrant_inputs |
|
| 542 | + * |
|
| 543 | + * @access public |
|
| 544 | + * @param EE_Registration $registration |
|
| 545 | + * @return EE_Form_Input_Base |
|
| 546 | + * @throws \EE_Error |
|
| 547 | + */ |
|
| 548 | + private function _additional_primary_registrant_inputs(EE_Registration $registration) |
|
| 549 | + { |
|
| 550 | + // generate hidden input |
|
| 551 | + return new EE_Hidden_Input( |
|
| 552 | + array( |
|
| 553 | + 'html_id' => 'primary_registrant', |
|
| 554 | + 'default' => $registration->reg_url_link(), |
|
| 555 | + ) |
|
| 556 | + ); |
|
| 557 | + } |
|
| 558 | + |
|
| 559 | + |
|
| 560 | + /** |
|
| 561 | + * @access public |
|
| 562 | + * @param EE_Registration $registration |
|
| 563 | + * @param EE_Question $question |
|
| 564 | + * @return EE_Form_Input_Base |
|
| 565 | + * @throws EE_Error |
|
| 566 | + * @throws InvalidArgumentException |
|
| 567 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 568 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 569 | + */ |
|
| 570 | + public function reg_form_question(EE_Registration $registration, EE_Question $question) |
|
| 571 | + { |
|
| 572 | + |
|
| 573 | + // if this question was for an attendee detail, then check for that answer |
|
| 574 | + $answer_value = EEM_Answer::instance()->get_attendee_property_answer_value( |
|
| 575 | + $registration, |
|
| 576 | + $question->system_ID() |
|
| 577 | + ); |
|
| 578 | + $answer = $answer_value === null |
|
| 579 | + ? EEM_Answer::instance()->get_one( |
|
| 580 | + array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID())) |
|
| 581 | + ) |
|
| 582 | + : null; |
|
| 583 | + // if NOT returning to edit an existing registration |
|
| 584 | + // OR if this question is for an attendee property |
|
| 585 | + // OR we still don't have an EE_Answer object |
|
| 586 | + if ($answer_value || ! $answer instanceof EE_Answer || ! $registration->reg_url_link()) { |
|
| 587 | + // create an EE_Answer object for storing everything in |
|
| 588 | + $answer = EE_Answer::new_instance(array( |
|
| 589 | + 'QST_ID' => $question->ID(), |
|
| 590 | + 'REG_ID' => $registration->ID(), |
|
| 591 | + )); |
|
| 592 | + } |
|
| 593 | + // verify instance |
|
| 594 | + if ($answer instanceof EE_Answer) { |
|
| 595 | + if (! empty($answer_value)) { |
|
| 596 | + $answer->set('ANS_value', $answer_value); |
|
| 597 | + } |
|
| 598 | + $answer->cache('Question', $question); |
|
| 599 | + //remember system ID had a bug where sometimes it could be null |
|
| 600 | + $answer_cache_id = $question->is_system_question() |
|
| 601 | + ? $question->system_ID() . '-' . $registration->reg_url_link() |
|
| 602 | + : $question->ID() . '-' . $registration->reg_url_link(); |
|
| 603 | + $registration->cache('Answer', $answer, $answer_cache_id); |
|
| 604 | + } |
|
| 605 | + return $this->_generate_question_input($registration, $question, $answer); |
|
| 606 | + } |
|
| 607 | + |
|
| 608 | + |
|
| 609 | + /** |
|
| 610 | + * @param EE_Registration $registration |
|
| 611 | + * @param EE_Question $question |
|
| 612 | + * @param mixed EE_Answer|NULL $answer |
|
| 613 | + * @return EE_Form_Input_Base |
|
| 614 | + * @throws \EE_Error |
|
| 615 | + */ |
|
| 616 | + private function _generate_question_input(EE_Registration $registration, EE_Question $question, $answer) |
|
| 617 | + { |
|
| 618 | + $identifier = $question->is_system_question() |
|
| 619 | + ? $question->system_ID() |
|
| 620 | + : $question->ID(); |
|
| 621 | + $this->_required_questions[$identifier] = $question->required() ? true : false; |
|
| 622 | + add_filter( |
|
| 623 | + 'FHEE__EE_Question__generate_form_input__country_options', |
|
| 624 | + array($this, 'use_cached_countries_for_form_input'), |
|
| 625 | + 10, |
|
| 626 | + 4 |
|
| 627 | + ); |
|
| 628 | + add_filter( |
|
| 629 | + 'FHEE__EE_Question__generate_form_input__state_options', |
|
| 630 | + array($this, 'use_cached_states_for_form_input'), |
|
| 631 | + 10, |
|
| 632 | + 4 |
|
| 633 | + ); |
|
| 634 | + $input_constructor_args = array( |
|
| 635 | + 'html_name' => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']', |
|
| 636 | + 'html_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier, |
|
| 637 | + 'html_class' => 'ee-reg-qstn ee-reg-qstn-' . $identifier, |
|
| 638 | + 'html_label_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier, |
|
| 639 | + 'html_label_class' => 'ee-reg-qstn', |
|
| 640 | + ); |
|
| 641 | + $input_constructor_args['html_label_id'] .= '-lbl'; |
|
| 642 | + if ($answer instanceof EE_Answer && $answer->ID()) { |
|
| 643 | + $input_constructor_args['html_name'] .= '[' . $answer->ID() . ']'; |
|
| 644 | + $input_constructor_args['html_id'] .= '-' . $answer->ID(); |
|
| 645 | + $input_constructor_args['html_label_id'] .= '-' . $answer->ID(); |
|
| 646 | + } |
|
| 647 | + $form_input = $question->generate_form_input( |
|
| 648 | + $registration, |
|
| 649 | + $answer, |
|
| 650 | + $input_constructor_args |
|
| 651 | + ); |
|
| 652 | + remove_filter( |
|
| 653 | + 'FHEE__EE_Question__generate_form_input__country_options', |
|
| 654 | + array($this, 'use_cached_countries_for_form_input') |
|
| 655 | + ); |
|
| 656 | + remove_filter( |
|
| 657 | + 'FHEE__EE_Question__generate_form_input__state_options', |
|
| 658 | + array($this, 'use_cached_states_for_form_input') |
|
| 659 | + ); |
|
| 660 | + return $form_input; |
|
| 661 | + } |
|
| 662 | + |
|
| 663 | + |
|
| 664 | + /** |
|
| 665 | + * Gets the list of countries for the form input |
|
| 666 | + * |
|
| 667 | + * @param array|null $countries_list |
|
| 668 | + * @param \EE_Question $question |
|
| 669 | + * @param \EE_Registration $registration |
|
| 670 | + * @param \EE_Answer $answer |
|
| 671 | + * @return array 2d keys are country IDs, values are their names |
|
| 672 | + * @throws EE_Error |
|
| 673 | + * @throws InvalidArgumentException |
|
| 674 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 675 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 676 | + */ |
|
| 677 | + public function use_cached_countries_for_form_input( |
|
| 678 | + $countries_list, |
|
| 679 | + \EE_Question $question = null, |
|
| 680 | + \EE_Registration $registration = null, |
|
| 681 | + \EE_Answer $answer = null |
|
| 682 | + ) { |
|
| 683 | + $country_options = array('' => ''); |
|
| 684 | + // get possibly cached list of countries |
|
| 685 | + $countries = $this->checkout->action === 'process_reg_step' |
|
| 686 | + ? EEM_Country::instance()->get_all_countries() |
|
| 687 | + : EEM_Country::instance()->get_all_active_countries(); |
|
| 688 | + if (! empty($countries)) { |
|
| 689 | + foreach ($countries as $country) { |
|
| 690 | + if ($country instanceof EE_Country) { |
|
| 691 | + $country_options[$country->ID()] = $country->name(); |
|
| 692 | + } |
|
| 693 | + } |
|
| 694 | + } |
|
| 695 | + if ($question instanceof EE_Question |
|
| 696 | + && $registration instanceof EE_Registration) { |
|
| 697 | + $answer = EEM_Answer::instance()->get_one( |
|
| 698 | + array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID())) |
|
| 699 | + ); |
|
| 700 | + } else { |
|
| 701 | + $answer = EE_Answer::new_instance(); |
|
| 702 | + } |
|
| 703 | + $country_options = apply_filters( |
|
| 704 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__country_options', |
|
| 705 | + $country_options, |
|
| 706 | + $this, |
|
| 707 | + $registration, |
|
| 708 | + $question, |
|
| 709 | + $answer |
|
| 710 | + ); |
|
| 711 | + return $country_options; |
|
| 712 | + } |
|
| 713 | + |
|
| 714 | + |
|
| 715 | + /** |
|
| 716 | + * Gets the list of states for the form input |
|
| 717 | + * |
|
| 718 | + * @param array|null $states_list |
|
| 719 | + * @param \EE_Question $question |
|
| 720 | + * @param \EE_Registration $registration |
|
| 721 | + * @param \EE_Answer $answer |
|
| 722 | + * @return array 2d keys are state IDs, values are their names |
|
| 723 | + * @throws EE_Error |
|
| 724 | + * @throws InvalidArgumentException |
|
| 725 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 726 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 727 | + */ |
|
| 728 | + public function use_cached_states_for_form_input( |
|
| 729 | + $states_list, |
|
| 730 | + \EE_Question $question = null, |
|
| 731 | + \EE_Registration $registration = null, |
|
| 732 | + \EE_Answer $answer = null |
|
| 733 | + ) { |
|
| 734 | + $state_options = array('' => array('' => '')); |
|
| 735 | + $states = $this->checkout->action === 'process_reg_step' |
|
| 736 | + ? EEM_State::instance()->get_all_states() |
|
| 737 | + : EEM_State::instance()->get_all_active_states(); |
|
| 738 | + if (! empty($states)) { |
|
| 739 | + foreach ($states as $state) { |
|
| 740 | + if ($state instanceof EE_State) { |
|
| 741 | + $state_options[$state->country()->name()][$state->ID()] = $state->name(); |
|
| 742 | + } |
|
| 743 | + } |
|
| 744 | + } |
|
| 745 | + $state_options = apply_filters( |
|
| 746 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___generate_question_input__state_options', |
|
| 747 | + $state_options, |
|
| 748 | + $this, |
|
| 749 | + $registration, |
|
| 750 | + $question, |
|
| 751 | + $answer |
|
| 752 | + ); |
|
| 753 | + return $state_options; |
|
| 754 | + } |
|
| 755 | + |
|
| 756 | + |
|
| 757 | + |
|
| 758 | + |
|
| 759 | + |
|
| 760 | + |
|
| 761 | + /********************************************************************************************************/ |
|
| 762 | + /**************************************** PROCESS REG STEP ****************************************/ |
|
| 763 | + /********************************************************************************************************/ |
|
| 764 | + /** |
|
| 765 | + * @return bool |
|
| 766 | + * @throws EE_Error |
|
| 767 | + * @throws InvalidArgumentException |
|
| 768 | + * @throws ReflectionException |
|
| 769 | + * @throws RuntimeException |
|
| 770 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 771 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 772 | + */ |
|
| 773 | + public function process_reg_step() |
|
| 774 | + { |
|
| 775 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 776 | + // grab validated data from form |
|
| 777 | + $valid_data = $this->checkout->current_step->valid_data(); |
|
| 778 | + // EEH_Debug_Tools::printr( $_REQUEST, '$_REQUEST', __FILE__, __LINE__ ); |
|
| 779 | + // EEH_Debug_Tools::printr( $valid_data, '$valid_data', __FILE__, __LINE__ ); |
|
| 780 | + // if we don't have any $valid_data then something went TERRIBLY WRONG !!! |
|
| 781 | + if (empty($valid_data)) { |
|
| 782 | + EE_Error::add_error( |
|
| 783 | + esc_html__('No valid question responses were received.', 'event_espresso'), |
|
| 784 | + __FILE__, |
|
| 785 | + __FUNCTION__, |
|
| 786 | + __LINE__ |
|
| 787 | + ); |
|
| 788 | + return false; |
|
| 789 | + } |
|
| 790 | + if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) { |
|
| 791 | + EE_Error::add_error( |
|
| 792 | + esc_html__( |
|
| 793 | + 'A valid transaction could not be initiated for processing your registrations.', |
|
| 794 | + 'event_espresso' |
|
| 795 | + ), |
|
| 796 | + __FILE__, |
|
| 797 | + __FUNCTION__, |
|
| 798 | + __LINE__ |
|
| 799 | + ); |
|
| 800 | + return false; |
|
| 801 | + } |
|
| 802 | + // get cached registrations |
|
| 803 | + $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params); |
|
| 804 | + // verify we got the goods |
|
| 805 | + if (empty($registrations)) { |
|
| 806 | + //combine the old translated string with a new one, in order to not break translations |
|
| 807 | + $error_message = esc_html__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' ) |
|
| 808 | + . sprintf( |
|
| 809 | + esc_html__('%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.', 'event_espresso'), |
|
| 810 | + '<a href="' . get_post_type_archive_link('espresso_events') . '" >', |
|
| 811 | + '</a>', |
|
| 812 | + '<br />' |
|
| 813 | + ); |
|
| 814 | + EE_Error::add_error( |
|
| 815 | + $error_message, |
|
| 816 | + __FILE__, |
|
| 817 | + __FUNCTION__, |
|
| 818 | + __LINE__ |
|
| 819 | + ); |
|
| 820 | + return false; |
|
| 821 | + } |
|
| 822 | + // extract attendee info from form data and save to model objects |
|
| 823 | + $registrations_processed = $this->_process_registrations($registrations, $valid_data); |
|
| 824 | + // if first pass thru SPCO, |
|
| 825 | + // then let's check processed registrations against the total number of tickets in the cart |
|
| 826 | + if ($registrations_processed === false) { |
|
| 827 | + // but return immediately if the previous step exited early due to errors |
|
| 828 | + return false; |
|
| 829 | + } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) { |
|
| 830 | + // generate a correctly translated string for all possible singular/plural combinations |
|
| 831 | + if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) { |
|
| 832 | + $error_msg = sprintf( |
|
| 833 | + esc_html__( |
|
| 834 | + 'There was %1$d ticket in the Event Queue, but %2$ds registrations were processed', |
|
| 835 | + 'event_espresso' |
|
| 836 | + ), |
|
| 837 | + $this->checkout->total_ticket_count, |
|
| 838 | + $registrations_processed |
|
| 839 | + ); |
|
| 840 | + } elseif ($this->checkout->total_ticket_count !== 1 && $registrations_processed === 1) { |
|
| 841 | + $error_msg = sprintf( |
|
| 842 | + esc_html__( |
|
| 843 | + 'There was a total of %1$d tickets in the Event Queue, but only %2$ds registration was processed', |
|
| 844 | + 'event_espresso' |
|
| 845 | + ), |
|
| 846 | + $this->checkout->total_ticket_count, |
|
| 847 | + $registrations_processed |
|
| 848 | + ); |
|
| 849 | + } else { |
|
| 850 | + $error_msg = sprintf( |
|
| 851 | + esc_html__( |
|
| 852 | + 'There was a total of %1$d tickets in the Event Queue, but %2$ds registrations were processed', |
|
| 853 | + 'event_espresso' |
|
| 854 | + ), |
|
| 855 | + $this->checkout->total_ticket_count, |
|
| 856 | + $registrations_processed |
|
| 857 | + ); |
|
| 858 | + } |
|
| 859 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 860 | + return false; |
|
| 861 | + } |
|
| 862 | + // mark this reg step as completed |
|
| 863 | + $this->set_completed(); |
|
| 864 | + $this->_set_success_message( |
|
| 865 | + esc_html__('The Attendee Information Step has been successfully completed.', 'event_espresso') |
|
| 866 | + ); |
|
| 867 | + //do action in case a plugin wants to do something with the data submitted in step 1. |
|
| 868 | + //passes EE_Single_Page_Checkout, and it's posted data |
|
| 869 | + do_action('AHEE__EE_Single_Page_Checkout__process_attendee_information__end', $this, $valid_data); |
|
| 870 | + return true; |
|
| 871 | + } |
|
| 872 | + |
|
| 873 | + |
|
| 874 | + /** |
|
| 875 | + * _process_registrations |
|
| 876 | + * |
|
| 877 | + * @param EE_Registration[] $registrations |
|
| 878 | + * @param array $valid_data |
|
| 879 | + * @return bool|int |
|
| 880 | + * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 881 | + * @throws EE_Error |
|
| 882 | + * @throws InvalidArgumentException |
|
| 883 | + * @throws ReflectionException |
|
| 884 | + * @throws RuntimeException |
|
| 885 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 886 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 887 | + */ |
|
| 888 | + private function _process_registrations($registrations = array(), $valid_data = array()) |
|
| 889 | + { |
|
| 890 | + // load resources and set some defaults |
|
| 891 | + EE_Registry::instance()->load_model('Attendee'); |
|
| 892 | + // holder for primary registrant attendee object |
|
| 893 | + $this->checkout->primary_attendee_obj = null; |
|
| 894 | + // array for tracking reg form data for the primary registrant |
|
| 895 | + $primary_registrant = array( |
|
| 896 | + 'line_item_id' => null, |
|
| 897 | + ); |
|
| 898 | + $copy_primary = false; |
|
| 899 | + // reg form sections that do not contain inputs |
|
| 900 | + $non_input_form_sections = array( |
|
| 901 | + 'primary_registrant', |
|
| 902 | + 'additional_attendee_reg_info', |
|
| 903 | + 'spco_copy_attendee_chk', |
|
| 904 | + ); |
|
| 905 | + // attendee counter |
|
| 906 | + $att_nmbr = 0; |
|
| 907 | + // grab the saved registrations from the transaction |
|
| 908 | + foreach ($registrations as $registration) { |
|
| 909 | + // verify EE_Registration object |
|
| 910 | + if (! $registration instanceof EE_Registration) { |
|
| 911 | + EE_Error::add_error( |
|
| 912 | + esc_html__( |
|
| 913 | + 'An invalid Registration object was discovered when attempting to process your registration information.', |
|
| 914 | + 'event_espresso' |
|
| 915 | + ), |
|
| 916 | + __FILE__, |
|
| 917 | + __FUNCTION__, |
|
| 918 | + __LINE__ |
|
| 919 | + ); |
|
| 920 | + return false; |
|
| 921 | + } |
|
| 922 | + /** @var string $reg_url_link */ |
|
| 923 | + $reg_url_link = $registration->reg_url_link(); |
|
| 924 | + // reg_url_link exists ? |
|
| 925 | + if (! empty($reg_url_link)) { |
|
| 926 | + // should this registration be processed during this visit ? |
|
| 927 | + if ($this->checkout->visit_allows_processing_of_this_registration($registration)) { |
|
| 928 | + // if NOT revisiting, then let's save the registration now, |
|
| 929 | + // so that we have a REG_ID to use when generating other objects |
|
| 930 | + if (! $this->checkout->revisit) { |
|
| 931 | + $registration->save(); |
|
| 932 | + } |
|
| 933 | + /** |
|
| 934 | + * This allows plugins to trigger a fail on processing of a |
|
| 935 | + * registration for any conditions they may have for it to pass. |
|
| 936 | + * |
|
| 937 | + * @var bool if true is returned by the plugin then the |
|
| 938 | + * registration processing is halted. |
|
| 939 | + */ |
|
| 940 | + if (apply_filters( |
|
| 941 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___process_registrations__pre_registration_process', |
|
| 942 | + false, |
|
| 943 | + $att_nmbr, |
|
| 944 | + $registration, |
|
| 945 | + $registrations, |
|
| 946 | + $valid_data, |
|
| 947 | + $this |
|
| 948 | + )) { |
|
| 949 | + return false; |
|
| 950 | + } |
|
| 951 | + |
|
| 952 | + // Houston, we have a registration! |
|
| 953 | + $att_nmbr++; |
|
| 954 | + $this->_attendee_data[$reg_url_link] = array(); |
|
| 955 | + // grab any existing related answer objects |
|
| 956 | + $this->_registration_answers = $registration->answers(); |
|
| 957 | + // unset( $valid_data[ $reg_url_link ]['additional_attendee_reg_info'] ); |
|
| 958 | + if (isset($valid_data[$reg_url_link])) { |
|
| 959 | + // do we need to copy basic info from primary attendee ? |
|
| 960 | + $copy_primary = isset($valid_data[$reg_url_link]['additional_attendee_reg_info']) |
|
| 961 | + && absint($valid_data[$reg_url_link]['additional_attendee_reg_info']) === 0 |
|
| 962 | + ? true |
|
| 963 | + : false; |
|
| 964 | + // filter form input data for this registration |
|
| 965 | + $valid_data[$reg_url_link] = (array)apply_filters( |
|
| 966 | + 'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item', |
|
| 967 | + $valid_data[$reg_url_link] |
|
| 968 | + ); |
|
| 969 | + if (isset($valid_data['primary_attendee'])) { |
|
| 970 | + $primary_registrant['line_item_id'] = ! empty($valid_data['primary_attendee']) |
|
| 971 | + ? $valid_data['primary_attendee'] |
|
| 972 | + : false; |
|
| 973 | + unset($valid_data['primary_attendee']); |
|
| 974 | + } |
|
| 975 | + // now loop through our array of valid post data && process attendee reg forms |
|
| 976 | + foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) { |
|
| 977 | + if (! in_array($form_section, $non_input_form_sections)) { |
|
| 978 | + foreach ($form_inputs as $form_input => $input_value) { |
|
| 979 | + // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ ); |
|
| 980 | + // check for critical inputs |
|
| 981 | + if (! $this->_verify_critical_attendee_details_are_set_and_validate_email( |
|
| 982 | + $form_input, |
|
| 983 | + $input_value |
|
| 984 | + ) |
|
| 985 | + ) { |
|
| 986 | + return false; |
|
| 987 | + } |
|
| 988 | + // store a bit of data about the primary attendee |
|
| 989 | + if ($att_nmbr === 1 |
|
| 990 | + && ! empty($input_value) |
|
| 991 | + && $reg_url_link === $primary_registrant['line_item_id'] |
|
| 992 | + ) { |
|
| 993 | + $primary_registrant[$form_input] = $input_value; |
|
| 994 | + } elseif ($copy_primary |
|
| 995 | + && $input_value === null |
|
| 996 | + && isset($primary_registrant[$form_input]) |
|
| 997 | + ) { |
|
| 998 | + $input_value = $primary_registrant[$form_input]; |
|
| 999 | + } |
|
| 1000 | + // now attempt to save the input data |
|
| 1001 | + if (! $this->_save_registration_form_input( |
|
| 1002 | + $registration, |
|
| 1003 | + $form_input, |
|
| 1004 | + $input_value |
|
| 1005 | + ) |
|
| 1006 | + ) { |
|
| 1007 | + EE_Error::add_error( |
|
| 1008 | + sprintf( |
|
| 1009 | + esc_html__( |
|
| 1010 | + 'Unable to save registration form data for the form input: "%1$s" with the submitted value: "%2$s"', |
|
| 1011 | + 'event_espresso' |
|
| 1012 | + ), |
|
| 1013 | + $form_input, |
|
| 1014 | + $input_value |
|
| 1015 | + ), |
|
| 1016 | + __FILE__, |
|
| 1017 | + __FUNCTION__, |
|
| 1018 | + __LINE__ |
|
| 1019 | + ); |
|
| 1020 | + return false; |
|
| 1021 | + } |
|
| 1022 | + } |
|
| 1023 | + } |
|
| 1024 | + } // end of foreach ( $valid_data[ $reg_url_link ] as $form_section => $form_inputs ) |
|
| 1025 | + } |
|
| 1026 | + //EEH_Debug_Tools::printr( $this->_attendee_data, '$this->_attendee_data', __FILE__, __LINE__ ); |
|
| 1027 | + // this registration does not require additional attendee information ? |
|
| 1028 | + if ($copy_primary |
|
| 1029 | + && $att_nmbr > 1 |
|
| 1030 | + && $this->checkout->primary_attendee_obj instanceof EE_Attendee |
|
| 1031 | + ) { |
|
| 1032 | + // just copy the primary registrant |
|
| 1033 | + $attendee = $this->checkout->primary_attendee_obj; |
|
| 1034 | + } else { |
|
| 1035 | + // ensure critical details are set for additional attendees |
|
| 1036 | + $this->_attendee_data[$reg_url_link] = $att_nmbr > 1 |
|
| 1037 | + ? $this->_copy_critical_attendee_details_from_primary_registrant( |
|
| 1038 | + $this->_attendee_data[$reg_url_link] |
|
| 1039 | + ) |
|
| 1040 | + : $this->_attendee_data[$reg_url_link]; |
|
| 1041 | + // execute create attendee command (which may return an existing attendee) |
|
| 1042 | + $attendee = EE_Registry::instance()->BUS->execute( |
|
| 1043 | + new CreateAttendeeCommand( |
|
| 1044 | + $this->_attendee_data[$reg_url_link], |
|
| 1045 | + $registration |
|
| 1046 | + ) |
|
| 1047 | + ); |
|
| 1048 | + // who's #1 ? |
|
| 1049 | + if ($att_nmbr === 1) { |
|
| 1050 | + $this->checkout->primary_attendee_obj = $attendee; |
|
| 1051 | + } |
|
| 1052 | + } |
|
| 1053 | + // EEH_Debug_Tools::printr( $attendee, '$attendee', __FILE__, __LINE__ ); |
|
| 1054 | + // add relation to registration, set attendee ID, and cache attendee |
|
| 1055 | + $this->_associate_attendee_with_registration($registration, $attendee); |
|
| 1056 | + // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ ); |
|
| 1057 | + if (! $registration->attendee() instanceof EE_Attendee) { |
|
| 1058 | + EE_Error::add_error( |
|
| 1059 | + sprintf( |
|
| 1060 | + esc_html__( |
|
| 1061 | + 'Registration %s has an invalid or missing Attendee object.', |
|
| 1062 | + 'event_espresso' |
|
| 1063 | + ), |
|
| 1064 | + $reg_url_link |
|
| 1065 | + ), |
|
| 1066 | + __FILE__, |
|
| 1067 | + __FUNCTION__, |
|
| 1068 | + __LINE__ |
|
| 1069 | + ); |
|
| 1070 | + return false; |
|
| 1071 | + } |
|
| 1072 | + /** @type EE_Registration_Processor $registration_processor */ |
|
| 1073 | + $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
| 1074 | + // at this point, we should have enough details about the registrant to consider the registration |
|
| 1075 | + // NOT incomplete |
|
| 1076 | + $registration_processor->toggle_incomplete_registration_status_to_default( |
|
| 1077 | + $registration, |
|
| 1078 | + false, |
|
| 1079 | + new Context( |
|
| 1080 | + 'spco_reg_step_attendee_information_process_registrations', |
|
| 1081 | + esc_html__( |
|
| 1082 | + 'Finished populating registration with details from the registration form after submitting the Attendee Information Reg Step.', |
|
| 1083 | + 'event_espresso' |
|
| 1084 | + ) |
|
| 1085 | + ) |
|
| 1086 | + ); |
|
| 1087 | + // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to |
|
| 1088 | + // abandoned |
|
| 1089 | + $this->checkout->transaction->toggle_failed_transaction_status(); |
|
| 1090 | + // if we've gotten this far, then let's save what we have |
|
| 1091 | + $registration->save(); |
|
| 1092 | + // add relation between TXN and registration |
|
| 1093 | + $this->_associate_registration_with_transaction($registration); |
|
| 1094 | + } |
|
| 1095 | + } else { |
|
| 1096 | + EE_Error::add_error( |
|
| 1097 | + esc_html__( |
|
| 1098 | + 'An invalid or missing line item ID was encountered while attempting to process the registration form.', |
|
| 1099 | + 'event_espresso' |
|
| 1100 | + ), |
|
| 1101 | + __FILE__, |
|
| 1102 | + __FUNCTION__, |
|
| 1103 | + __LINE__ |
|
| 1104 | + ); |
|
| 1105 | + // remove malformed data |
|
| 1106 | + unset($valid_data[$reg_url_link]); |
|
| 1107 | + return false; |
|
| 1108 | + } |
|
| 1109 | + |
|
| 1110 | + } // end of foreach ( $this->checkout->transaction->registrations() as $registration ) |
|
| 1111 | + return $att_nmbr; |
|
| 1112 | + } |
|
| 1113 | + |
|
| 1114 | + |
|
| 1115 | + /** |
|
| 1116 | + * _save_registration_form_input |
|
| 1117 | + * |
|
| 1118 | + * @param EE_Registration $registration |
|
| 1119 | + * @param string $form_input |
|
| 1120 | + * @param string $input_value |
|
| 1121 | + * @return bool |
|
| 1122 | + * @throws EE_Error |
|
| 1123 | + * @throws InvalidArgumentException |
|
| 1124 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 1125 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 1126 | + */ |
|
| 1127 | + private function _save_registration_form_input( |
|
| 1128 | + EE_Registration $registration, |
|
| 1129 | + $form_input = '', |
|
| 1130 | + $input_value = '' |
|
| 1131 | + ) { |
|
| 1132 | + // \EEH_Debug_Tools::printr( __FUNCTION__, __CLASS__, __FILE__, __LINE__, 2 ); |
|
| 1133 | + // \EEH_Debug_Tools::printr( $form_input, '$form_input', __FILE__, __LINE__ ); |
|
| 1134 | + // \EEH_Debug_Tools::printr( $input_value, '$input_value', __FILE__, __LINE__ ); |
|
| 1135 | + // allow for plugins to hook in and do their own processing of the form input. |
|
| 1136 | + // For plugins to bypass normal processing here, they just need to return a boolean value. |
|
| 1137 | + if (apply_filters( |
|
| 1138 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information___save_registration_form_input', |
|
| 1139 | + false, |
|
| 1140 | + $registration, |
|
| 1141 | + $form_input, |
|
| 1142 | + $input_value, |
|
| 1143 | + $this |
|
| 1144 | + )) { |
|
| 1145 | + return true; |
|
| 1146 | + } |
|
| 1147 | + /* |
|
| 1148 | 1148 | * $answer_cache_id is the key used to find the EE_Answer we want |
| 1149 | 1149 | * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477 |
| 1150 | 1150 | */ |
| 1151 | - $answer_cache_id = $this->checkout->reg_url_link |
|
| 1152 | - ? $form_input . '-' . $registration->reg_url_link() |
|
| 1153 | - : $form_input; |
|
| 1154 | - $answer_is_obj = isset($this->_registration_answers[$answer_cache_id]) |
|
| 1155 | - && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer |
|
| 1156 | - ? true |
|
| 1157 | - : false; |
|
| 1158 | - //rename form_inputs if they are EE_Attendee properties |
|
| 1159 | - switch ((string) $form_input) { |
|
| 1160 | - case 'state': |
|
| 1161 | - case 'STA_ID': |
|
| 1162 | - $attendee_property = true; |
|
| 1163 | - $form_input = 'STA_ID'; |
|
| 1164 | - break; |
|
| 1165 | - |
|
| 1166 | - case 'country': |
|
| 1167 | - case 'CNT_ISO': |
|
| 1168 | - $attendee_property = true; |
|
| 1169 | - $form_input = 'CNT_ISO'; |
|
| 1170 | - break; |
|
| 1171 | - |
|
| 1172 | - default: |
|
| 1173 | - $ATT_input = 'ATT_' . $form_input; |
|
| 1174 | - //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ ); |
|
| 1175 | - $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false; |
|
| 1176 | - $form_input = $attendee_property ? 'ATT_' . $form_input : $form_input; |
|
| 1177 | - } |
|
| 1178 | - // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ ); |
|
| 1179 | - // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ ); |
|
| 1180 | - // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ ); |
|
| 1181 | - // if this form input has a corresponding attendee property |
|
| 1182 | - if ($attendee_property) { |
|
| 1183 | - $this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value; |
|
| 1184 | - if ($answer_is_obj) { |
|
| 1185 | - // and delete the corresponding answer since we won't be storing this data in that object |
|
| 1186 | - $registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer'); |
|
| 1187 | - $this->_registration_answers[$answer_cache_id]->delete_permanently(); |
|
| 1188 | - } |
|
| 1189 | - return true; |
|
| 1190 | - } elseif ($answer_is_obj) { |
|
| 1191 | - // save this data to the answer object |
|
| 1192 | - $this->_registration_answers[$answer_cache_id]->set_value($input_value); |
|
| 1193 | - $result = $this->_registration_answers[$answer_cache_id]->save(); |
|
| 1194 | - return $result !== false ? true : false; |
|
| 1195 | - } else { |
|
| 1196 | - foreach ($this->_registration_answers as $answer) { |
|
| 1197 | - if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) { |
|
| 1198 | - $answer->set_value($input_value); |
|
| 1199 | - $result = $answer->save(); |
|
| 1200 | - return $result !== false ? true : false; |
|
| 1201 | - } |
|
| 1202 | - } |
|
| 1203 | - } |
|
| 1204 | - return false; |
|
| 1205 | - } |
|
| 1206 | - |
|
| 1207 | - |
|
| 1208 | - /** |
|
| 1209 | - * _verify_critical_attendee_details_are_set |
|
| 1210 | - * |
|
| 1211 | - * @param string $form_input |
|
| 1212 | - * @param string $input_value |
|
| 1213 | - * @return boolean |
|
| 1214 | - */ |
|
| 1215 | - private function _verify_critical_attendee_details_are_set_and_validate_email( |
|
| 1216 | - $form_input = '', |
|
| 1217 | - $input_value = '' |
|
| 1218 | - ) { |
|
| 1219 | - if (empty($input_value)) { |
|
| 1220 | - // if the form input isn't marked as being required, then just return |
|
| 1221 | - if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) { |
|
| 1222 | - return true; |
|
| 1223 | - } |
|
| 1224 | - switch ($form_input) { |
|
| 1225 | - case 'fname': |
|
| 1226 | - EE_Error::add_error( |
|
| 1227 | - esc_html__('First Name is a required value.', 'event_espresso'), |
|
| 1228 | - __FILE__, |
|
| 1229 | - __FUNCTION__, |
|
| 1230 | - __LINE__ |
|
| 1231 | - ); |
|
| 1232 | - return false; |
|
| 1233 | - break; |
|
| 1234 | - case 'lname': |
|
| 1235 | - EE_Error::add_error( |
|
| 1236 | - esc_html__('Last Name is a required value.', 'event_espresso'), |
|
| 1237 | - __FILE__, |
|
| 1238 | - __FUNCTION__, |
|
| 1239 | - __LINE__ |
|
| 1240 | - ); |
|
| 1241 | - return false; |
|
| 1242 | - break; |
|
| 1243 | - case 'email': |
|
| 1244 | - EE_Error::add_error( |
|
| 1245 | - esc_html__('Please enter a valid email address.', 'event_espresso'), |
|
| 1246 | - __FILE__, |
|
| 1247 | - __FUNCTION__, |
|
| 1248 | - __LINE__ |
|
| 1249 | - ); |
|
| 1250 | - return false; |
|
| 1251 | - break; |
|
| 1252 | - } |
|
| 1253 | - } |
|
| 1254 | - return true; |
|
| 1255 | - } |
|
| 1256 | - |
|
| 1257 | - |
|
| 1258 | - /** |
|
| 1259 | - * _associate_attendee_with_registration |
|
| 1260 | - * |
|
| 1261 | - * @param EE_Registration $registration |
|
| 1262 | - * @param EE_Attendee $attendee |
|
| 1263 | - * @return void |
|
| 1264 | - * @throws EE_Error |
|
| 1265 | - * @throws RuntimeException |
|
| 1266 | - */ |
|
| 1267 | - private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee) |
|
| 1268 | - { |
|
| 1269 | - // add relation to attendee |
|
| 1270 | - $registration->_add_relation_to($attendee, 'Attendee'); |
|
| 1271 | - $registration->set_attendee_id($attendee->ID()); |
|
| 1272 | - $registration->update_cache_after_object_save('Attendee', $attendee); |
|
| 1273 | - } |
|
| 1274 | - |
|
| 1275 | - |
|
| 1276 | - /** |
|
| 1277 | - * _associate_registration_with_transaction |
|
| 1278 | - * |
|
| 1279 | - * @param EE_Registration $registration |
|
| 1280 | - * @return void |
|
| 1281 | - * @throws \EE_Error |
|
| 1282 | - */ |
|
| 1283 | - private function _associate_registration_with_transaction(EE_Registration $registration) |
|
| 1284 | - { |
|
| 1285 | - // add relation to registration |
|
| 1286 | - $this->checkout->transaction->_add_relation_to($registration, 'Registration'); |
|
| 1287 | - $this->checkout->transaction->update_cache_after_object_save('Registration', $registration); |
|
| 1288 | - } |
|
| 1289 | - |
|
| 1290 | - |
|
| 1291 | - /** |
|
| 1292 | - * _copy_critical_attendee_details_from_primary_registrant |
|
| 1293 | - * ensures that all attendees at least have data for first name, last name, and email address |
|
| 1294 | - * |
|
| 1295 | - * @param array $attendee_data |
|
| 1296 | - * @return array |
|
| 1297 | - * @throws \EE_Error |
|
| 1298 | - */ |
|
| 1299 | - private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array()) |
|
| 1300 | - { |
|
| 1301 | - // bare minimum critical details include first name, last name, email address |
|
| 1302 | - $critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email'); |
|
| 1303 | - // add address info to critical details? |
|
| 1304 | - if (apply_filters( |
|
| 1305 | - 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details', |
|
| 1306 | - false |
|
| 1307 | - )) { |
|
| 1308 | - $address_details = array( |
|
| 1309 | - 'ATT_address', |
|
| 1310 | - 'ATT_address2', |
|
| 1311 | - 'ATT_city', |
|
| 1312 | - 'STA_ID', |
|
| 1313 | - 'CNT_ISO', |
|
| 1314 | - 'ATT_zip', |
|
| 1315 | - 'ATT_phone', |
|
| 1316 | - ); |
|
| 1317 | - $critical_attendee_details = array_merge($critical_attendee_details, $address_details); |
|
| 1318 | - } |
|
| 1319 | - foreach ($critical_attendee_details as $critical_attendee_detail) { |
|
| 1320 | - if (! isset($attendee_data[$critical_attendee_detail]) |
|
| 1321 | - || empty($attendee_data[$critical_attendee_detail]) |
|
| 1322 | - ) { |
|
| 1323 | - $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get( |
|
| 1324 | - $critical_attendee_detail |
|
| 1325 | - ); |
|
| 1326 | - } |
|
| 1327 | - } |
|
| 1328 | - return $attendee_data; |
|
| 1329 | - } |
|
| 1330 | - |
|
| 1331 | - |
|
| 1332 | - /** |
|
| 1333 | - * update_reg_step |
|
| 1334 | - * this is the final step after a user revisits the site to edit their attendee information |
|
| 1335 | - * this gets called AFTER the process_reg_step() method above |
|
| 1336 | - * |
|
| 1337 | - * @return bool |
|
| 1338 | - * @throws EE_Error |
|
| 1339 | - * @throws InvalidArgumentException |
|
| 1340 | - * @throws ReflectionException |
|
| 1341 | - * @throws RuntimeException |
|
| 1342 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 1343 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 1344 | - */ |
|
| 1345 | - public function update_reg_step() |
|
| 1346 | - { |
|
| 1347 | - // save everything |
|
| 1348 | - if ($this->process_reg_step()) { |
|
| 1349 | - $this->checkout->redirect = true; |
|
| 1350 | - $this->checkout->redirect_url = add_query_arg( |
|
| 1351 | - array( |
|
| 1352 | - 'e_reg_url_link' => $this->checkout->reg_url_link, |
|
| 1353 | - 'revisit' => true, |
|
| 1354 | - ), |
|
| 1355 | - $this->checkout->thank_you_page_url |
|
| 1356 | - ); |
|
| 1357 | - $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url); |
|
| 1358 | - return true; |
|
| 1359 | - } |
|
| 1360 | - return false; |
|
| 1361 | - } |
|
| 1151 | + $answer_cache_id = $this->checkout->reg_url_link |
|
| 1152 | + ? $form_input . '-' . $registration->reg_url_link() |
|
| 1153 | + : $form_input; |
|
| 1154 | + $answer_is_obj = isset($this->_registration_answers[$answer_cache_id]) |
|
| 1155 | + && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer |
|
| 1156 | + ? true |
|
| 1157 | + : false; |
|
| 1158 | + //rename form_inputs if they are EE_Attendee properties |
|
| 1159 | + switch ((string) $form_input) { |
|
| 1160 | + case 'state': |
|
| 1161 | + case 'STA_ID': |
|
| 1162 | + $attendee_property = true; |
|
| 1163 | + $form_input = 'STA_ID'; |
|
| 1164 | + break; |
|
| 1165 | + |
|
| 1166 | + case 'country': |
|
| 1167 | + case 'CNT_ISO': |
|
| 1168 | + $attendee_property = true; |
|
| 1169 | + $form_input = 'CNT_ISO'; |
|
| 1170 | + break; |
|
| 1171 | + |
|
| 1172 | + default: |
|
| 1173 | + $ATT_input = 'ATT_' . $form_input; |
|
| 1174 | + //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ ); |
|
| 1175 | + $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false; |
|
| 1176 | + $form_input = $attendee_property ? 'ATT_' . $form_input : $form_input; |
|
| 1177 | + } |
|
| 1178 | + // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ ); |
|
| 1179 | + // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ ); |
|
| 1180 | + // EEH_Debug_Tools::printr( $answer_is_obj, '$answer_is_obj', __FILE__, __LINE__ ); |
|
| 1181 | + // if this form input has a corresponding attendee property |
|
| 1182 | + if ($attendee_property) { |
|
| 1183 | + $this->_attendee_data[$registration->reg_url_link()][$form_input] = $input_value; |
|
| 1184 | + if ($answer_is_obj) { |
|
| 1185 | + // and delete the corresponding answer since we won't be storing this data in that object |
|
| 1186 | + $registration->_remove_relation_to($this->_registration_answers[$answer_cache_id], 'Answer'); |
|
| 1187 | + $this->_registration_answers[$answer_cache_id]->delete_permanently(); |
|
| 1188 | + } |
|
| 1189 | + return true; |
|
| 1190 | + } elseif ($answer_is_obj) { |
|
| 1191 | + // save this data to the answer object |
|
| 1192 | + $this->_registration_answers[$answer_cache_id]->set_value($input_value); |
|
| 1193 | + $result = $this->_registration_answers[$answer_cache_id]->save(); |
|
| 1194 | + return $result !== false ? true : false; |
|
| 1195 | + } else { |
|
| 1196 | + foreach ($this->_registration_answers as $answer) { |
|
| 1197 | + if ($answer instanceof EE_Answer && $answer->question_ID() === $answer_cache_id) { |
|
| 1198 | + $answer->set_value($input_value); |
|
| 1199 | + $result = $answer->save(); |
|
| 1200 | + return $result !== false ? true : false; |
|
| 1201 | + } |
|
| 1202 | + } |
|
| 1203 | + } |
|
| 1204 | + return false; |
|
| 1205 | + } |
|
| 1206 | + |
|
| 1207 | + |
|
| 1208 | + /** |
|
| 1209 | + * _verify_critical_attendee_details_are_set |
|
| 1210 | + * |
|
| 1211 | + * @param string $form_input |
|
| 1212 | + * @param string $input_value |
|
| 1213 | + * @return boolean |
|
| 1214 | + */ |
|
| 1215 | + private function _verify_critical_attendee_details_are_set_and_validate_email( |
|
| 1216 | + $form_input = '', |
|
| 1217 | + $input_value = '' |
|
| 1218 | + ) { |
|
| 1219 | + if (empty($input_value)) { |
|
| 1220 | + // if the form input isn't marked as being required, then just return |
|
| 1221 | + if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) { |
|
| 1222 | + return true; |
|
| 1223 | + } |
|
| 1224 | + switch ($form_input) { |
|
| 1225 | + case 'fname': |
|
| 1226 | + EE_Error::add_error( |
|
| 1227 | + esc_html__('First Name is a required value.', 'event_espresso'), |
|
| 1228 | + __FILE__, |
|
| 1229 | + __FUNCTION__, |
|
| 1230 | + __LINE__ |
|
| 1231 | + ); |
|
| 1232 | + return false; |
|
| 1233 | + break; |
|
| 1234 | + case 'lname': |
|
| 1235 | + EE_Error::add_error( |
|
| 1236 | + esc_html__('Last Name is a required value.', 'event_espresso'), |
|
| 1237 | + __FILE__, |
|
| 1238 | + __FUNCTION__, |
|
| 1239 | + __LINE__ |
|
| 1240 | + ); |
|
| 1241 | + return false; |
|
| 1242 | + break; |
|
| 1243 | + case 'email': |
|
| 1244 | + EE_Error::add_error( |
|
| 1245 | + esc_html__('Please enter a valid email address.', 'event_espresso'), |
|
| 1246 | + __FILE__, |
|
| 1247 | + __FUNCTION__, |
|
| 1248 | + __LINE__ |
|
| 1249 | + ); |
|
| 1250 | + return false; |
|
| 1251 | + break; |
|
| 1252 | + } |
|
| 1253 | + } |
|
| 1254 | + return true; |
|
| 1255 | + } |
|
| 1256 | + |
|
| 1257 | + |
|
| 1258 | + /** |
|
| 1259 | + * _associate_attendee_with_registration |
|
| 1260 | + * |
|
| 1261 | + * @param EE_Registration $registration |
|
| 1262 | + * @param EE_Attendee $attendee |
|
| 1263 | + * @return void |
|
| 1264 | + * @throws EE_Error |
|
| 1265 | + * @throws RuntimeException |
|
| 1266 | + */ |
|
| 1267 | + private function _associate_attendee_with_registration(EE_Registration $registration, EE_Attendee $attendee) |
|
| 1268 | + { |
|
| 1269 | + // add relation to attendee |
|
| 1270 | + $registration->_add_relation_to($attendee, 'Attendee'); |
|
| 1271 | + $registration->set_attendee_id($attendee->ID()); |
|
| 1272 | + $registration->update_cache_after_object_save('Attendee', $attendee); |
|
| 1273 | + } |
|
| 1274 | + |
|
| 1275 | + |
|
| 1276 | + /** |
|
| 1277 | + * _associate_registration_with_transaction |
|
| 1278 | + * |
|
| 1279 | + * @param EE_Registration $registration |
|
| 1280 | + * @return void |
|
| 1281 | + * @throws \EE_Error |
|
| 1282 | + */ |
|
| 1283 | + private function _associate_registration_with_transaction(EE_Registration $registration) |
|
| 1284 | + { |
|
| 1285 | + // add relation to registration |
|
| 1286 | + $this->checkout->transaction->_add_relation_to($registration, 'Registration'); |
|
| 1287 | + $this->checkout->transaction->update_cache_after_object_save('Registration', $registration); |
|
| 1288 | + } |
|
| 1289 | + |
|
| 1290 | + |
|
| 1291 | + /** |
|
| 1292 | + * _copy_critical_attendee_details_from_primary_registrant |
|
| 1293 | + * ensures that all attendees at least have data for first name, last name, and email address |
|
| 1294 | + * |
|
| 1295 | + * @param array $attendee_data |
|
| 1296 | + * @return array |
|
| 1297 | + * @throws \EE_Error |
|
| 1298 | + */ |
|
| 1299 | + private function _copy_critical_attendee_details_from_primary_registrant($attendee_data = array()) |
|
| 1300 | + { |
|
| 1301 | + // bare minimum critical details include first name, last name, email address |
|
| 1302 | + $critical_attendee_details = array('ATT_fname', 'ATT_lname', 'ATT_email'); |
|
| 1303 | + // add address info to critical details? |
|
| 1304 | + if (apply_filters( |
|
| 1305 | + 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details', |
|
| 1306 | + false |
|
| 1307 | + )) { |
|
| 1308 | + $address_details = array( |
|
| 1309 | + 'ATT_address', |
|
| 1310 | + 'ATT_address2', |
|
| 1311 | + 'ATT_city', |
|
| 1312 | + 'STA_ID', |
|
| 1313 | + 'CNT_ISO', |
|
| 1314 | + 'ATT_zip', |
|
| 1315 | + 'ATT_phone', |
|
| 1316 | + ); |
|
| 1317 | + $critical_attendee_details = array_merge($critical_attendee_details, $address_details); |
|
| 1318 | + } |
|
| 1319 | + foreach ($critical_attendee_details as $critical_attendee_detail) { |
|
| 1320 | + if (! isset($attendee_data[$critical_attendee_detail]) |
|
| 1321 | + || empty($attendee_data[$critical_attendee_detail]) |
|
| 1322 | + ) { |
|
| 1323 | + $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get( |
|
| 1324 | + $critical_attendee_detail |
|
| 1325 | + ); |
|
| 1326 | + } |
|
| 1327 | + } |
|
| 1328 | + return $attendee_data; |
|
| 1329 | + } |
|
| 1330 | + |
|
| 1331 | + |
|
| 1332 | + /** |
|
| 1333 | + * update_reg_step |
|
| 1334 | + * this is the final step after a user revisits the site to edit their attendee information |
|
| 1335 | + * this gets called AFTER the process_reg_step() method above |
|
| 1336 | + * |
|
| 1337 | + * @return bool |
|
| 1338 | + * @throws EE_Error |
|
| 1339 | + * @throws InvalidArgumentException |
|
| 1340 | + * @throws ReflectionException |
|
| 1341 | + * @throws RuntimeException |
|
| 1342 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
| 1343 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
| 1344 | + */ |
|
| 1345 | + public function update_reg_step() |
|
| 1346 | + { |
|
| 1347 | + // save everything |
|
| 1348 | + if ($this->process_reg_step()) { |
|
| 1349 | + $this->checkout->redirect = true; |
|
| 1350 | + $this->checkout->redirect_url = add_query_arg( |
|
| 1351 | + array( |
|
| 1352 | + 'e_reg_url_link' => $this->checkout->reg_url_link, |
|
| 1353 | + 'revisit' => true, |
|
| 1354 | + ), |
|
| 1355 | + $this->checkout->thank_you_page_url |
|
| 1356 | + ); |
|
| 1357 | + $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url); |
|
| 1358 | + return true; |
|
| 1359 | + } |
|
| 1360 | + return false; |
|
| 1361 | + } |
|
| 1362 | 1362 | } |
@@ -48,7 +48,7 @@ discard block |
||
| 48 | 48 | { |
| 49 | 49 | $this->_slug = 'attendee_information'; |
| 50 | 50 | $this->_name = esc_html__('Attendee Information', 'event_espresso'); |
| 51 | - $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . DS . 'attendee_info_main.template.php'; |
|
| 51 | + $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.DS.'attendee_info_main.template.php'; |
|
| 52 | 52 | $this->checkout = $checkout; |
| 53 | 53 | $this->_reset_success_message(); |
| 54 | 54 | $this->set_instructions( |
@@ -59,11 +59,11 @@ discard block |
||
| 59 | 59 | |
| 60 | 60 | public function translate_js_strings() |
| 61 | 61 | { |
| 62 | - EE_Registry::$i18n_js_strings['required_field'] = esc_html__( |
|
| 62 | + EE_Registry::$i18n_js_strings['required_field'] = esc_html__( |
|
| 63 | 63 | ' is a required question.', |
| 64 | 64 | 'event_espresso' |
| 65 | 65 | ); |
| 66 | - EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__( |
|
| 66 | + EE_Registry::$i18n_js_strings['required_multi_field'] = esc_html__( |
|
| 67 | 67 | ' is a required question. Please enter a value for at least one of the options.', |
| 68 | 68 | 'event_espresso' |
| 69 | 69 | ); |
@@ -71,18 +71,18 @@ discard block |
||
| 71 | 71 | 'Please answer all required questions correctly before proceeding.', |
| 72 | 72 | 'event_espresso' |
| 73 | 73 | ); |
| 74 | - EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf( |
|
| 74 | + EE_Registry::$i18n_js_strings['attendee_info_copied'] = sprintf( |
|
| 75 | 75 | esc_html__( |
| 76 | 76 | 'The attendee information was successfully copied.%sPlease ensure the rest of the registration form is completed before proceeding.', |
| 77 | 77 | 'event_espresso' |
| 78 | 78 | ), |
| 79 | 79 | '<br/>' |
| 80 | 80 | ); |
| 81 | - EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__( |
|
| 81 | + EE_Registry::$i18n_js_strings['attendee_info_copy_error'] = esc_html__( |
|
| 82 | 82 | 'An unknown error occurred on the server while attempting to copy the attendee information. Please refresh the page and try again.', |
| 83 | 83 | 'event_espresso' |
| 84 | 84 | ); |
| 85 | - EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__( |
|
| 85 | + EE_Registry::$i18n_js_strings['enter_valid_email'] = esc_html__( |
|
| 86 | 86 | 'You must enter a valid email address.', |
| 87 | 87 | 'event_espresso' |
| 88 | 88 | ); |
@@ -145,11 +145,11 @@ discard block |
||
| 145 | 145 | && $this->checkout->visit_allows_processing_of_this_registration($registration) |
| 146 | 146 | ) { |
| 147 | 147 | $subsection = $this->_registrations_reg_form($registration); |
| 148 | - if(!$subsection instanceof EE_Form_Section_Proper) { |
|
| 148 | + if ( ! $subsection instanceof EE_Form_Section_Proper) { |
|
| 149 | 149 | continue; |
| 150 | 150 | } |
| 151 | - $subsections[ $registration->reg_url_link() ] = $subsection; |
|
| 152 | - if (! $this->checkout->admin_request) { |
|
| 151 | + $subsections[$registration->reg_url_link()] = $subsection; |
|
| 152 | + if ( ! $this->checkout->admin_request) { |
|
| 153 | 153 | $template_args['registrations'][$registration->reg_url_link()] = $registration; |
| 154 | 154 | $template_args['ticket_count'][$registration->ticket()->ID()] = isset( |
| 155 | 155 | $template_args['ticket_count'][$registration->ticket()->ID()] |
@@ -197,8 +197,7 @@ discard block |
||
| 197 | 197 | 'html_id' => $this->reg_form_name(), |
| 198 | 198 | 'subsections' => $subsections, |
| 199 | 199 | 'layout_strategy' => $this->checkout->admin_request ? |
| 200 | - new EE_Div_Per_Section_Layout() : |
|
| 201 | - new EE_Template_Layout( |
|
| 200 | + new EE_Div_Per_Section_Layout() : new EE_Template_Layout( |
|
| 202 | 201 | array( |
| 203 | 202 | 'layout_template_file' => $this->_template, // layout_template |
| 204 | 203 | 'template_args' => $template_args, |
@@ -241,7 +240,7 @@ discard block |
||
| 241 | 240 | if ($question_groups) { |
| 242 | 241 | // array of params to pass to parent constructor |
| 243 | 242 | $form_args = array( |
| 244 | - 'html_id' => 'ee-registration-' . $registration->reg_url_link(), |
|
| 243 | + 'html_id' => 'ee-registration-'.$registration->reg_url_link(), |
|
| 245 | 244 | 'html_class' => 'ee-reg-form-attendee-dv', |
| 246 | 245 | 'html_style' => $this->checkout->admin_request |
| 247 | 246 | ? 'padding:0em 2em 1em; margin:3em 0 0; border:1px solid #ddd;' |
@@ -297,7 +296,7 @@ discard block |
||
| 297 | 296 | // generate hidden input |
| 298 | 297 | return new EE_Hidden_Input( |
| 299 | 298 | array( |
| 300 | - 'html_id' => 'additional-attendee-reg-info-' . $registration->reg_url_link(), |
|
| 299 | + 'html_id' => 'additional-attendee-reg-info-'.$registration->reg_url_link(), |
|
| 301 | 300 | 'default' => $additional_attendee_reg_info, |
| 302 | 301 | ) |
| 303 | 302 | ); |
@@ -317,11 +316,11 @@ discard block |
||
| 317 | 316 | { |
| 318 | 317 | // array of params to pass to parent constructor |
| 319 | 318 | $form_args = array( |
| 320 | - 'html_id' => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID(), |
|
| 319 | + 'html_id' => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-'.$registration->ID(), |
|
| 321 | 320 | 'html_class' => $this->checkout->admin_request |
| 322 | 321 | ? 'form-table ee-reg-form-qstn-grp-dv' |
| 323 | 322 | : 'ee-reg-form-qstn-grp-dv', |
| 324 | - 'html_label_id' => 'ee-reg-form-qstn-grp-' . $question_group->identifier() . '-' . $registration->ID() . '-lbl', |
|
| 323 | + 'html_label_id' => 'ee-reg-form-qstn-grp-'.$question_group->identifier().'-'.$registration->ID().'-lbl', |
|
| 325 | 324 | 'subsections' => array( |
| 326 | 325 | 'reg_form_qstn_grp_hdr' => $this->_question_group_header($question_group), |
| 327 | 326 | ), |
@@ -332,7 +331,7 @@ discard block |
||
| 332 | 331 | // where params |
| 333 | 332 | $query_params = array('QST_deleted' => 0); |
| 334 | 333 | // don't load admin only questions on the frontend |
| 335 | - if (! $this->checkout->admin_request) { |
|
| 334 | + if ( ! $this->checkout->admin_request) { |
|
| 336 | 335 | $query_params['QST_admin_only'] = array('!=', true); |
| 337 | 336 | } |
| 338 | 337 | $questions = $question_group->get_many_related( |
@@ -476,7 +475,7 @@ discard block |
||
| 476 | 475 | { |
| 477 | 476 | return new EE_Form_Section_HTML( |
| 478 | 477 | EEH_Template::locate_template( |
| 479 | - SPCO_REG_STEPS_PATH . $this->_slug . DS . '_auto_copy_attendee_info.template.php', |
|
| 478 | + SPCO_REG_STEPS_PATH.$this->_slug.DS.'_auto_copy_attendee_info.template.php', |
|
| 480 | 479 | apply_filters( |
| 481 | 480 | 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__auto_copy_attendee_info__template_args', |
| 482 | 481 | array() |
@@ -508,16 +507,16 @@ discard block |
||
| 508 | 507 | if ($registration->ticket()->ID() !== $prev_ticket) { |
| 509 | 508 | $item_name = $registration->ticket()->name(); |
| 510 | 509 | $item_name .= $registration->ticket()->description() !== '' |
| 511 | - ? ' - ' . $registration->ticket()->description() |
|
| 510 | + ? ' - '.$registration->ticket()->description() |
|
| 512 | 511 | : ''; |
| 513 | - $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-' . $registration->ticket()->ID() . ']'] = |
|
| 512 | + $copy_attendee_info_inputs['spco_copy_attendee_chk[ticket-'.$registration->ticket()->ID().']'] = |
|
| 514 | 513 | new EE_Form_Section_HTML( |
| 515 | - '<h6 class="spco-copy-attendee-event-hdr">' . $item_name . '</h6>' |
|
| 514 | + '<h6 class="spco-copy-attendee-event-hdr">'.$item_name.'</h6>' |
|
| 516 | 515 | ); |
| 517 | 516 | $prev_ticket = $registration->ticket()->ID(); |
| 518 | 517 | } |
| 519 | 518 | |
| 520 | - $copy_attendee_info_inputs['spco_copy_attendee_chk[' . $registration->ID() . ']'] = |
|
| 519 | + $copy_attendee_info_inputs['spco_copy_attendee_chk['.$registration->ID().']'] = |
|
| 521 | 520 | new EE_Checkbox_Multi_Input( |
| 522 | 521 | array( |
| 523 | 522 | $registration->ID() => sprintf( |
@@ -526,7 +525,7 @@ discard block |
||
| 526 | 525 | ), |
| 527 | 526 | ), |
| 528 | 527 | array( |
| 529 | - 'html_id' => 'spco-copy-attendee-chk-' . $registration->reg_url_link(), |
|
| 528 | + 'html_id' => 'spco-copy-attendee-chk-'.$registration->reg_url_link(), |
|
| 530 | 529 | 'html_class' => 'spco-copy-attendee-chk ee-do-not-validate', |
| 531 | 530 | 'display_html_label_text' => false, |
| 532 | 531 | ) |
@@ -575,7 +574,7 @@ discard block |
||
| 575 | 574 | $registration, |
| 576 | 575 | $question->system_ID() |
| 577 | 576 | ); |
| 578 | - $answer = $answer_value === null |
|
| 577 | + $answer = $answer_value === null |
|
| 579 | 578 | ? EEM_Answer::instance()->get_one( |
| 580 | 579 | array(array('QST_ID' => $question->ID(), 'REG_ID' => $registration->ID())) |
| 581 | 580 | ) |
@@ -592,14 +591,14 @@ discard block |
||
| 592 | 591 | } |
| 593 | 592 | // verify instance |
| 594 | 593 | if ($answer instanceof EE_Answer) { |
| 595 | - if (! empty($answer_value)) { |
|
| 594 | + if ( ! empty($answer_value)) { |
|
| 596 | 595 | $answer->set('ANS_value', $answer_value); |
| 597 | 596 | } |
| 598 | 597 | $answer->cache('Question', $question); |
| 599 | 598 | //remember system ID had a bug where sometimes it could be null |
| 600 | 599 | $answer_cache_id = $question->is_system_question() |
| 601 | - ? $question->system_ID() . '-' . $registration->reg_url_link() |
|
| 602 | - : $question->ID() . '-' . $registration->reg_url_link(); |
|
| 600 | + ? $question->system_ID().'-'.$registration->reg_url_link() |
|
| 601 | + : $question->ID().'-'.$registration->reg_url_link(); |
|
| 603 | 602 | $registration->cache('Answer', $answer, $answer_cache_id); |
| 604 | 603 | } |
| 605 | 604 | return $this->_generate_question_input($registration, $question, $answer); |
@@ -631,18 +630,18 @@ discard block |
||
| 631 | 630 | 10, |
| 632 | 631 | 4 |
| 633 | 632 | ); |
| 634 | - $input_constructor_args = array( |
|
| 635 | - 'html_name' => 'ee_reg_qstn[' . $registration->ID() . '][' . $identifier . ']', |
|
| 636 | - 'html_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier, |
|
| 637 | - 'html_class' => 'ee-reg-qstn ee-reg-qstn-' . $identifier, |
|
| 638 | - 'html_label_id' => 'ee_reg_qstn-' . $registration->ID() . '-' . $identifier, |
|
| 633 | + $input_constructor_args = array( |
|
| 634 | + 'html_name' => 'ee_reg_qstn['.$registration->ID().']['.$identifier.']', |
|
| 635 | + 'html_id' => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier, |
|
| 636 | + 'html_class' => 'ee-reg-qstn ee-reg-qstn-'.$identifier, |
|
| 637 | + 'html_label_id' => 'ee_reg_qstn-'.$registration->ID().'-'.$identifier, |
|
| 639 | 638 | 'html_label_class' => 'ee-reg-qstn', |
| 640 | 639 | ); |
| 641 | 640 | $input_constructor_args['html_label_id'] .= '-lbl'; |
| 642 | 641 | if ($answer instanceof EE_Answer && $answer->ID()) { |
| 643 | - $input_constructor_args['html_name'] .= '[' . $answer->ID() . ']'; |
|
| 644 | - $input_constructor_args['html_id'] .= '-' . $answer->ID(); |
|
| 645 | - $input_constructor_args['html_label_id'] .= '-' . $answer->ID(); |
|
| 642 | + $input_constructor_args['html_name'] .= '['.$answer->ID().']'; |
|
| 643 | + $input_constructor_args['html_id'] .= '-'.$answer->ID(); |
|
| 644 | + $input_constructor_args['html_label_id'] .= '-'.$answer->ID(); |
|
| 646 | 645 | } |
| 647 | 646 | $form_input = $question->generate_form_input( |
| 648 | 647 | $registration, |
@@ -685,7 +684,7 @@ discard block |
||
| 685 | 684 | $countries = $this->checkout->action === 'process_reg_step' |
| 686 | 685 | ? EEM_Country::instance()->get_all_countries() |
| 687 | 686 | : EEM_Country::instance()->get_all_active_countries(); |
| 688 | - if (! empty($countries)) { |
|
| 687 | + if ( ! empty($countries)) { |
|
| 689 | 688 | foreach ($countries as $country) { |
| 690 | 689 | if ($country instanceof EE_Country) { |
| 691 | 690 | $country_options[$country->ID()] = $country->name(); |
@@ -735,7 +734,7 @@ discard block |
||
| 735 | 734 | $states = $this->checkout->action === 'process_reg_step' |
| 736 | 735 | ? EEM_State::instance()->get_all_states() |
| 737 | 736 | : EEM_State::instance()->get_all_active_states(); |
| 738 | - if (! empty($states)) { |
|
| 737 | + if ( ! empty($states)) { |
|
| 739 | 738 | foreach ($states as $state) { |
| 740 | 739 | if ($state instanceof EE_State) { |
| 741 | 740 | $state_options[$state->country()->name()][$state->ID()] = $state->name(); |
@@ -787,7 +786,7 @@ discard block |
||
| 787 | 786 | ); |
| 788 | 787 | return false; |
| 789 | 788 | } |
| 790 | - if (! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) { |
|
| 789 | + if ( ! $this->checkout->transaction instanceof EE_Transaction || ! $this->checkout->continue_reg) { |
|
| 791 | 790 | EE_Error::add_error( |
| 792 | 791 | esc_html__( |
| 793 | 792 | 'A valid transaction could not be initiated for processing your registrations.', |
@@ -804,10 +803,10 @@ discard block |
||
| 804 | 803 | // verify we got the goods |
| 805 | 804 | if (empty($registrations)) { |
| 806 | 805 | //combine the old translated string with a new one, in order to not break translations |
| 807 | - $error_message = esc_html__( 'Your form data could not be applied to any valid registrations.', 'event_espresso' ) |
|
| 806 | + $error_message = esc_html__('Your form data could not be applied to any valid registrations.', 'event_espresso') |
|
| 808 | 807 | . sprintf( |
| 809 | 808 | esc_html__('%3$sThis can sometimes happen if too much time has been taken to complete the registration process.%3$sPlease return to the %1$sEvent List%2$s and reselect your tickets. If the problem continues, please contact the site administrator.', 'event_espresso'), |
| 810 | - '<a href="' . get_post_type_archive_link('espresso_events') . '" >', |
|
| 809 | + '<a href="'.get_post_type_archive_link('espresso_events').'" >', |
|
| 811 | 810 | '</a>', |
| 812 | 811 | '<br />' |
| 813 | 812 | ); |
@@ -826,7 +825,7 @@ discard block |
||
| 826 | 825 | if ($registrations_processed === false) { |
| 827 | 826 | // but return immediately if the previous step exited early due to errors |
| 828 | 827 | return false; |
| 829 | - } elseif (! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) { |
|
| 828 | + } elseif ( ! $this->checkout->revisit && $registrations_processed !== $this->checkout->total_ticket_count) { |
|
| 830 | 829 | // generate a correctly translated string for all possible singular/plural combinations |
| 831 | 830 | if ($this->checkout->total_ticket_count === 1 && $registrations_processed !== 1) { |
| 832 | 831 | $error_msg = sprintf( |
@@ -907,7 +906,7 @@ discard block |
||
| 907 | 906 | // grab the saved registrations from the transaction |
| 908 | 907 | foreach ($registrations as $registration) { |
| 909 | 908 | // verify EE_Registration object |
| 910 | - if (! $registration instanceof EE_Registration) { |
|
| 909 | + if ( ! $registration instanceof EE_Registration) { |
|
| 911 | 910 | EE_Error::add_error( |
| 912 | 911 | esc_html__( |
| 913 | 912 | 'An invalid Registration object was discovered when attempting to process your registration information.', |
@@ -922,12 +921,12 @@ discard block |
||
| 922 | 921 | /** @var string $reg_url_link */ |
| 923 | 922 | $reg_url_link = $registration->reg_url_link(); |
| 924 | 923 | // reg_url_link exists ? |
| 925 | - if (! empty($reg_url_link)) { |
|
| 924 | + if ( ! empty($reg_url_link)) { |
|
| 926 | 925 | // should this registration be processed during this visit ? |
| 927 | 926 | if ($this->checkout->visit_allows_processing_of_this_registration($registration)) { |
| 928 | 927 | // if NOT revisiting, then let's save the registration now, |
| 929 | 928 | // so that we have a REG_ID to use when generating other objects |
| 930 | - if (! $this->checkout->revisit) { |
|
| 929 | + if ( ! $this->checkout->revisit) { |
|
| 931 | 930 | $registration->save(); |
| 932 | 931 | } |
| 933 | 932 | /** |
@@ -962,7 +961,7 @@ discard block |
||
| 962 | 961 | ? true |
| 963 | 962 | : false; |
| 964 | 963 | // filter form input data for this registration |
| 965 | - $valid_data[$reg_url_link] = (array)apply_filters( |
|
| 964 | + $valid_data[$reg_url_link] = (array) apply_filters( |
|
| 966 | 965 | 'FHEE__EE_Single_Page_Checkout__process_attendee_information__valid_data_line_item', |
| 967 | 966 | $valid_data[$reg_url_link] |
| 968 | 967 | ); |
@@ -974,11 +973,11 @@ discard block |
||
| 974 | 973 | } |
| 975 | 974 | // now loop through our array of valid post data && process attendee reg forms |
| 976 | 975 | foreach ($valid_data[$reg_url_link] as $form_section => $form_inputs) { |
| 977 | - if (! in_array($form_section, $non_input_form_sections)) { |
|
| 976 | + if ( ! in_array($form_section, $non_input_form_sections)) { |
|
| 978 | 977 | foreach ($form_inputs as $form_input => $input_value) { |
| 979 | 978 | // \EEH_Debug_Tools::printr( $input_value, $form_input, __FILE__, __LINE__ ); |
| 980 | 979 | // check for critical inputs |
| 981 | - if (! $this->_verify_critical_attendee_details_are_set_and_validate_email( |
|
| 980 | + if ( ! $this->_verify_critical_attendee_details_are_set_and_validate_email( |
|
| 982 | 981 | $form_input, |
| 983 | 982 | $input_value |
| 984 | 983 | ) |
@@ -998,7 +997,7 @@ discard block |
||
| 998 | 997 | $input_value = $primary_registrant[$form_input]; |
| 999 | 998 | } |
| 1000 | 999 | // now attempt to save the input data |
| 1001 | - if (! $this->_save_registration_form_input( |
|
| 1000 | + if ( ! $this->_save_registration_form_input( |
|
| 1002 | 1001 | $registration, |
| 1003 | 1002 | $form_input, |
| 1004 | 1003 | $input_value |
@@ -1054,7 +1053,7 @@ discard block |
||
| 1054 | 1053 | // add relation to registration, set attendee ID, and cache attendee |
| 1055 | 1054 | $this->_associate_attendee_with_registration($registration, $attendee); |
| 1056 | 1055 | // \EEH_Debug_Tools::printr( $registration, '$registration', __FILE__, __LINE__ ); |
| 1057 | - if (! $registration->attendee() instanceof EE_Attendee) { |
|
| 1056 | + if ( ! $registration->attendee() instanceof EE_Attendee) { |
|
| 1058 | 1057 | EE_Error::add_error( |
| 1059 | 1058 | sprintf( |
| 1060 | 1059 | esc_html__( |
@@ -1149,7 +1148,7 @@ discard block |
||
| 1149 | 1148 | * @see https://events.codebasehq.com/projects/event-espresso/tickets/10477 |
| 1150 | 1149 | */ |
| 1151 | 1150 | $answer_cache_id = $this->checkout->reg_url_link |
| 1152 | - ? $form_input . '-' . $registration->reg_url_link() |
|
| 1151 | + ? $form_input.'-'.$registration->reg_url_link() |
|
| 1153 | 1152 | : $form_input; |
| 1154 | 1153 | $answer_is_obj = isset($this->_registration_answers[$answer_cache_id]) |
| 1155 | 1154 | && $this->_registration_answers[$answer_cache_id] instanceof EE_Answer |
@@ -1170,10 +1169,10 @@ discard block |
||
| 1170 | 1169 | break; |
| 1171 | 1170 | |
| 1172 | 1171 | default: |
| 1173 | - $ATT_input = 'ATT_' . $form_input; |
|
| 1172 | + $ATT_input = 'ATT_'.$form_input; |
|
| 1174 | 1173 | //EEH_Debug_Tools::printr( $ATT_input, '$ATT_input', __FILE__, __LINE__ ); |
| 1175 | 1174 | $attendee_property = EEM_Attendee::instance()->has_field($ATT_input) ? true : false; |
| 1176 | - $form_input = $attendee_property ? 'ATT_' . $form_input : $form_input; |
|
| 1175 | + $form_input = $attendee_property ? 'ATT_'.$form_input : $form_input; |
|
| 1177 | 1176 | } |
| 1178 | 1177 | // EEH_Debug_Tools::printr( $answer_cache_id, '$answer_cache_id', __FILE__, __LINE__ ); |
| 1179 | 1178 | // EEH_Debug_Tools::printr( $attendee_property, '$attendee_property', __FILE__, __LINE__ ); |
@@ -1218,7 +1217,7 @@ discard block |
||
| 1218 | 1217 | ) { |
| 1219 | 1218 | if (empty($input_value)) { |
| 1220 | 1219 | // if the form input isn't marked as being required, then just return |
| 1221 | - if (! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) { |
|
| 1220 | + if ( ! isset($this->_required_questions[$form_input]) || ! $this->_required_questions[$form_input]) { |
|
| 1222 | 1221 | return true; |
| 1223 | 1222 | } |
| 1224 | 1223 | switch ($form_input) { |
@@ -1305,7 +1304,7 @@ discard block |
||
| 1305 | 1304 | 'FHEE__EE_SPCO_Reg_Step_Attendee_Information__merge_address_details_with_critical_attendee_details', |
| 1306 | 1305 | false |
| 1307 | 1306 | )) { |
| 1308 | - $address_details = array( |
|
| 1307 | + $address_details = array( |
|
| 1309 | 1308 | 'ATT_address', |
| 1310 | 1309 | 'ATT_address2', |
| 1311 | 1310 | 'ATT_city', |
@@ -1317,7 +1316,7 @@ discard block |
||
| 1317 | 1316 | $critical_attendee_details = array_merge($critical_attendee_details, $address_details); |
| 1318 | 1317 | } |
| 1319 | 1318 | foreach ($critical_attendee_details as $critical_attendee_detail) { |
| 1320 | - if (! isset($attendee_data[$critical_attendee_detail]) |
|
| 1319 | + if ( ! isset($attendee_data[$critical_attendee_detail]) |
|
| 1321 | 1320 | || empty($attendee_data[$critical_attendee_detail]) |
| 1322 | 1321 | ) { |
| 1323 | 1322 | $attendee_data[$critical_attendee_detail] = $this->checkout->primary_attendee_obj->get( |
@@ -22,382 +22,382 @@ |
||
| 22 | 22 | class EED_Recaptcha extends EED_Module |
| 23 | 23 | { |
| 24 | 24 | |
| 25 | - /** |
|
| 26 | - * @var EE_Registration_Config $config |
|
| 27 | - */ |
|
| 28 | - private static $config; |
|
| 29 | - |
|
| 30 | - /** |
|
| 31 | - * @type bool $_not_a_robot |
|
| 32 | - */ |
|
| 33 | - private static $_not_a_robot; |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * @type string $_recaptcha_response |
|
| 37 | - */ |
|
| 38 | - private static $_recaptcha_response; |
|
| 39 | - |
|
| 40 | - |
|
| 41 | - /** |
|
| 42 | - * @return EED_Module|EED_Recaptcha |
|
| 43 | - */ |
|
| 44 | - public static function instance() |
|
| 45 | - { |
|
| 46 | - return parent::get_instance(__CLASS__); |
|
| 47 | - } |
|
| 48 | - |
|
| 49 | - |
|
| 50 | - /** |
|
| 51 | - * set_hooks - for hooking into EE Core, other modules, etc |
|
| 52 | - * |
|
| 53 | - * @return void |
|
| 54 | - * @throws InvalidArgumentException |
|
| 55 | - * @throws InvalidInterfaceException |
|
| 56 | - * @throws InvalidDataTypeException |
|
| 57 | - */ |
|
| 58 | - public static function set_hooks() |
|
| 59 | - { |
|
| 60 | - EED_Recaptcha::$config = EE_Registry::instance()->CFG->registration; |
|
| 61 | - // use_captcha ? |
|
| 62 | - if ( |
|
| 63 | - EED_Recaptcha::useRecaptcha() |
|
| 64 | - && EED_Recaptcha::notPaymentOptionsRevisit() |
|
| 65 | - ) { |
|
| 66 | - EED_Recaptcha::set_definitions(); |
|
| 67 | - EED_Recaptcha::enqueue_styles_and_scripts(); |
|
| 68 | - add_action('wp', array('EED_Recaptcha', 'set_late_hooks'), 1, 0); |
|
| 69 | - add_action( |
|
| 70 | - 'AHEE__before_spco_whats_next_buttons', |
|
| 71 | - array('EED_Recaptcha', 'display_recaptcha'), 10, 0 |
|
| 72 | - ); |
|
| 73 | - add_filter( |
|
| 74 | - 'FHEE__EED_Single_Page_Checkout__init___continue_reg', |
|
| 75 | - array('EED_Recaptcha', 'not_a_robot') |
|
| 76 | - ); |
|
| 77 | - add_filter( |
|
| 78 | - 'FHEE__EE_SPCO_Reg_Step__set_completed___completed', |
|
| 79 | - array('EED_Recaptcha', 'not_a_robot') |
|
| 80 | - ); |
|
| 81 | - add_filter( |
|
| 82 | - 'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', |
|
| 83 | - array('EED_Recaptcha', 'recaptcha_response') |
|
| 84 | - ); |
|
| 85 | - add_filter( |
|
| 86 | - 'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array', |
|
| 87 | - array('EED_Recaptcha', 'bypass_recaptcha_for_spco_load_payment_method') |
|
| 88 | - ); |
|
| 89 | - } |
|
| 90 | - } |
|
| 91 | - |
|
| 92 | - |
|
| 93 | - /** |
|
| 94 | - * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
| 95 | - * |
|
| 96 | - * @return void |
|
| 97 | - * @throws InvalidArgumentException |
|
| 98 | - * @throws InvalidInterfaceException |
|
| 99 | - * @throws InvalidDataTypeException |
|
| 100 | - */ |
|
| 101 | - public static function set_hooks_admin() |
|
| 102 | - { |
|
| 103 | - EED_Recaptcha::$config = EE_Registry::instance()->CFG->registration; |
|
| 104 | - EED_Recaptcha::set_definitions(); |
|
| 105 | - // use_captcha ? |
|
| 106 | - if ( |
|
| 107 | - EED_Recaptcha::useRecaptcha() |
|
| 108 | - && EED_Recaptcha::notPaymentOptionsRevisit() |
|
| 109 | - && EE_Registry::instance()->REQ->get('step', '') !== '' |
|
| 110 | - ) { |
|
| 111 | - EED_Recaptcha::enqueue_styles_and_scripts(); |
|
| 112 | - add_filter( |
|
| 113 | - 'FHEE__EED_Single_Page_Checkout__init___continue_reg', |
|
| 114 | - array('EED_Recaptcha', 'not_a_robot') |
|
| 115 | - ); |
|
| 116 | - add_filter( |
|
| 117 | - 'FHEE__EE_SPCO_Reg_Step__set_completed___completed', |
|
| 118 | - array('EED_Recaptcha', 'not_a_robot') |
|
| 119 | - ); |
|
| 120 | - add_filter( |
|
| 121 | - 'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', |
|
| 122 | - array('EED_Recaptcha', 'recaptcha_response') |
|
| 123 | - ); |
|
| 124 | - } |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - |
|
| 128 | - /** |
|
| 129 | - * @return void |
|
| 130 | - */ |
|
| 131 | - public static function set_definitions() |
|
| 132 | - { |
|
| 133 | - if (is_user_logged_in()) { |
|
| 134 | - EED_Recaptcha::$_not_a_robot = true; |
|
| 135 | - } |
|
| 136 | - define( |
|
| 137 | - 'RECAPTCHA_BASE_PATH', |
|
| 138 | - rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS |
|
| 139 | - ); |
|
| 140 | - define('RECAPTCHA_BASE_URL', plugin_dir_url(__FILE__)); |
|
| 141 | - } |
|
| 142 | - |
|
| 143 | - |
|
| 144 | - /** |
|
| 145 | - * @return void |
|
| 146 | - */ |
|
| 147 | - public static function set_late_hooks() |
|
| 148 | - { |
|
| 149 | - add_filter( |
|
| 150 | - 'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', |
|
| 151 | - array('EED_Recaptcha', 'not_a_robot') |
|
| 152 | - ); |
|
| 153 | - } |
|
| 154 | - |
|
| 155 | - |
|
| 156 | - /** |
|
| 157 | - * @return boolean |
|
| 158 | - */ |
|
| 159 | - public static function useRecaptcha() |
|
| 160 | - { |
|
| 161 | - return EED_Recaptcha::$config->use_captcha |
|
| 162 | - && EED_Recaptcha::$config->recaptcha_theme !== 'invisible'; |
|
| 163 | - } |
|
| 164 | - |
|
| 165 | - |
|
| 166 | - /** |
|
| 167 | - * @return boolean |
|
| 168 | - * @throws InvalidArgumentException |
|
| 169 | - * @throws InvalidInterfaceException |
|
| 170 | - * @throws InvalidDataTypeException |
|
| 171 | - */ |
|
| 172 | - public static function notPaymentOptionsRevisit() |
|
| 173 | - { |
|
| 174 | - return ! ( |
|
| 175 | - EE_Registry::instance()->REQ->get('step', '') === 'payment_options' |
|
| 176 | - && (boolean) EE_Registry::instance()->REQ->get('revisit', false) === true |
|
| 177 | - ); |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - |
|
| 181 | - /** |
|
| 182 | - * @return void |
|
| 183 | - * @throws InvalidArgumentException |
|
| 184 | - * @throws InvalidInterfaceException |
|
| 185 | - * @throws InvalidDataTypeException |
|
| 186 | - */ |
|
| 187 | - public static function enqueue_styles_and_scripts() |
|
| 188 | - { |
|
| 189 | - wp_register_script( |
|
| 190 | - 'espresso_recaptcha', |
|
| 191 | - RECAPTCHA_BASE_URL . 'scripts' . DS . 'espresso_recaptcha.js', |
|
| 192 | - array('single_page_checkout'), |
|
| 193 | - EVENT_ESPRESSO_VERSION, |
|
| 194 | - true |
|
| 195 | - ); |
|
| 196 | - wp_register_script( |
|
| 197 | - 'google_recaptcha', |
|
| 198 | - 'https://www.google.com/recaptcha/api.js?hl=' . EED_Recaptcha::$config->recaptcha_language, |
|
| 199 | - array('espresso_recaptcha'), |
|
| 200 | - EVENT_ESPRESSO_VERSION, |
|
| 201 | - true |
|
| 202 | - ); |
|
| 203 | - EE_Registry::$i18n_js_strings['no_SPCO_error'] = __( |
|
| 204 | - 'It appears the Single Page Checkout javascript was not loaded properly! Please refresh the page and try again or contact support.', |
|
| 205 | - 'event_espresso' |
|
| 206 | - ); |
|
| 207 | - EE_Registry::$i18n_js_strings['no_recaptcha_error'] = __( |
|
| 208 | - 'There appears to be a problem with the reCAPTCHA configuration! Please check the admin settings or contact support.', |
|
| 209 | - 'event_espresso' |
|
| 210 | - ); |
|
| 211 | - EE_Registry::$i18n_js_strings['recaptcha_fail'] = __( |
|
| 212 | - 'Please complete the anti-spam test before proceeding.', |
|
| 213 | - 'event_espresso' |
|
| 214 | - ); |
|
| 215 | - } |
|
| 216 | - |
|
| 217 | - |
|
| 218 | - /** |
|
| 219 | - * @param \WP $WP |
|
| 220 | - */ |
|
| 221 | - public function run($WP) |
|
| 222 | - { |
|
| 223 | - } |
|
| 224 | - |
|
| 225 | - |
|
| 226 | - /** |
|
| 227 | - * @return boolean |
|
| 228 | - * @throws InvalidArgumentException |
|
| 229 | - * @throws InvalidInterfaceException |
|
| 230 | - * @throws InvalidDataTypeException |
|
| 231 | - */ |
|
| 232 | - public static function not_a_robot() |
|
| 233 | - { |
|
| 234 | - $not_a_robot = is_bool(EED_Recaptcha::$_not_a_robot) |
|
| 235 | - ? EED_Recaptcha::$_not_a_robot |
|
| 236 | - : EED_Recaptcha::recaptcha_passed(); |
|
| 237 | - return $not_a_robot; |
|
| 238 | - } |
|
| 239 | - |
|
| 240 | - |
|
| 241 | - /** |
|
| 242 | - * @return void |
|
| 243 | - * @throws DomainException |
|
| 244 | - * @throws InvalidArgumentException |
|
| 245 | - * @throws InvalidInterfaceException |
|
| 246 | - * @throws InvalidDataTypeException |
|
| 247 | - */ |
|
| 248 | - public static function display_recaptcha() |
|
| 249 | - { |
|
| 250 | - // logged in means you have already passed a turing test of sorts |
|
| 251 | - if (is_user_logged_in()) { |
|
| 252 | - return; |
|
| 253 | - } |
|
| 254 | - // don't display if not using recaptcha or user is logged in |
|
| 255 | - if (EED_Recaptcha::useRecaptcha() && ! EED_Recaptcha::$_not_a_robot) { |
|
| 256 | - // only display if they have NOT passed the test yet |
|
| 257 | - EEH_Template::display_template( |
|
| 258 | - RECAPTCHA_BASE_PATH . DS . 'templates' . DS . 'recaptcha.template.php', |
|
| 259 | - array( |
|
| 260 | - 'recaptcha_publickey' => EED_Recaptcha::$config->recaptcha_publickey, |
|
| 261 | - 'recaptcha_theme' => EED_Recaptcha::$config->recaptcha_theme, |
|
| 262 | - 'recaptcha_type' => EED_Recaptcha::$config->recaptcha_type, |
|
| 263 | - ) |
|
| 264 | - ); |
|
| 265 | - wp_enqueue_script('google_recaptcha'); |
|
| 266 | - } |
|
| 267 | - } |
|
| 268 | - |
|
| 269 | - |
|
| 270 | - /** |
|
| 271 | - * @return array |
|
| 272 | - * @throws InvalidArgumentException |
|
| 273 | - * @throws InvalidInterfaceException |
|
| 274 | - * @throws InvalidDataTypeException |
|
| 275 | - */ |
|
| 276 | - public static function bypass_recaptcha_for_spco_load_payment_method() |
|
| 277 | - { |
|
| 278 | - return array( |
|
| 279 | - 'EESID' => EE_Registry::instance()->SSN->id(), |
|
| 280 | - 'step' => 'payment_options', |
|
| 281 | - 'action' => 'switch_spco_billing_form', |
|
| 282 | - ); |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - |
|
| 286 | - /** |
|
| 287 | - * @return boolean |
|
| 288 | - * @throws InvalidArgumentException |
|
| 289 | - * @throws InvalidInterfaceException |
|
| 290 | - * @throws InvalidDataTypeException |
|
| 291 | - */ |
|
| 292 | - public static function recaptcha_passed() |
|
| 293 | - { |
|
| 294 | - // logged in means you have already passed a turing test of sorts |
|
| 295 | - if (is_user_logged_in() || EED_Recaptcha::_bypass_recaptcha()) { |
|
| 296 | - return true; |
|
| 297 | - } |
|
| 298 | - // was test already passed? |
|
| 299 | - $recaptcha_passed = EE_Registry::instance()->SSN->get_session_data('recaptcha_passed'); |
|
| 300 | - $recaptcha_passed = filter_var($recaptcha_passed, FILTER_VALIDATE_BOOLEAN); |
|
| 301 | - // verify recaptcha |
|
| 302 | - EED_Recaptcha::_get_recaptcha_response(); |
|
| 303 | - if (! $recaptcha_passed && EED_Recaptcha::$_recaptcha_response) { |
|
| 304 | - $recaptcha_passed = EED_Recaptcha::_process_recaptcha_response(); |
|
| 305 | - EE_Registry::instance()->SSN->set_session_data(array('recaptcha_passed' => $recaptcha_passed)); |
|
| 306 | - } |
|
| 307 | - EED_Recaptcha::$_not_a_robot = $recaptcha_passed; |
|
| 308 | - return $recaptcha_passed; |
|
| 309 | - } |
|
| 310 | - |
|
| 311 | - |
|
| 312 | - /** |
|
| 313 | - * @param array $recaptcha_response |
|
| 314 | - * @return array |
|
| 315 | - */ |
|
| 316 | - public static function recaptcha_response($recaptcha_response = array()) |
|
| 317 | - { |
|
| 318 | - if (EED_Recaptcha::_bypass_recaptcha()) { |
|
| 319 | - $recaptcha_response['bypass_recaptcha'] = true; |
|
| 320 | - $recaptcha_response['recaptcha_passed'] = true; |
|
| 321 | - } else { |
|
| 322 | - $recaptcha_response['recaptcha_passed'] = EED_Recaptcha::$_not_a_robot; |
|
| 323 | - } |
|
| 324 | - return $recaptcha_response; |
|
| 325 | - } |
|
| 326 | - |
|
| 327 | - |
|
| 328 | - /** |
|
| 329 | - * @return boolean |
|
| 330 | - */ |
|
| 331 | - private static function _bypass_recaptcha() |
|
| 332 | - { |
|
| 333 | - // an array of key value pairs that must match exactly with the incoming request, |
|
| 334 | - // in order to bypass recaptcha for the current request ONLY |
|
| 335 | - $bypass_request_params_array = (array) apply_filters( |
|
| 336 | - 'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array', |
|
| 337 | - array() |
|
| 338 | - ); |
|
| 339 | - // does $bypass_request_params_array have any values ? |
|
| 340 | - if (empty($bypass_request_params_array)) { |
|
| 341 | - return false; |
|
| 342 | - } |
|
| 343 | - // initially set bypass to TRUE |
|
| 344 | - $bypass_recaptcha = true; |
|
| 345 | - foreach ($bypass_request_params_array as $key => $value) { |
|
| 346 | - // if $key is not found or value doesn't match exactly, then toggle bypass to FALSE, |
|
| 347 | - // otherwise carry over it's value. This way, one missed setting results in no bypass |
|
| 348 | - $bypass_recaptcha = isset($_REQUEST[ $key ]) && $_REQUEST[ $key ] === $value |
|
| 349 | - ? $bypass_recaptcha |
|
| 350 | - : false; |
|
| 351 | - } |
|
| 352 | - return $bypass_recaptcha; |
|
| 353 | - } |
|
| 354 | - |
|
| 355 | - |
|
| 356 | - /** |
|
| 357 | - * @return void |
|
| 358 | - * @throws InvalidArgumentException |
|
| 359 | - * @throws InvalidInterfaceException |
|
| 360 | - * @throws InvalidDataTypeException |
|
| 361 | - */ |
|
| 362 | - private static function _get_recaptcha_response() |
|
| 363 | - { |
|
| 364 | - EED_Recaptcha::$_recaptcha_response = EE_Registry::instance()->REQ->get( |
|
| 365 | - 'g-recaptcha-response', |
|
| 366 | - false |
|
| 367 | - ); |
|
| 368 | - } |
|
| 369 | - |
|
| 370 | - |
|
| 371 | - /** |
|
| 372 | - * @return boolean |
|
| 373 | - * @throws InvalidArgumentException |
|
| 374 | - * @throws InvalidInterfaceException |
|
| 375 | - * @throws InvalidDataTypeException |
|
| 376 | - */ |
|
| 377 | - private static function _process_recaptcha_response() |
|
| 378 | - { |
|
| 379 | - // verify library is loaded |
|
| 380 | - if (! class_exists('\ReCaptcha\ReCaptcha')) { |
|
| 381 | - require_once RECAPTCHA_BASE_PATH . DS . 'autoload.php'; |
|
| 382 | - } |
|
| 383 | - // The response from reCAPTCHA |
|
| 384 | - EED_Recaptcha::_get_recaptcha_response(); |
|
| 385 | - $recaptcha_response = EED_Recaptcha::$_recaptcha_response; |
|
| 386 | - // Was there a reCAPTCHA response? |
|
| 387 | - if ($recaptcha_response) { |
|
| 388 | - // if allow_url_fopen is Off, then set a different request method |
|
| 389 | - $request_method = ! ini_get('allow_url_fopen') ? new SocketPost() : null; |
|
| 390 | - $recaptcha = new ReCaptcha( |
|
| 391 | - EED_Recaptcha::$config->recaptcha_privatekey, |
|
| 392 | - $request_method |
|
| 393 | - ); |
|
| 394 | - $recaptcha_response = $recaptcha->verify( |
|
| 395 | - EED_Recaptcha::$_recaptcha_response, |
|
| 396 | - $_SERVER['REMOTE_ADDR'] |
|
| 397 | - ); |
|
| 398 | - } |
|
| 399 | - return $recaptcha_response instanceof Response && $recaptcha_response->isSuccess(); |
|
| 400 | - } |
|
| 25 | + /** |
|
| 26 | + * @var EE_Registration_Config $config |
|
| 27 | + */ |
|
| 28 | + private static $config; |
|
| 29 | + |
|
| 30 | + /** |
|
| 31 | + * @type bool $_not_a_robot |
|
| 32 | + */ |
|
| 33 | + private static $_not_a_robot; |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * @type string $_recaptcha_response |
|
| 37 | + */ |
|
| 38 | + private static $_recaptcha_response; |
|
| 39 | + |
|
| 40 | + |
|
| 41 | + /** |
|
| 42 | + * @return EED_Module|EED_Recaptcha |
|
| 43 | + */ |
|
| 44 | + public static function instance() |
|
| 45 | + { |
|
| 46 | + return parent::get_instance(__CLASS__); |
|
| 47 | + } |
|
| 48 | + |
|
| 49 | + |
|
| 50 | + /** |
|
| 51 | + * set_hooks - for hooking into EE Core, other modules, etc |
|
| 52 | + * |
|
| 53 | + * @return void |
|
| 54 | + * @throws InvalidArgumentException |
|
| 55 | + * @throws InvalidInterfaceException |
|
| 56 | + * @throws InvalidDataTypeException |
|
| 57 | + */ |
|
| 58 | + public static function set_hooks() |
|
| 59 | + { |
|
| 60 | + EED_Recaptcha::$config = EE_Registry::instance()->CFG->registration; |
|
| 61 | + // use_captcha ? |
|
| 62 | + if ( |
|
| 63 | + EED_Recaptcha::useRecaptcha() |
|
| 64 | + && EED_Recaptcha::notPaymentOptionsRevisit() |
|
| 65 | + ) { |
|
| 66 | + EED_Recaptcha::set_definitions(); |
|
| 67 | + EED_Recaptcha::enqueue_styles_and_scripts(); |
|
| 68 | + add_action('wp', array('EED_Recaptcha', 'set_late_hooks'), 1, 0); |
|
| 69 | + add_action( |
|
| 70 | + 'AHEE__before_spco_whats_next_buttons', |
|
| 71 | + array('EED_Recaptcha', 'display_recaptcha'), 10, 0 |
|
| 72 | + ); |
|
| 73 | + add_filter( |
|
| 74 | + 'FHEE__EED_Single_Page_Checkout__init___continue_reg', |
|
| 75 | + array('EED_Recaptcha', 'not_a_robot') |
|
| 76 | + ); |
|
| 77 | + add_filter( |
|
| 78 | + 'FHEE__EE_SPCO_Reg_Step__set_completed___completed', |
|
| 79 | + array('EED_Recaptcha', 'not_a_robot') |
|
| 80 | + ); |
|
| 81 | + add_filter( |
|
| 82 | + 'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', |
|
| 83 | + array('EED_Recaptcha', 'recaptcha_response') |
|
| 84 | + ); |
|
| 85 | + add_filter( |
|
| 86 | + 'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array', |
|
| 87 | + array('EED_Recaptcha', 'bypass_recaptcha_for_spco_load_payment_method') |
|
| 88 | + ); |
|
| 89 | + } |
|
| 90 | + } |
|
| 91 | + |
|
| 92 | + |
|
| 93 | + /** |
|
| 94 | + * set_hooks_admin - for hooking into EE Admin Core, other modules, etc |
|
| 95 | + * |
|
| 96 | + * @return void |
|
| 97 | + * @throws InvalidArgumentException |
|
| 98 | + * @throws InvalidInterfaceException |
|
| 99 | + * @throws InvalidDataTypeException |
|
| 100 | + */ |
|
| 101 | + public static function set_hooks_admin() |
|
| 102 | + { |
|
| 103 | + EED_Recaptcha::$config = EE_Registry::instance()->CFG->registration; |
|
| 104 | + EED_Recaptcha::set_definitions(); |
|
| 105 | + // use_captcha ? |
|
| 106 | + if ( |
|
| 107 | + EED_Recaptcha::useRecaptcha() |
|
| 108 | + && EED_Recaptcha::notPaymentOptionsRevisit() |
|
| 109 | + && EE_Registry::instance()->REQ->get('step', '') !== '' |
|
| 110 | + ) { |
|
| 111 | + EED_Recaptcha::enqueue_styles_and_scripts(); |
|
| 112 | + add_filter( |
|
| 113 | + 'FHEE__EED_Single_Page_Checkout__init___continue_reg', |
|
| 114 | + array('EED_Recaptcha', 'not_a_robot') |
|
| 115 | + ); |
|
| 116 | + add_filter( |
|
| 117 | + 'FHEE__EE_SPCO_Reg_Step__set_completed___completed', |
|
| 118 | + array('EED_Recaptcha', 'not_a_robot') |
|
| 119 | + ); |
|
| 120 | + add_filter( |
|
| 121 | + 'FHEE__EE_SPCO_JSON_Response___toString__JSON_response', |
|
| 122 | + array('EED_Recaptcha', 'recaptcha_response') |
|
| 123 | + ); |
|
| 124 | + } |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + |
|
| 128 | + /** |
|
| 129 | + * @return void |
|
| 130 | + */ |
|
| 131 | + public static function set_definitions() |
|
| 132 | + { |
|
| 133 | + if (is_user_logged_in()) { |
|
| 134 | + EED_Recaptcha::$_not_a_robot = true; |
|
| 135 | + } |
|
| 136 | + define( |
|
| 137 | + 'RECAPTCHA_BASE_PATH', |
|
| 138 | + rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS |
|
| 139 | + ); |
|
| 140 | + define('RECAPTCHA_BASE_URL', plugin_dir_url(__FILE__)); |
|
| 141 | + } |
|
| 142 | + |
|
| 143 | + |
|
| 144 | + /** |
|
| 145 | + * @return void |
|
| 146 | + */ |
|
| 147 | + public static function set_late_hooks() |
|
| 148 | + { |
|
| 149 | + add_filter( |
|
| 150 | + 'FHEE__Single_Page_Checkout__translate_js_strings__ajax_submit', |
|
| 151 | + array('EED_Recaptcha', 'not_a_robot') |
|
| 152 | + ); |
|
| 153 | + } |
|
| 154 | + |
|
| 155 | + |
|
| 156 | + /** |
|
| 157 | + * @return boolean |
|
| 158 | + */ |
|
| 159 | + public static function useRecaptcha() |
|
| 160 | + { |
|
| 161 | + return EED_Recaptcha::$config->use_captcha |
|
| 162 | + && EED_Recaptcha::$config->recaptcha_theme !== 'invisible'; |
|
| 163 | + } |
|
| 164 | + |
|
| 165 | + |
|
| 166 | + /** |
|
| 167 | + * @return boolean |
|
| 168 | + * @throws InvalidArgumentException |
|
| 169 | + * @throws InvalidInterfaceException |
|
| 170 | + * @throws InvalidDataTypeException |
|
| 171 | + */ |
|
| 172 | + public static function notPaymentOptionsRevisit() |
|
| 173 | + { |
|
| 174 | + return ! ( |
|
| 175 | + EE_Registry::instance()->REQ->get('step', '') === 'payment_options' |
|
| 176 | + && (boolean) EE_Registry::instance()->REQ->get('revisit', false) === true |
|
| 177 | + ); |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + |
|
| 181 | + /** |
|
| 182 | + * @return void |
|
| 183 | + * @throws InvalidArgumentException |
|
| 184 | + * @throws InvalidInterfaceException |
|
| 185 | + * @throws InvalidDataTypeException |
|
| 186 | + */ |
|
| 187 | + public static function enqueue_styles_and_scripts() |
|
| 188 | + { |
|
| 189 | + wp_register_script( |
|
| 190 | + 'espresso_recaptcha', |
|
| 191 | + RECAPTCHA_BASE_URL . 'scripts' . DS . 'espresso_recaptcha.js', |
|
| 192 | + array('single_page_checkout'), |
|
| 193 | + EVENT_ESPRESSO_VERSION, |
|
| 194 | + true |
|
| 195 | + ); |
|
| 196 | + wp_register_script( |
|
| 197 | + 'google_recaptcha', |
|
| 198 | + 'https://www.google.com/recaptcha/api.js?hl=' . EED_Recaptcha::$config->recaptcha_language, |
|
| 199 | + array('espresso_recaptcha'), |
|
| 200 | + EVENT_ESPRESSO_VERSION, |
|
| 201 | + true |
|
| 202 | + ); |
|
| 203 | + EE_Registry::$i18n_js_strings['no_SPCO_error'] = __( |
|
| 204 | + 'It appears the Single Page Checkout javascript was not loaded properly! Please refresh the page and try again or contact support.', |
|
| 205 | + 'event_espresso' |
|
| 206 | + ); |
|
| 207 | + EE_Registry::$i18n_js_strings['no_recaptcha_error'] = __( |
|
| 208 | + 'There appears to be a problem with the reCAPTCHA configuration! Please check the admin settings or contact support.', |
|
| 209 | + 'event_espresso' |
|
| 210 | + ); |
|
| 211 | + EE_Registry::$i18n_js_strings['recaptcha_fail'] = __( |
|
| 212 | + 'Please complete the anti-spam test before proceeding.', |
|
| 213 | + 'event_espresso' |
|
| 214 | + ); |
|
| 215 | + } |
|
| 216 | + |
|
| 217 | + |
|
| 218 | + /** |
|
| 219 | + * @param \WP $WP |
|
| 220 | + */ |
|
| 221 | + public function run($WP) |
|
| 222 | + { |
|
| 223 | + } |
|
| 224 | + |
|
| 225 | + |
|
| 226 | + /** |
|
| 227 | + * @return boolean |
|
| 228 | + * @throws InvalidArgumentException |
|
| 229 | + * @throws InvalidInterfaceException |
|
| 230 | + * @throws InvalidDataTypeException |
|
| 231 | + */ |
|
| 232 | + public static function not_a_robot() |
|
| 233 | + { |
|
| 234 | + $not_a_robot = is_bool(EED_Recaptcha::$_not_a_robot) |
|
| 235 | + ? EED_Recaptcha::$_not_a_robot |
|
| 236 | + : EED_Recaptcha::recaptcha_passed(); |
|
| 237 | + return $not_a_robot; |
|
| 238 | + } |
|
| 239 | + |
|
| 240 | + |
|
| 241 | + /** |
|
| 242 | + * @return void |
|
| 243 | + * @throws DomainException |
|
| 244 | + * @throws InvalidArgumentException |
|
| 245 | + * @throws InvalidInterfaceException |
|
| 246 | + * @throws InvalidDataTypeException |
|
| 247 | + */ |
|
| 248 | + public static function display_recaptcha() |
|
| 249 | + { |
|
| 250 | + // logged in means you have already passed a turing test of sorts |
|
| 251 | + if (is_user_logged_in()) { |
|
| 252 | + return; |
|
| 253 | + } |
|
| 254 | + // don't display if not using recaptcha or user is logged in |
|
| 255 | + if (EED_Recaptcha::useRecaptcha() && ! EED_Recaptcha::$_not_a_robot) { |
|
| 256 | + // only display if they have NOT passed the test yet |
|
| 257 | + EEH_Template::display_template( |
|
| 258 | + RECAPTCHA_BASE_PATH . DS . 'templates' . DS . 'recaptcha.template.php', |
|
| 259 | + array( |
|
| 260 | + 'recaptcha_publickey' => EED_Recaptcha::$config->recaptcha_publickey, |
|
| 261 | + 'recaptcha_theme' => EED_Recaptcha::$config->recaptcha_theme, |
|
| 262 | + 'recaptcha_type' => EED_Recaptcha::$config->recaptcha_type, |
|
| 263 | + ) |
|
| 264 | + ); |
|
| 265 | + wp_enqueue_script('google_recaptcha'); |
|
| 266 | + } |
|
| 267 | + } |
|
| 268 | + |
|
| 269 | + |
|
| 270 | + /** |
|
| 271 | + * @return array |
|
| 272 | + * @throws InvalidArgumentException |
|
| 273 | + * @throws InvalidInterfaceException |
|
| 274 | + * @throws InvalidDataTypeException |
|
| 275 | + */ |
|
| 276 | + public static function bypass_recaptcha_for_spco_load_payment_method() |
|
| 277 | + { |
|
| 278 | + return array( |
|
| 279 | + 'EESID' => EE_Registry::instance()->SSN->id(), |
|
| 280 | + 'step' => 'payment_options', |
|
| 281 | + 'action' => 'switch_spco_billing_form', |
|
| 282 | + ); |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + |
|
| 286 | + /** |
|
| 287 | + * @return boolean |
|
| 288 | + * @throws InvalidArgumentException |
|
| 289 | + * @throws InvalidInterfaceException |
|
| 290 | + * @throws InvalidDataTypeException |
|
| 291 | + */ |
|
| 292 | + public static function recaptcha_passed() |
|
| 293 | + { |
|
| 294 | + // logged in means you have already passed a turing test of sorts |
|
| 295 | + if (is_user_logged_in() || EED_Recaptcha::_bypass_recaptcha()) { |
|
| 296 | + return true; |
|
| 297 | + } |
|
| 298 | + // was test already passed? |
|
| 299 | + $recaptcha_passed = EE_Registry::instance()->SSN->get_session_data('recaptcha_passed'); |
|
| 300 | + $recaptcha_passed = filter_var($recaptcha_passed, FILTER_VALIDATE_BOOLEAN); |
|
| 301 | + // verify recaptcha |
|
| 302 | + EED_Recaptcha::_get_recaptcha_response(); |
|
| 303 | + if (! $recaptcha_passed && EED_Recaptcha::$_recaptcha_response) { |
|
| 304 | + $recaptcha_passed = EED_Recaptcha::_process_recaptcha_response(); |
|
| 305 | + EE_Registry::instance()->SSN->set_session_data(array('recaptcha_passed' => $recaptcha_passed)); |
|
| 306 | + } |
|
| 307 | + EED_Recaptcha::$_not_a_robot = $recaptcha_passed; |
|
| 308 | + return $recaptcha_passed; |
|
| 309 | + } |
|
| 310 | + |
|
| 311 | + |
|
| 312 | + /** |
|
| 313 | + * @param array $recaptcha_response |
|
| 314 | + * @return array |
|
| 315 | + */ |
|
| 316 | + public static function recaptcha_response($recaptcha_response = array()) |
|
| 317 | + { |
|
| 318 | + if (EED_Recaptcha::_bypass_recaptcha()) { |
|
| 319 | + $recaptcha_response['bypass_recaptcha'] = true; |
|
| 320 | + $recaptcha_response['recaptcha_passed'] = true; |
|
| 321 | + } else { |
|
| 322 | + $recaptcha_response['recaptcha_passed'] = EED_Recaptcha::$_not_a_robot; |
|
| 323 | + } |
|
| 324 | + return $recaptcha_response; |
|
| 325 | + } |
|
| 326 | + |
|
| 327 | + |
|
| 328 | + /** |
|
| 329 | + * @return boolean |
|
| 330 | + */ |
|
| 331 | + private static function _bypass_recaptcha() |
|
| 332 | + { |
|
| 333 | + // an array of key value pairs that must match exactly with the incoming request, |
|
| 334 | + // in order to bypass recaptcha for the current request ONLY |
|
| 335 | + $bypass_request_params_array = (array) apply_filters( |
|
| 336 | + 'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array', |
|
| 337 | + array() |
|
| 338 | + ); |
|
| 339 | + // does $bypass_request_params_array have any values ? |
|
| 340 | + if (empty($bypass_request_params_array)) { |
|
| 341 | + return false; |
|
| 342 | + } |
|
| 343 | + // initially set bypass to TRUE |
|
| 344 | + $bypass_recaptcha = true; |
|
| 345 | + foreach ($bypass_request_params_array as $key => $value) { |
|
| 346 | + // if $key is not found or value doesn't match exactly, then toggle bypass to FALSE, |
|
| 347 | + // otherwise carry over it's value. This way, one missed setting results in no bypass |
|
| 348 | + $bypass_recaptcha = isset($_REQUEST[ $key ]) && $_REQUEST[ $key ] === $value |
|
| 349 | + ? $bypass_recaptcha |
|
| 350 | + : false; |
|
| 351 | + } |
|
| 352 | + return $bypass_recaptcha; |
|
| 353 | + } |
|
| 354 | + |
|
| 355 | + |
|
| 356 | + /** |
|
| 357 | + * @return void |
|
| 358 | + * @throws InvalidArgumentException |
|
| 359 | + * @throws InvalidInterfaceException |
|
| 360 | + * @throws InvalidDataTypeException |
|
| 361 | + */ |
|
| 362 | + private static function _get_recaptcha_response() |
|
| 363 | + { |
|
| 364 | + EED_Recaptcha::$_recaptcha_response = EE_Registry::instance()->REQ->get( |
|
| 365 | + 'g-recaptcha-response', |
|
| 366 | + false |
|
| 367 | + ); |
|
| 368 | + } |
|
| 369 | + |
|
| 370 | + |
|
| 371 | + /** |
|
| 372 | + * @return boolean |
|
| 373 | + * @throws InvalidArgumentException |
|
| 374 | + * @throws InvalidInterfaceException |
|
| 375 | + * @throws InvalidDataTypeException |
|
| 376 | + */ |
|
| 377 | + private static function _process_recaptcha_response() |
|
| 378 | + { |
|
| 379 | + // verify library is loaded |
|
| 380 | + if (! class_exists('\ReCaptcha\ReCaptcha')) { |
|
| 381 | + require_once RECAPTCHA_BASE_PATH . DS . 'autoload.php'; |
|
| 382 | + } |
|
| 383 | + // The response from reCAPTCHA |
|
| 384 | + EED_Recaptcha::_get_recaptcha_response(); |
|
| 385 | + $recaptcha_response = EED_Recaptcha::$_recaptcha_response; |
|
| 386 | + // Was there a reCAPTCHA response? |
|
| 387 | + if ($recaptcha_response) { |
|
| 388 | + // if allow_url_fopen is Off, then set a different request method |
|
| 389 | + $request_method = ! ini_get('allow_url_fopen') ? new SocketPost() : null; |
|
| 390 | + $recaptcha = new ReCaptcha( |
|
| 391 | + EED_Recaptcha::$config->recaptcha_privatekey, |
|
| 392 | + $request_method |
|
| 393 | + ); |
|
| 394 | + $recaptcha_response = $recaptcha->verify( |
|
| 395 | + EED_Recaptcha::$_recaptcha_response, |
|
| 396 | + $_SERVER['REMOTE_ADDR'] |
|
| 397 | + ); |
|
| 398 | + } |
|
| 399 | + return $recaptcha_response instanceof Response && $recaptcha_response->isSuccess(); |
|
| 400 | + } |
|
| 401 | 401 | } |
| 402 | 402 | // End of file EED_Recaptcha.module.php |
| 403 | 403 | // Location: /modules/recaptcha/EED_Recaptcha.module.php |
@@ -135,7 +135,7 @@ discard block |
||
| 135 | 135 | } |
| 136 | 136 | define( |
| 137 | 137 | 'RECAPTCHA_BASE_PATH', |
| 138 | - rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS) . DS |
|
| 138 | + rtrim(str_replace(array('\\', '/'), DS, plugin_dir_path(__FILE__)), DS).DS |
|
| 139 | 139 | ); |
| 140 | 140 | define('RECAPTCHA_BASE_URL', plugin_dir_url(__FILE__)); |
| 141 | 141 | } |
@@ -188,19 +188,19 @@ discard block |
||
| 188 | 188 | { |
| 189 | 189 | wp_register_script( |
| 190 | 190 | 'espresso_recaptcha', |
| 191 | - RECAPTCHA_BASE_URL . 'scripts' . DS . 'espresso_recaptcha.js', |
|
| 191 | + RECAPTCHA_BASE_URL.'scripts'.DS.'espresso_recaptcha.js', |
|
| 192 | 192 | array('single_page_checkout'), |
| 193 | 193 | EVENT_ESPRESSO_VERSION, |
| 194 | 194 | true |
| 195 | 195 | ); |
| 196 | 196 | wp_register_script( |
| 197 | 197 | 'google_recaptcha', |
| 198 | - 'https://www.google.com/recaptcha/api.js?hl=' . EED_Recaptcha::$config->recaptcha_language, |
|
| 198 | + 'https://www.google.com/recaptcha/api.js?hl='.EED_Recaptcha::$config->recaptcha_language, |
|
| 199 | 199 | array('espresso_recaptcha'), |
| 200 | 200 | EVENT_ESPRESSO_VERSION, |
| 201 | 201 | true |
| 202 | 202 | ); |
| 203 | - EE_Registry::$i18n_js_strings['no_SPCO_error'] = __( |
|
| 203 | + EE_Registry::$i18n_js_strings['no_SPCO_error'] = __( |
|
| 204 | 204 | 'It appears the Single Page Checkout javascript was not loaded properly! Please refresh the page and try again or contact support.', |
| 205 | 205 | 'event_espresso' |
| 206 | 206 | ); |
@@ -208,7 +208,7 @@ discard block |
||
| 208 | 208 | 'There appears to be a problem with the reCAPTCHA configuration! Please check the admin settings or contact support.', |
| 209 | 209 | 'event_espresso' |
| 210 | 210 | ); |
| 211 | - EE_Registry::$i18n_js_strings['recaptcha_fail'] = __( |
|
| 211 | + EE_Registry::$i18n_js_strings['recaptcha_fail'] = __( |
|
| 212 | 212 | 'Please complete the anti-spam test before proceeding.', |
| 213 | 213 | 'event_espresso' |
| 214 | 214 | ); |
@@ -255,7 +255,7 @@ discard block |
||
| 255 | 255 | if (EED_Recaptcha::useRecaptcha() && ! EED_Recaptcha::$_not_a_robot) { |
| 256 | 256 | // only display if they have NOT passed the test yet |
| 257 | 257 | EEH_Template::display_template( |
| 258 | - RECAPTCHA_BASE_PATH . DS . 'templates' . DS . 'recaptcha.template.php', |
|
| 258 | + RECAPTCHA_BASE_PATH.DS.'templates'.DS.'recaptcha.template.php', |
|
| 259 | 259 | array( |
| 260 | 260 | 'recaptcha_publickey' => EED_Recaptcha::$config->recaptcha_publickey, |
| 261 | 261 | 'recaptcha_theme' => EED_Recaptcha::$config->recaptcha_theme, |
@@ -300,7 +300,7 @@ discard block |
||
| 300 | 300 | $recaptcha_passed = filter_var($recaptcha_passed, FILTER_VALIDATE_BOOLEAN); |
| 301 | 301 | // verify recaptcha |
| 302 | 302 | EED_Recaptcha::_get_recaptcha_response(); |
| 303 | - if (! $recaptcha_passed && EED_Recaptcha::$_recaptcha_response) { |
|
| 303 | + if ( ! $recaptcha_passed && EED_Recaptcha::$_recaptcha_response) { |
|
| 304 | 304 | $recaptcha_passed = EED_Recaptcha::_process_recaptcha_response(); |
| 305 | 305 | EE_Registry::instance()->SSN->set_session_data(array('recaptcha_passed' => $recaptcha_passed)); |
| 306 | 306 | } |
@@ -345,7 +345,7 @@ discard block |
||
| 345 | 345 | foreach ($bypass_request_params_array as $key => $value) { |
| 346 | 346 | // if $key is not found or value doesn't match exactly, then toggle bypass to FALSE, |
| 347 | 347 | // otherwise carry over it's value. This way, one missed setting results in no bypass |
| 348 | - $bypass_recaptcha = isset($_REQUEST[ $key ]) && $_REQUEST[ $key ] === $value |
|
| 348 | + $bypass_recaptcha = isset($_REQUEST[$key]) && $_REQUEST[$key] === $value |
|
| 349 | 349 | ? $bypass_recaptcha |
| 350 | 350 | : false; |
| 351 | 351 | } |
@@ -377,8 +377,8 @@ discard block |
||
| 377 | 377 | private static function _process_recaptcha_response() |
| 378 | 378 | { |
| 379 | 379 | // verify library is loaded |
| 380 | - if (! class_exists('\ReCaptcha\ReCaptcha')) { |
|
| 381 | - require_once RECAPTCHA_BASE_PATH . DS . 'autoload.php'; |
|
| 380 | + if ( ! class_exists('\ReCaptcha\ReCaptcha')) { |
|
| 381 | + require_once RECAPTCHA_BASE_PATH.DS.'autoload.php'; |
|
| 382 | 382 | } |
| 383 | 383 | // The response from reCAPTCHA |
| 384 | 384 | EED_Recaptcha::_get_recaptcha_response(); |
@@ -1,5 +1,5 @@ discard block |
||
| 1 | 1 | <?php if (! defined('EVENT_ESPRESSO_VERSION')) { |
| 2 | - exit('No direct script access allowed'); |
|
| 2 | + exit('No direct script access allowed'); |
|
| 3 | 3 | } |
| 4 | 4 | |
| 5 | 5 | |
@@ -16,673 +16,673 @@ discard block |
||
| 16 | 16 | abstract class EE_SPCO_Reg_Step |
| 17 | 17 | { |
| 18 | 18 | |
| 19 | - /** |
|
| 20 | - * $_completed - TRUE if this step has fully completed it's duties |
|
| 21 | - * |
|
| 22 | - * @access protected |
|
| 23 | - * @type bool $_completed |
|
| 24 | - */ |
|
| 25 | - protected $_completed = false; |
|
| 26 | - |
|
| 27 | - /** |
|
| 28 | - * $_is_current_step - TRUE if this is the current step |
|
| 29 | - * |
|
| 30 | - * @access protected |
|
| 31 | - * @type bool $_is_current_step |
|
| 32 | - */ |
|
| 33 | - protected $_is_current_step = false; |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * $_order - when the reg step should be run relative to other steps |
|
| 37 | - * |
|
| 38 | - * @access protected |
|
| 39 | - * @type int $_template |
|
| 40 | - */ |
|
| 41 | - protected $_order = 0; |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * $_slug - URL param for this step |
|
| 45 | - * |
|
| 46 | - * @access protected |
|
| 47 | - * @type string $_slug |
|
| 48 | - */ |
|
| 49 | - protected $_slug; |
|
| 50 | - |
|
| 51 | - /** |
|
| 52 | - * $_name - Step Name - translatable string |
|
| 53 | - * |
|
| 54 | - * @access protected |
|
| 55 | - * @type string $_slug |
|
| 56 | - */ |
|
| 57 | - protected $_name; |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * $_submit_button_text - translatable string that appears on this step's submit button |
|
| 61 | - * |
|
| 62 | - * @access protected |
|
| 63 | - * @type string $_slug |
|
| 64 | - */ |
|
| 65 | - protected $_submit_button_text; |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * $_template - template name |
|
| 69 | - * |
|
| 70 | - * @access protected |
|
| 71 | - * @type string $_template |
|
| 72 | - */ |
|
| 73 | - protected $_template; |
|
| 74 | - |
|
| 75 | - /** |
|
| 76 | - * $_reg_form_name - the form input name and id attribute |
|
| 77 | - * |
|
| 78 | - * @access protected |
|
| 79 | - * @var string $_reg_form_name |
|
| 80 | - */ |
|
| 81 | - protected $_reg_form_name; |
|
| 82 | - |
|
| 83 | - /** |
|
| 84 | - * $_success_message - text to display upon successful form submission |
|
| 85 | - * |
|
| 86 | - * @access private |
|
| 87 | - * @var string $_success_message |
|
| 88 | - */ |
|
| 89 | - protected $_success_message; |
|
| 90 | - |
|
| 91 | - /** |
|
| 92 | - * $_instructions - a brief description of how to complete the reg step. |
|
| 93 | - * Usually displayed in conjunction with the previous step's success message. |
|
| 94 | - * |
|
| 95 | - * @access private |
|
| 96 | - * @var string $_instructions |
|
| 97 | - */ |
|
| 98 | - protected $_instructions; |
|
| 99 | - |
|
| 100 | - /** |
|
| 101 | - * $_valid_data - the normalized and validated data for this step |
|
| 102 | - * |
|
| 103 | - * @access public |
|
| 104 | - * @var array $_valid_data |
|
| 105 | - */ |
|
| 106 | - protected $_valid_data = array(); |
|
| 107 | - |
|
| 108 | - /** |
|
| 109 | - * $reg_form - the registration form for this step |
|
| 110 | - * |
|
| 111 | - * @access public |
|
| 112 | - * @var EE_Form_Section_Proper $reg_form |
|
| 113 | - */ |
|
| 114 | - public $reg_form; |
|
| 115 | - |
|
| 116 | - /** |
|
| 117 | - * $checkout - EE_Checkout object for handling the properties of the current checkout process |
|
| 118 | - * |
|
| 119 | - * @access public |
|
| 120 | - * @var EE_Checkout $checkout |
|
| 121 | - */ |
|
| 122 | - public $checkout; |
|
| 123 | - |
|
| 124 | - |
|
| 125 | - |
|
| 126 | - /** |
|
| 127 | - * @return void |
|
| 128 | - */ |
|
| 129 | - abstract public function translate_js_strings(); |
|
| 130 | - |
|
| 131 | - |
|
| 19 | + /** |
|
| 20 | + * $_completed - TRUE if this step has fully completed it's duties |
|
| 21 | + * |
|
| 22 | + * @access protected |
|
| 23 | + * @type bool $_completed |
|
| 24 | + */ |
|
| 25 | + protected $_completed = false; |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * $_is_current_step - TRUE if this is the current step |
|
| 29 | + * |
|
| 30 | + * @access protected |
|
| 31 | + * @type bool $_is_current_step |
|
| 32 | + */ |
|
| 33 | + protected $_is_current_step = false; |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * $_order - when the reg step should be run relative to other steps |
|
| 37 | + * |
|
| 38 | + * @access protected |
|
| 39 | + * @type int $_template |
|
| 40 | + */ |
|
| 41 | + protected $_order = 0; |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * $_slug - URL param for this step |
|
| 45 | + * |
|
| 46 | + * @access protected |
|
| 47 | + * @type string $_slug |
|
| 48 | + */ |
|
| 49 | + protected $_slug; |
|
| 50 | + |
|
| 51 | + /** |
|
| 52 | + * $_name - Step Name - translatable string |
|
| 53 | + * |
|
| 54 | + * @access protected |
|
| 55 | + * @type string $_slug |
|
| 56 | + */ |
|
| 57 | + protected $_name; |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * $_submit_button_text - translatable string that appears on this step's submit button |
|
| 61 | + * |
|
| 62 | + * @access protected |
|
| 63 | + * @type string $_slug |
|
| 64 | + */ |
|
| 65 | + protected $_submit_button_text; |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * $_template - template name |
|
| 69 | + * |
|
| 70 | + * @access protected |
|
| 71 | + * @type string $_template |
|
| 72 | + */ |
|
| 73 | + protected $_template; |
|
| 74 | + |
|
| 75 | + /** |
|
| 76 | + * $_reg_form_name - the form input name and id attribute |
|
| 77 | + * |
|
| 78 | + * @access protected |
|
| 79 | + * @var string $_reg_form_name |
|
| 80 | + */ |
|
| 81 | + protected $_reg_form_name; |
|
| 82 | + |
|
| 83 | + /** |
|
| 84 | + * $_success_message - text to display upon successful form submission |
|
| 85 | + * |
|
| 86 | + * @access private |
|
| 87 | + * @var string $_success_message |
|
| 88 | + */ |
|
| 89 | + protected $_success_message; |
|
| 90 | + |
|
| 91 | + /** |
|
| 92 | + * $_instructions - a brief description of how to complete the reg step. |
|
| 93 | + * Usually displayed in conjunction with the previous step's success message. |
|
| 94 | + * |
|
| 95 | + * @access private |
|
| 96 | + * @var string $_instructions |
|
| 97 | + */ |
|
| 98 | + protected $_instructions; |
|
| 99 | + |
|
| 100 | + /** |
|
| 101 | + * $_valid_data - the normalized and validated data for this step |
|
| 102 | + * |
|
| 103 | + * @access public |
|
| 104 | + * @var array $_valid_data |
|
| 105 | + */ |
|
| 106 | + protected $_valid_data = array(); |
|
| 107 | + |
|
| 108 | + /** |
|
| 109 | + * $reg_form - the registration form for this step |
|
| 110 | + * |
|
| 111 | + * @access public |
|
| 112 | + * @var EE_Form_Section_Proper $reg_form |
|
| 113 | + */ |
|
| 114 | + public $reg_form; |
|
| 115 | + |
|
| 116 | + /** |
|
| 117 | + * $checkout - EE_Checkout object for handling the properties of the current checkout process |
|
| 118 | + * |
|
| 119 | + * @access public |
|
| 120 | + * @var EE_Checkout $checkout |
|
| 121 | + */ |
|
| 122 | + public $checkout; |
|
| 123 | + |
|
| 124 | + |
|
| 125 | + |
|
| 126 | + /** |
|
| 127 | + * @return void |
|
| 128 | + */ |
|
| 129 | + abstract public function translate_js_strings(); |
|
| 130 | + |
|
| 131 | + |
|
| 132 | 132 | |
| 133 | - /** |
|
| 134 | - * @return void |
|
| 135 | - */ |
|
| 136 | - abstract public function enqueue_styles_and_scripts(); |
|
| 137 | - |
|
| 138 | - |
|
| 139 | - |
|
| 140 | - /** |
|
| 141 | - * @return boolean |
|
| 142 | - */ |
|
| 143 | - abstract public function initialize_reg_step(); |
|
| 144 | - |
|
| 145 | - |
|
| 146 | - |
|
| 147 | - /** |
|
| 148 | - * @return string |
|
| 149 | - */ |
|
| 150 | - abstract public function generate_reg_form(); |
|
| 151 | - |
|
| 152 | - |
|
| 153 | - |
|
| 154 | - /** |
|
| 155 | - * @return boolean |
|
| 156 | - */ |
|
| 157 | - abstract public function process_reg_step(); |
|
| 158 | - |
|
| 159 | - |
|
| 160 | - |
|
| 161 | - /** |
|
| 162 | - * @return boolean |
|
| 163 | - */ |
|
| 164 | - abstract public function update_reg_step(); |
|
| 165 | - |
|
| 166 | - |
|
| 167 | - |
|
| 168 | - /** |
|
| 169 | - * @return boolean |
|
| 170 | - */ |
|
| 171 | - public function completed() |
|
| 172 | - { |
|
| 173 | - return $this->_completed; |
|
| 174 | - } |
|
| 133 | + /** |
|
| 134 | + * @return void |
|
| 135 | + */ |
|
| 136 | + abstract public function enqueue_styles_and_scripts(); |
|
| 137 | + |
|
| 138 | + |
|
| 139 | + |
|
| 140 | + /** |
|
| 141 | + * @return boolean |
|
| 142 | + */ |
|
| 143 | + abstract public function initialize_reg_step(); |
|
| 144 | + |
|
| 145 | + |
|
| 146 | + |
|
| 147 | + /** |
|
| 148 | + * @return string |
|
| 149 | + */ |
|
| 150 | + abstract public function generate_reg_form(); |
|
| 151 | + |
|
| 152 | + |
|
| 153 | + |
|
| 154 | + /** |
|
| 155 | + * @return boolean |
|
| 156 | + */ |
|
| 157 | + abstract public function process_reg_step(); |
|
| 158 | + |
|
| 159 | + |
|
| 160 | + |
|
| 161 | + /** |
|
| 162 | + * @return boolean |
|
| 163 | + */ |
|
| 164 | + abstract public function update_reg_step(); |
|
| 165 | + |
|
| 166 | + |
|
| 167 | + |
|
| 168 | + /** |
|
| 169 | + * @return boolean |
|
| 170 | + */ |
|
| 171 | + public function completed() |
|
| 172 | + { |
|
| 173 | + return $this->_completed; |
|
| 174 | + } |
|
| 175 | 175 | |
| 176 | 176 | |
| 177 | 177 | |
| 178 | - /** |
|
| 179 | - * set_completed - toggles $_completed to TRUE |
|
| 180 | - */ |
|
| 181 | - public function set_completed() |
|
| 182 | - { |
|
| 183 | - // DEBUG LOG |
|
| 184 | - //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ ); |
|
| 185 | - $this->_completed = apply_filters('FHEE__EE_SPCO_Reg_Step__set_completed___completed', true, $this); |
|
| 186 | - } |
|
| 178 | + /** |
|
| 179 | + * set_completed - toggles $_completed to TRUE |
|
| 180 | + */ |
|
| 181 | + public function set_completed() |
|
| 182 | + { |
|
| 183 | + // DEBUG LOG |
|
| 184 | + //$this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ ); |
|
| 185 | + $this->_completed = apply_filters('FHEE__EE_SPCO_Reg_Step__set_completed___completed', true, $this); |
|
| 186 | + } |
|
| 187 | 187 | |
| 188 | 188 | |
| 189 | 189 | |
| 190 | - /** |
|
| 191 | - * set_completed - toggles $_completed to FALSE |
|
| 192 | - */ |
|
| 193 | - public function set_not_completed() |
|
| 194 | - { |
|
| 195 | - $this->_completed = false; |
|
| 196 | - } |
|
| 190 | + /** |
|
| 191 | + * set_completed - toggles $_completed to FALSE |
|
| 192 | + */ |
|
| 193 | + public function set_not_completed() |
|
| 194 | + { |
|
| 195 | + $this->_completed = false; |
|
| 196 | + } |
|
| 197 | 197 | |
| 198 | 198 | |
| 199 | 199 | |
| 200 | - /** |
|
| 201 | - * @return string |
|
| 202 | - */ |
|
| 203 | - public function name() |
|
| 204 | - { |
|
| 205 | - return $this->_name; |
|
| 206 | - } |
|
| 200 | + /** |
|
| 201 | + * @return string |
|
| 202 | + */ |
|
| 203 | + public function name() |
|
| 204 | + { |
|
| 205 | + return $this->_name; |
|
| 206 | + } |
|
| 207 | 207 | |
| 208 | 208 | |
| 209 | 209 | |
| 210 | - /** |
|
| 211 | - * @return string |
|
| 212 | - */ |
|
| 213 | - public function slug() |
|
| 214 | - { |
|
| 215 | - return $this->_slug; |
|
| 216 | - } |
|
| 210 | + /** |
|
| 211 | + * @return string |
|
| 212 | + */ |
|
| 213 | + public function slug() |
|
| 214 | + { |
|
| 215 | + return $this->_slug; |
|
| 216 | + } |
|
| 217 | 217 | |
| 218 | 218 | |
| 219 | 219 | |
| 220 | - /** |
|
| 221 | - * submit_button_text |
|
| 222 | - * the text that appears on the reg step form submit button |
|
| 223 | - * |
|
| 224 | - * @return string |
|
| 225 | - */ |
|
| 226 | - public function submit_button_text() |
|
| 227 | - { |
|
| 228 | - return $this->_submit_button_text; |
|
| 229 | - } |
|
| 220 | + /** |
|
| 221 | + * submit_button_text |
|
| 222 | + * the text that appears on the reg step form submit button |
|
| 223 | + * |
|
| 224 | + * @return string |
|
| 225 | + */ |
|
| 226 | + public function submit_button_text() |
|
| 227 | + { |
|
| 228 | + return $this->_submit_button_text; |
|
| 229 | + } |
|
| 230 | 230 | |
| 231 | 231 | |
| 232 | 232 | |
| 233 | - /** |
|
| 234 | - * set_submit_button_text |
|
| 235 | - * sets the text that appears on the reg step form submit button |
|
| 236 | - * |
|
| 237 | - * @param string $submit_button_text |
|
| 238 | - */ |
|
| 239 | - public function set_submit_button_text($submit_button_text = '') |
|
| 240 | - { |
|
| 241 | - if (! empty($submit_button_text)) { |
|
| 242 | - $this->_submit_button_text = $submit_button_text; |
|
| 243 | - } else if ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
| 244 | - if ($this->checkout->revisit) { |
|
| 245 | - $this->_submit_button_text = sprintf( |
|
| 246 | - __('Update %s', 'event_espresso'), |
|
| 247 | - $this->checkout->current_step->name() |
|
| 248 | - ); |
|
| 249 | - } else { |
|
| 250 | - $this->_submit_button_text = sprintf( |
|
| 251 | - __('Proceed to %s', 'event_espresso'), |
|
| 252 | - $this->checkout->next_step->name() |
|
| 253 | - ); |
|
| 254 | - } |
|
| 255 | - } |
|
| 256 | - // filters the submit button text |
|
| 257 | - $this->_submit_button_text = apply_filters( |
|
| 258 | - 'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text', |
|
| 259 | - $this->_submit_button_text, |
|
| 260 | - $this->checkout |
|
| 261 | - ); |
|
| 262 | - } |
|
| 233 | + /** |
|
| 234 | + * set_submit_button_text |
|
| 235 | + * sets the text that appears on the reg step form submit button |
|
| 236 | + * |
|
| 237 | + * @param string $submit_button_text |
|
| 238 | + */ |
|
| 239 | + public function set_submit_button_text($submit_button_text = '') |
|
| 240 | + { |
|
| 241 | + if (! empty($submit_button_text)) { |
|
| 242 | + $this->_submit_button_text = $submit_button_text; |
|
| 243 | + } else if ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
| 244 | + if ($this->checkout->revisit) { |
|
| 245 | + $this->_submit_button_text = sprintf( |
|
| 246 | + __('Update %s', 'event_espresso'), |
|
| 247 | + $this->checkout->current_step->name() |
|
| 248 | + ); |
|
| 249 | + } else { |
|
| 250 | + $this->_submit_button_text = sprintf( |
|
| 251 | + __('Proceed to %s', 'event_espresso'), |
|
| 252 | + $this->checkout->next_step->name() |
|
| 253 | + ); |
|
| 254 | + } |
|
| 255 | + } |
|
| 256 | + // filters the submit button text |
|
| 257 | + $this->_submit_button_text = apply_filters( |
|
| 258 | + 'FHEE__EE_SPCO_Reg_Step__set_submit_button_text___submit_button_text', |
|
| 259 | + $this->_submit_button_text, |
|
| 260 | + $this->checkout |
|
| 261 | + ); |
|
| 262 | + } |
|
| 263 | 263 | |
| 264 | 264 | |
| 265 | 265 | |
| 266 | - /** |
|
| 267 | - * @param boolean $is_current_step |
|
| 268 | - */ |
|
| 269 | - public function set_is_current_step($is_current_step) |
|
| 270 | - { |
|
| 271 | - $this->_is_current_step = $is_current_step; |
|
| 272 | - } |
|
| 266 | + /** |
|
| 267 | + * @param boolean $is_current_step |
|
| 268 | + */ |
|
| 269 | + public function set_is_current_step($is_current_step) |
|
| 270 | + { |
|
| 271 | + $this->_is_current_step = $is_current_step; |
|
| 272 | + } |
|
| 273 | 273 | |
| 274 | 274 | |
| 275 | 275 | |
| 276 | - /** |
|
| 277 | - * @return boolean |
|
| 278 | - */ |
|
| 279 | - public function is_current_step() |
|
| 280 | - { |
|
| 281 | - return $this->_is_current_step; |
|
| 282 | - } |
|
| 276 | + /** |
|
| 277 | + * @return boolean |
|
| 278 | + */ |
|
| 279 | + public function is_current_step() |
|
| 280 | + { |
|
| 281 | + return $this->_is_current_step; |
|
| 282 | + } |
|
| 283 | 283 | |
| 284 | 284 | |
| 285 | 285 | |
| 286 | - /** |
|
| 287 | - * @return boolean |
|
| 288 | - */ |
|
| 289 | - public function is_final_step() |
|
| 290 | - { |
|
| 291 | - return $this instanceof EE_SPCO_Reg_Step_Finalize_Registration ? true : false; |
|
| 292 | - } |
|
| 286 | + /** |
|
| 287 | + * @return boolean |
|
| 288 | + */ |
|
| 289 | + public function is_final_step() |
|
| 290 | + { |
|
| 291 | + return $this instanceof EE_SPCO_Reg_Step_Finalize_Registration ? true : false; |
|
| 292 | + } |
|
| 293 | 293 | |
| 294 | 294 | |
| 295 | 295 | |
| 296 | - /** |
|
| 297 | - * @param int $order |
|
| 298 | - */ |
|
| 299 | - public function set_order($order) |
|
| 300 | - { |
|
| 301 | - $this->_order = $order; |
|
| 302 | - } |
|
| 303 | - |
|
| 304 | - |
|
| 296 | + /** |
|
| 297 | + * @param int $order |
|
| 298 | + */ |
|
| 299 | + public function set_order($order) |
|
| 300 | + { |
|
| 301 | + $this->_order = $order; |
|
| 302 | + } |
|
| 303 | + |
|
| 304 | + |
|
| 305 | 305 | |
| 306 | - /** |
|
| 307 | - * @return int |
|
| 308 | - */ |
|
| 309 | - public function order() |
|
| 310 | - { |
|
| 311 | - return $this->_order; |
|
| 312 | - } |
|
| 313 | - |
|
| 314 | - |
|
| 315 | - |
|
| 316 | - /** |
|
| 317 | - * @return string |
|
| 318 | - */ |
|
| 319 | - public function template() |
|
| 320 | - { |
|
| 321 | - return $this->_template; |
|
| 322 | - } |
|
| 323 | - |
|
| 324 | - |
|
| 325 | - |
|
| 326 | - /** |
|
| 327 | - * @return string |
|
| 328 | - */ |
|
| 329 | - public function success_message() |
|
| 330 | - { |
|
| 331 | - return $this->_success_message; |
|
| 332 | - } |
|
| 333 | - |
|
| 334 | - |
|
| 335 | - |
|
| 336 | - /** |
|
| 337 | - * _set_success_message |
|
| 338 | - * |
|
| 339 | - * @param string $success_message |
|
| 340 | - */ |
|
| 341 | - protected function _set_success_message($success_message) |
|
| 342 | - { |
|
| 343 | - $this->_success_message = $success_message; |
|
| 344 | - } |
|
| 345 | - |
|
| 346 | - |
|
| 347 | - |
|
| 348 | - /** |
|
| 349 | - * _reset_success_message |
|
| 350 | - * |
|
| 351 | - * @return void |
|
| 352 | - */ |
|
| 353 | - protected function _reset_success_message() |
|
| 354 | - { |
|
| 355 | - $this->_success_message = ''; |
|
| 356 | - } |
|
| 306 | + /** |
|
| 307 | + * @return int |
|
| 308 | + */ |
|
| 309 | + public function order() |
|
| 310 | + { |
|
| 311 | + return $this->_order; |
|
| 312 | + } |
|
| 313 | + |
|
| 314 | + |
|
| 315 | + |
|
| 316 | + /** |
|
| 317 | + * @return string |
|
| 318 | + */ |
|
| 319 | + public function template() |
|
| 320 | + { |
|
| 321 | + return $this->_template; |
|
| 322 | + } |
|
| 323 | + |
|
| 324 | + |
|
| 325 | + |
|
| 326 | + /** |
|
| 327 | + * @return string |
|
| 328 | + */ |
|
| 329 | + public function success_message() |
|
| 330 | + { |
|
| 331 | + return $this->_success_message; |
|
| 332 | + } |
|
| 333 | + |
|
| 334 | + |
|
| 335 | + |
|
| 336 | + /** |
|
| 337 | + * _set_success_message |
|
| 338 | + * |
|
| 339 | + * @param string $success_message |
|
| 340 | + */ |
|
| 341 | + protected function _set_success_message($success_message) |
|
| 342 | + { |
|
| 343 | + $this->_success_message = $success_message; |
|
| 344 | + } |
|
| 345 | + |
|
| 346 | + |
|
| 347 | + |
|
| 348 | + /** |
|
| 349 | + * _reset_success_message |
|
| 350 | + * |
|
| 351 | + * @return void |
|
| 352 | + */ |
|
| 353 | + protected function _reset_success_message() |
|
| 354 | + { |
|
| 355 | + $this->_success_message = ''; |
|
| 356 | + } |
|
| 357 | 357 | |
| 358 | 358 | |
| 359 | 359 | |
| 360 | - /** |
|
| 361 | - * @return string |
|
| 362 | - */ |
|
| 363 | - public function _instructions() |
|
| 364 | - { |
|
| 365 | - return $this->_instructions; |
|
| 366 | - } |
|
| 367 | - |
|
| 368 | - |
|
| 369 | - |
|
| 370 | - /** |
|
| 371 | - * @param string $instructions |
|
| 372 | - */ |
|
| 373 | - public function set_instructions($instructions) |
|
| 374 | - { |
|
| 375 | - $this->_instructions = apply_filters( |
|
| 376 | - 'FHEE__EE_SPCO_Reg_Step__set_instructions__instructions', |
|
| 377 | - $instructions, |
|
| 378 | - $this |
|
| 379 | - ); |
|
| 380 | - } |
|
| 381 | - |
|
| 382 | - |
|
| 383 | - |
|
| 384 | - /** |
|
| 385 | - * @param array $valid_data |
|
| 386 | - */ |
|
| 387 | - public function set_valid_data($valid_data) |
|
| 388 | - { |
|
| 389 | - $this->_valid_data = $valid_data; |
|
| 390 | - } |
|
| 391 | - |
|
| 392 | - |
|
| 393 | - |
|
| 394 | - /** |
|
| 395 | - * @return array |
|
| 396 | - */ |
|
| 397 | - public function valid_data() |
|
| 398 | - { |
|
| 399 | - if (empty($this->_valid_data)) { |
|
| 400 | - $this->_valid_data = $this->reg_form->valid_data(); |
|
| 401 | - } |
|
| 402 | - return $this->_valid_data; |
|
| 403 | - } |
|
| 404 | - |
|
| 405 | - |
|
| 406 | - |
|
| 407 | - /** |
|
| 408 | - * @return string |
|
| 409 | - */ |
|
| 410 | - public function reg_form_name() |
|
| 411 | - { |
|
| 412 | - if (empty($this->_reg_form_name)) { |
|
| 413 | - $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form'); |
|
| 414 | - } |
|
| 415 | - return $this->_reg_form_name; |
|
| 416 | - } |
|
| 417 | - |
|
| 418 | - |
|
| 419 | - |
|
| 420 | - /** |
|
| 421 | - * @param string $reg_form_name |
|
| 422 | - */ |
|
| 423 | - protected function set_reg_form_name($reg_form_name) |
|
| 424 | - { |
|
| 425 | - $this->_reg_form_name = $reg_form_name; |
|
| 426 | - } |
|
| 427 | - |
|
| 428 | - |
|
| 429 | - |
|
| 430 | - /** |
|
| 431 | - * reg_step_url |
|
| 432 | - * |
|
| 433 | - * @param string $action |
|
| 434 | - * @return string |
|
| 435 | - */ |
|
| 436 | - public function reg_step_url($action = '') |
|
| 437 | - { |
|
| 438 | - $query_args = array('step' => $this->slug()); |
|
| 439 | - if (! empty($action)) { |
|
| 440 | - $query_args['action'] = $action; |
|
| 441 | - } |
|
| 442 | - // final step has no display |
|
| 443 | - if ($this instanceof EE_SPCO_Reg_Step_Finalize_Registration && $action === 'display_spco_reg_step') { |
|
| 444 | - $query_args['action'] = 'process_reg_step'; |
|
| 445 | - } |
|
| 446 | - if ($this->checkout->revisit) { |
|
| 447 | - $query_args['revisit'] = true; |
|
| 448 | - } |
|
| 449 | - if ($this->checkout->reg_url_link) { |
|
| 450 | - $query_args['e_reg_url_link'] = $this->checkout->reg_url_link; |
|
| 451 | - } |
|
| 452 | - return add_query_arg($query_args, $this->checkout->reg_page_base_url); |
|
| 453 | - } |
|
| 454 | - |
|
| 455 | - |
|
| 456 | - |
|
| 457 | - /** |
|
| 458 | - * creates the default hidden inputs section |
|
| 459 | - * |
|
| 460 | - * @return EE_Form_Section_Proper |
|
| 461 | - * @throws \EE_Error |
|
| 462 | - */ |
|
| 463 | - public function reg_step_hidden_inputs() |
|
| 464 | - { |
|
| 465 | - // hidden inputs for admin registrations |
|
| 466 | - if ($this->checkout->admin_request) { |
|
| 467 | - return new EE_Form_Section_Proper( |
|
| 468 | - array( |
|
| 469 | - 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
| 470 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
| 471 | - 'subsections' => array( |
|
| 472 | - 'next_step' => new EE_Fixed_Hidden_Input( |
|
| 473 | - array( |
|
| 474 | - 'html_name' => 'next_step', |
|
| 475 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
| 476 | - 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
| 477 | - ? $this->checkout->next_step->slug() |
|
| 478 | - : '', |
|
| 479 | - ) |
|
| 480 | - ), |
|
| 481 | - ), |
|
| 482 | - ) |
|
| 483 | - ); |
|
| 484 | - } |
|
| 485 | - // hidden inputs for frontend registrations |
|
| 486 | - return new EE_Form_Section_Proper( |
|
| 487 | - array( |
|
| 488 | - 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
| 489 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
| 490 | - 'subsections' => array( |
|
| 491 | - 'action' => new EE_Fixed_Hidden_Input( |
|
| 492 | - array( |
|
| 493 | - 'html_name' => 'action', |
|
| 494 | - 'html_id' => 'spco-' . $this->slug() . '-action', |
|
| 495 | - 'default' => apply_filters( |
|
| 496 | - 'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action', |
|
| 497 | - empty($this->checkout->reg_url_link) |
|
| 498 | - ? 'process_reg_step' |
|
| 499 | - : 'update_reg_step', |
|
| 500 | - $this |
|
| 501 | - ), |
|
| 502 | - ) |
|
| 503 | - ), |
|
| 504 | - 'next_step' => new EE_Fixed_Hidden_Input( |
|
| 505 | - array( |
|
| 506 | - 'html_name' => 'next_step', |
|
| 507 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
| 508 | - 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
| 509 | - ? $this->checkout->next_step->slug() |
|
| 510 | - : '', |
|
| 511 | - ) |
|
| 512 | - ), |
|
| 513 | - 'e_reg_url_link' => new EE_Fixed_Hidden_Input( |
|
| 514 | - array( |
|
| 515 | - 'html_name' => 'e_reg_url_link', |
|
| 516 | - 'html_id' => 'spco-reg_url_link', |
|
| 517 | - 'default' => $this->checkout->reg_url_link, |
|
| 518 | - ) |
|
| 519 | - ), |
|
| 520 | - 'revisit' => new EE_Fixed_Hidden_Input( |
|
| 521 | - array( |
|
| 522 | - 'html_name' => 'revisit', |
|
| 523 | - 'html_id' => 'spco-revisit', |
|
| 524 | - 'default' => $this->checkout->revisit, |
|
| 525 | - ) |
|
| 526 | - ), |
|
| 527 | - ), |
|
| 528 | - ) |
|
| 529 | - ); |
|
| 530 | - } |
|
| 531 | - |
|
| 532 | - |
|
| 533 | - |
|
| 534 | - /** |
|
| 535 | - * generate_reg_form_for_actions |
|
| 536 | - * |
|
| 537 | - * @param array $actions |
|
| 538 | - * @return void |
|
| 539 | - */ |
|
| 540 | - public function generate_reg_form_for_actions($actions = array()) |
|
| 541 | - { |
|
| 542 | - $actions = array_merge( |
|
| 543 | - array( |
|
| 544 | - 'generate_reg_form', |
|
| 545 | - 'display_spco_reg_step', |
|
| 546 | - 'process_reg_step', |
|
| 547 | - 'update_reg_step', |
|
| 548 | - ), |
|
| 549 | - $actions |
|
| 550 | - ); |
|
| 551 | - $this->checkout->generate_reg_form = in_array($this->checkout->action, $actions, true) ? true : false; |
|
| 552 | - } |
|
| 553 | - |
|
| 554 | - |
|
| 555 | - |
|
| 556 | - /** |
|
| 557 | - * @return string |
|
| 558 | - * @throws \EE_Error |
|
| 559 | - */ |
|
| 560 | - public function display_reg_form() |
|
| 561 | - { |
|
| 562 | - $html = ''; |
|
| 563 | - if ($this->reg_form instanceof EE_Form_Section_Proper) { |
|
| 564 | - do_action('AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', $this->reg_form, $this); |
|
| 565 | - $html .= ! $this->checkout->admin_request ? $this->reg_form->form_open($this->reg_step_url()) : ''; |
|
| 566 | - if (EE_Registry::instance()->REQ->ajax) { |
|
| 567 | - $this->reg_form->localize_validation_rules(); |
|
| 568 | - $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization()); |
|
| 569 | - } |
|
| 570 | - $html .= $this->reg_form->get_html(); |
|
| 571 | - $html .= ! $this->checkout->admin_request ? $this->reg_step_submit_button() : ''; |
|
| 572 | - $html .= ! $this->checkout->admin_request ? $this->reg_form->form_close() : ''; |
|
| 573 | - } |
|
| 574 | - return $html; |
|
| 575 | - } |
|
| 576 | - |
|
| 577 | - |
|
| 578 | - |
|
| 579 | - /** |
|
| 580 | - * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
| 581 | - * |
|
| 582 | - * @return string |
|
| 583 | - * @throws \EE_Error |
|
| 584 | - */ |
|
| 585 | - public function reg_step_submit_button() |
|
| 586 | - { |
|
| 587 | - if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
| 588 | - return ''; |
|
| 589 | - } |
|
| 590 | - ob_start(); |
|
| 591 | - do_action( |
|
| 592 | - 'AHEE__before_spco_whats_next_buttons', |
|
| 593 | - $this->slug(), |
|
| 594 | - $this->checkout->next_step->slug(), |
|
| 595 | - $this->checkout |
|
| 596 | - ); |
|
| 597 | - $html = ob_get_clean(); |
|
| 598 | - // generate submit button |
|
| 599 | - $sbmt_btn = new EE_Submit_Input( |
|
| 600 | - array( |
|
| 601 | - 'html_name' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
| 602 | - 'html_id' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
| 603 | - 'html_class' => 'spco-next-step-btn', |
|
| 604 | - 'other_html_attributes' => ' rel="' . $this->slug() . '"', |
|
| 605 | - 'default' => $this->submit_button_text(), |
|
| 606 | - ) |
|
| 607 | - ); |
|
| 608 | - $sbmt_btn->set_button_css_attributes(true, 'large'); |
|
| 609 | - $sbmt_btn_html = $sbmt_btn->get_html_for_input(); |
|
| 610 | - $html .= EEH_HTML::div( |
|
| 611 | - apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $sbmt_btn_html, $this), |
|
| 612 | - 'spco-' . $this->slug() . '-whats-next-buttons-dv', |
|
| 613 | - 'spco-whats-next-buttons' |
|
| 614 | - ); |
|
| 615 | - return $html; |
|
| 616 | - } |
|
| 617 | - |
|
| 618 | - |
|
| 619 | - |
|
| 620 | - /** |
|
| 621 | - * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
| 622 | - * |
|
| 623 | - * @return string |
|
| 624 | - */ |
|
| 625 | - public function div_class() |
|
| 626 | - { |
|
| 627 | - return $this->is_current_step() ? '' : ' hidden'; |
|
| 628 | - } |
|
| 629 | - |
|
| 630 | - |
|
| 631 | - |
|
| 632 | - /** |
|
| 633 | - * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
| 634 | - * |
|
| 635 | - * @return string |
|
| 636 | - */ |
|
| 637 | - public function edit_lnk_url() |
|
| 638 | - { |
|
| 639 | - return add_query_arg(array('step' => $this->slug()), $this->checkout->reg_page_base_url); |
|
| 640 | - } |
|
| 641 | - |
|
| 642 | - |
|
| 643 | - |
|
| 644 | - /** |
|
| 645 | - * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
| 646 | - * |
|
| 647 | - * @return string |
|
| 648 | - */ |
|
| 649 | - public function edit_link_class() |
|
| 650 | - { |
|
| 651 | - return $this->is_current_step() ? ' hidden' : ''; |
|
| 652 | - } |
|
| 653 | - |
|
| 654 | - |
|
| 655 | - |
|
| 656 | - /** |
|
| 657 | - * update_checkout with changes that have been made to the cart |
|
| 658 | - * |
|
| 659 | - * @return void |
|
| 660 | - * @throws \EE_Error |
|
| 661 | - */ |
|
| 662 | - public function update_checkout() |
|
| 663 | - { |
|
| 664 | - // grab the cart grand total and reset TXN total |
|
| 665 | - $this->checkout->transaction->set_total($this->checkout->cart->get_cart_grand_total()); |
|
| 666 | - $this->checkout->stash_transaction_and_checkout(); |
|
| 667 | - } |
|
| 668 | - |
|
| 669 | - |
|
| 670 | - |
|
| 671 | - |
|
| 672 | - |
|
| 673 | - /** |
|
| 674 | - * __sleep |
|
| 675 | - * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon |
|
| 676 | - * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the |
|
| 677 | - * reg form, because if needed, it will be regenerated anyways |
|
| 678 | - * |
|
| 679 | - * @return array |
|
| 680 | - */ |
|
| 681 | - public function __sleep() |
|
| 682 | - { |
|
| 683 | - // remove the reg form and the checkout |
|
| 684 | - return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout')); |
|
| 685 | - } |
|
| 360 | + /** |
|
| 361 | + * @return string |
|
| 362 | + */ |
|
| 363 | + public function _instructions() |
|
| 364 | + { |
|
| 365 | + return $this->_instructions; |
|
| 366 | + } |
|
| 367 | + |
|
| 368 | + |
|
| 369 | + |
|
| 370 | + /** |
|
| 371 | + * @param string $instructions |
|
| 372 | + */ |
|
| 373 | + public function set_instructions($instructions) |
|
| 374 | + { |
|
| 375 | + $this->_instructions = apply_filters( |
|
| 376 | + 'FHEE__EE_SPCO_Reg_Step__set_instructions__instructions', |
|
| 377 | + $instructions, |
|
| 378 | + $this |
|
| 379 | + ); |
|
| 380 | + } |
|
| 381 | + |
|
| 382 | + |
|
| 383 | + |
|
| 384 | + /** |
|
| 385 | + * @param array $valid_data |
|
| 386 | + */ |
|
| 387 | + public function set_valid_data($valid_data) |
|
| 388 | + { |
|
| 389 | + $this->_valid_data = $valid_data; |
|
| 390 | + } |
|
| 391 | + |
|
| 392 | + |
|
| 393 | + |
|
| 394 | + /** |
|
| 395 | + * @return array |
|
| 396 | + */ |
|
| 397 | + public function valid_data() |
|
| 398 | + { |
|
| 399 | + if (empty($this->_valid_data)) { |
|
| 400 | + $this->_valid_data = $this->reg_form->valid_data(); |
|
| 401 | + } |
|
| 402 | + return $this->_valid_data; |
|
| 403 | + } |
|
| 404 | + |
|
| 405 | + |
|
| 406 | + |
|
| 407 | + /** |
|
| 408 | + * @return string |
|
| 409 | + */ |
|
| 410 | + public function reg_form_name() |
|
| 411 | + { |
|
| 412 | + if (empty($this->_reg_form_name)) { |
|
| 413 | + $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form'); |
|
| 414 | + } |
|
| 415 | + return $this->_reg_form_name; |
|
| 416 | + } |
|
| 417 | + |
|
| 418 | + |
|
| 419 | + |
|
| 420 | + /** |
|
| 421 | + * @param string $reg_form_name |
|
| 422 | + */ |
|
| 423 | + protected function set_reg_form_name($reg_form_name) |
|
| 424 | + { |
|
| 425 | + $this->_reg_form_name = $reg_form_name; |
|
| 426 | + } |
|
| 427 | + |
|
| 428 | + |
|
| 429 | + |
|
| 430 | + /** |
|
| 431 | + * reg_step_url |
|
| 432 | + * |
|
| 433 | + * @param string $action |
|
| 434 | + * @return string |
|
| 435 | + */ |
|
| 436 | + public function reg_step_url($action = '') |
|
| 437 | + { |
|
| 438 | + $query_args = array('step' => $this->slug()); |
|
| 439 | + if (! empty($action)) { |
|
| 440 | + $query_args['action'] = $action; |
|
| 441 | + } |
|
| 442 | + // final step has no display |
|
| 443 | + if ($this instanceof EE_SPCO_Reg_Step_Finalize_Registration && $action === 'display_spco_reg_step') { |
|
| 444 | + $query_args['action'] = 'process_reg_step'; |
|
| 445 | + } |
|
| 446 | + if ($this->checkout->revisit) { |
|
| 447 | + $query_args['revisit'] = true; |
|
| 448 | + } |
|
| 449 | + if ($this->checkout->reg_url_link) { |
|
| 450 | + $query_args['e_reg_url_link'] = $this->checkout->reg_url_link; |
|
| 451 | + } |
|
| 452 | + return add_query_arg($query_args, $this->checkout->reg_page_base_url); |
|
| 453 | + } |
|
| 454 | + |
|
| 455 | + |
|
| 456 | + |
|
| 457 | + /** |
|
| 458 | + * creates the default hidden inputs section |
|
| 459 | + * |
|
| 460 | + * @return EE_Form_Section_Proper |
|
| 461 | + * @throws \EE_Error |
|
| 462 | + */ |
|
| 463 | + public function reg_step_hidden_inputs() |
|
| 464 | + { |
|
| 465 | + // hidden inputs for admin registrations |
|
| 466 | + if ($this->checkout->admin_request) { |
|
| 467 | + return new EE_Form_Section_Proper( |
|
| 468 | + array( |
|
| 469 | + 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
| 470 | + 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
| 471 | + 'subsections' => array( |
|
| 472 | + 'next_step' => new EE_Fixed_Hidden_Input( |
|
| 473 | + array( |
|
| 474 | + 'html_name' => 'next_step', |
|
| 475 | + 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
| 476 | + 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
| 477 | + ? $this->checkout->next_step->slug() |
|
| 478 | + : '', |
|
| 479 | + ) |
|
| 480 | + ), |
|
| 481 | + ), |
|
| 482 | + ) |
|
| 483 | + ); |
|
| 484 | + } |
|
| 485 | + // hidden inputs for frontend registrations |
|
| 486 | + return new EE_Form_Section_Proper( |
|
| 487 | + array( |
|
| 488 | + 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
|
| 489 | + 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
| 490 | + 'subsections' => array( |
|
| 491 | + 'action' => new EE_Fixed_Hidden_Input( |
|
| 492 | + array( |
|
| 493 | + 'html_name' => 'action', |
|
| 494 | + 'html_id' => 'spco-' . $this->slug() . '-action', |
|
| 495 | + 'default' => apply_filters( |
|
| 496 | + 'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action', |
|
| 497 | + empty($this->checkout->reg_url_link) |
|
| 498 | + ? 'process_reg_step' |
|
| 499 | + : 'update_reg_step', |
|
| 500 | + $this |
|
| 501 | + ), |
|
| 502 | + ) |
|
| 503 | + ), |
|
| 504 | + 'next_step' => new EE_Fixed_Hidden_Input( |
|
| 505 | + array( |
|
| 506 | + 'html_name' => 'next_step', |
|
| 507 | + 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
| 508 | + 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
|
| 509 | + ? $this->checkout->next_step->slug() |
|
| 510 | + : '', |
|
| 511 | + ) |
|
| 512 | + ), |
|
| 513 | + 'e_reg_url_link' => new EE_Fixed_Hidden_Input( |
|
| 514 | + array( |
|
| 515 | + 'html_name' => 'e_reg_url_link', |
|
| 516 | + 'html_id' => 'spco-reg_url_link', |
|
| 517 | + 'default' => $this->checkout->reg_url_link, |
|
| 518 | + ) |
|
| 519 | + ), |
|
| 520 | + 'revisit' => new EE_Fixed_Hidden_Input( |
|
| 521 | + array( |
|
| 522 | + 'html_name' => 'revisit', |
|
| 523 | + 'html_id' => 'spco-revisit', |
|
| 524 | + 'default' => $this->checkout->revisit, |
|
| 525 | + ) |
|
| 526 | + ), |
|
| 527 | + ), |
|
| 528 | + ) |
|
| 529 | + ); |
|
| 530 | + } |
|
| 531 | + |
|
| 532 | + |
|
| 533 | + |
|
| 534 | + /** |
|
| 535 | + * generate_reg_form_for_actions |
|
| 536 | + * |
|
| 537 | + * @param array $actions |
|
| 538 | + * @return void |
|
| 539 | + */ |
|
| 540 | + public function generate_reg_form_for_actions($actions = array()) |
|
| 541 | + { |
|
| 542 | + $actions = array_merge( |
|
| 543 | + array( |
|
| 544 | + 'generate_reg_form', |
|
| 545 | + 'display_spco_reg_step', |
|
| 546 | + 'process_reg_step', |
|
| 547 | + 'update_reg_step', |
|
| 548 | + ), |
|
| 549 | + $actions |
|
| 550 | + ); |
|
| 551 | + $this->checkout->generate_reg_form = in_array($this->checkout->action, $actions, true) ? true : false; |
|
| 552 | + } |
|
| 553 | + |
|
| 554 | + |
|
| 555 | + |
|
| 556 | + /** |
|
| 557 | + * @return string |
|
| 558 | + * @throws \EE_Error |
|
| 559 | + */ |
|
| 560 | + public function display_reg_form() |
|
| 561 | + { |
|
| 562 | + $html = ''; |
|
| 563 | + if ($this->reg_form instanceof EE_Form_Section_Proper) { |
|
| 564 | + do_action('AHEE__EE_SPCO_Reg_Step__display_reg_form__reg_form', $this->reg_form, $this); |
|
| 565 | + $html .= ! $this->checkout->admin_request ? $this->reg_form->form_open($this->reg_step_url()) : ''; |
|
| 566 | + if (EE_Registry::instance()->REQ->ajax) { |
|
| 567 | + $this->reg_form->localize_validation_rules(); |
|
| 568 | + $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization()); |
|
| 569 | + } |
|
| 570 | + $html .= $this->reg_form->get_html(); |
|
| 571 | + $html .= ! $this->checkout->admin_request ? $this->reg_step_submit_button() : ''; |
|
| 572 | + $html .= ! $this->checkout->admin_request ? $this->reg_form->form_close() : ''; |
|
| 573 | + } |
|
| 574 | + return $html; |
|
| 575 | + } |
|
| 576 | + |
|
| 577 | + |
|
| 578 | + |
|
| 579 | + /** |
|
| 580 | + * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
| 581 | + * |
|
| 582 | + * @return string |
|
| 583 | + * @throws \EE_Error |
|
| 584 | + */ |
|
| 585 | + public function reg_step_submit_button() |
|
| 586 | + { |
|
| 587 | + if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
| 588 | + return ''; |
|
| 589 | + } |
|
| 590 | + ob_start(); |
|
| 591 | + do_action( |
|
| 592 | + 'AHEE__before_spco_whats_next_buttons', |
|
| 593 | + $this->slug(), |
|
| 594 | + $this->checkout->next_step->slug(), |
|
| 595 | + $this->checkout |
|
| 596 | + ); |
|
| 597 | + $html = ob_get_clean(); |
|
| 598 | + // generate submit button |
|
| 599 | + $sbmt_btn = new EE_Submit_Input( |
|
| 600 | + array( |
|
| 601 | + 'html_name' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
| 602 | + 'html_id' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
| 603 | + 'html_class' => 'spco-next-step-btn', |
|
| 604 | + 'other_html_attributes' => ' rel="' . $this->slug() . '"', |
|
| 605 | + 'default' => $this->submit_button_text(), |
|
| 606 | + ) |
|
| 607 | + ); |
|
| 608 | + $sbmt_btn->set_button_css_attributes(true, 'large'); |
|
| 609 | + $sbmt_btn_html = $sbmt_btn->get_html_for_input(); |
|
| 610 | + $html .= EEH_HTML::div( |
|
| 611 | + apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $sbmt_btn_html, $this), |
|
| 612 | + 'spco-' . $this->slug() . '-whats-next-buttons-dv', |
|
| 613 | + 'spco-whats-next-buttons' |
|
| 614 | + ); |
|
| 615 | + return $html; |
|
| 616 | + } |
|
| 617 | + |
|
| 618 | + |
|
| 619 | + |
|
| 620 | + /** |
|
| 621 | + * div_class - returns nothing for current step, but a css class of "hidden" for others |
|
| 622 | + * |
|
| 623 | + * @return string |
|
| 624 | + */ |
|
| 625 | + public function div_class() |
|
| 626 | + { |
|
| 627 | + return $this->is_current_step() ? '' : ' hidden'; |
|
| 628 | + } |
|
| 629 | + |
|
| 630 | + |
|
| 631 | + |
|
| 632 | + /** |
|
| 633 | + * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
| 634 | + * |
|
| 635 | + * @return string |
|
| 636 | + */ |
|
| 637 | + public function edit_lnk_url() |
|
| 638 | + { |
|
| 639 | + return add_query_arg(array('step' => $this->slug()), $this->checkout->reg_page_base_url); |
|
| 640 | + } |
|
| 641 | + |
|
| 642 | + |
|
| 643 | + |
|
| 644 | + /** |
|
| 645 | + * div_class - returns a css class of "hidden" for current step, but nothing for others |
|
| 646 | + * |
|
| 647 | + * @return string |
|
| 648 | + */ |
|
| 649 | + public function edit_link_class() |
|
| 650 | + { |
|
| 651 | + return $this->is_current_step() ? ' hidden' : ''; |
|
| 652 | + } |
|
| 653 | + |
|
| 654 | + |
|
| 655 | + |
|
| 656 | + /** |
|
| 657 | + * update_checkout with changes that have been made to the cart |
|
| 658 | + * |
|
| 659 | + * @return void |
|
| 660 | + * @throws \EE_Error |
|
| 661 | + */ |
|
| 662 | + public function update_checkout() |
|
| 663 | + { |
|
| 664 | + // grab the cart grand total and reset TXN total |
|
| 665 | + $this->checkout->transaction->set_total($this->checkout->cart->get_cart_grand_total()); |
|
| 666 | + $this->checkout->stash_transaction_and_checkout(); |
|
| 667 | + } |
|
| 668 | + |
|
| 669 | + |
|
| 670 | + |
|
| 671 | + |
|
| 672 | + |
|
| 673 | + /** |
|
| 674 | + * __sleep |
|
| 675 | + * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon |
|
| 676 | + * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the |
|
| 677 | + * reg form, because if needed, it will be regenerated anyways |
|
| 678 | + * |
|
| 679 | + * @return array |
|
| 680 | + */ |
|
| 681 | + public function __sleep() |
|
| 682 | + { |
|
| 683 | + // remove the reg form and the checkout |
|
| 684 | + return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout')); |
|
| 685 | + } |
|
| 686 | 686 | |
| 687 | 687 | |
| 688 | 688 | |
@@ -1,4 +1,4 @@ discard block |
||
| 1 | -<?php if (! defined('EVENT_ESPRESSO_VERSION')) { |
|
| 1 | +<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
|
| 2 | 2 | exit('No direct script access allowed'); |
| 3 | 3 | } |
| 4 | 4 | |
@@ -238,7 +238,7 @@ discard block |
||
| 238 | 238 | */ |
| 239 | 239 | public function set_submit_button_text($submit_button_text = '') |
| 240 | 240 | { |
| 241 | - if (! empty($submit_button_text)) { |
|
| 241 | + if ( ! empty($submit_button_text)) { |
|
| 242 | 242 | $this->_submit_button_text = $submit_button_text; |
| 243 | 243 | } else if ($this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
| 244 | 244 | if ($this->checkout->revisit) { |
@@ -410,7 +410,7 @@ discard block |
||
| 410 | 410 | public function reg_form_name() |
| 411 | 411 | { |
| 412 | 412 | if (empty($this->_reg_form_name)) { |
| 413 | - $this->set_reg_form_name('ee-spco-' . $this->slug() . '-reg-step-form'); |
|
| 413 | + $this->set_reg_form_name('ee-spco-'.$this->slug().'-reg-step-form'); |
|
| 414 | 414 | } |
| 415 | 415 | return $this->_reg_form_name; |
| 416 | 416 | } |
@@ -436,7 +436,7 @@ discard block |
||
| 436 | 436 | public function reg_step_url($action = '') |
| 437 | 437 | { |
| 438 | 438 | $query_args = array('step' => $this->slug()); |
| 439 | - if (! empty($action)) { |
|
| 439 | + if ( ! empty($action)) { |
|
| 440 | 440 | $query_args['action'] = $action; |
| 441 | 441 | } |
| 442 | 442 | // final step has no display |
@@ -467,12 +467,12 @@ discard block |
||
| 467 | 467 | return new EE_Form_Section_Proper( |
| 468 | 468 | array( |
| 469 | 469 | 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
| 470 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
| 470 | + 'html_id' => 'ee-'.$this->slug().'-hidden-inputs', |
|
| 471 | 471 | 'subsections' => array( |
| 472 | 472 | 'next_step' => new EE_Fixed_Hidden_Input( |
| 473 | 473 | array( |
| 474 | 474 | 'html_name' => 'next_step', |
| 475 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
| 475 | + 'html_id' => 'spco-'.$this->slug().'-next-step', |
|
| 476 | 476 | 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
| 477 | 477 | ? $this->checkout->next_step->slug() |
| 478 | 478 | : '', |
@@ -486,12 +486,12 @@ discard block |
||
| 486 | 486 | return new EE_Form_Section_Proper( |
| 487 | 487 | array( |
| 488 | 488 | 'layout_strategy' => new EE_Div_Per_Section_Layout(), |
| 489 | - 'html_id' => 'ee-' . $this->slug() . '-hidden-inputs', |
|
| 489 | + 'html_id' => 'ee-'.$this->slug().'-hidden-inputs', |
|
| 490 | 490 | 'subsections' => array( |
| 491 | 491 | 'action' => new EE_Fixed_Hidden_Input( |
| 492 | 492 | array( |
| 493 | 493 | 'html_name' => 'action', |
| 494 | - 'html_id' => 'spco-' . $this->slug() . '-action', |
|
| 494 | + 'html_id' => 'spco-'.$this->slug().'-action', |
|
| 495 | 495 | 'default' => apply_filters( |
| 496 | 496 | 'FHEE__EE_SPCO_Reg_Step__reg_step_hidden_inputs__default_form_action', |
| 497 | 497 | empty($this->checkout->reg_url_link) |
@@ -504,7 +504,7 @@ discard block |
||
| 504 | 504 | 'next_step' => new EE_Fixed_Hidden_Input( |
| 505 | 505 | array( |
| 506 | 506 | 'html_name' => 'next_step', |
| 507 | - 'html_id' => 'spco-' . $this->slug() . '-next-step', |
|
| 507 | + 'html_id' => 'spco-'.$this->slug().'-next-step', |
|
| 508 | 508 | 'default' => $this->checkout->next_step instanceof EE_SPCO_Reg_Step |
| 509 | 509 | ? $this->checkout->next_step->slug() |
| 510 | 510 | : '', |
@@ -584,7 +584,7 @@ discard block |
||
| 584 | 584 | */ |
| 585 | 585 | public function reg_step_submit_button() |
| 586 | 586 | { |
| 587 | - if (! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
| 587 | + if ( ! $this->checkout->next_step instanceof EE_SPCO_Reg_Step) { |
|
| 588 | 588 | return ''; |
| 589 | 589 | } |
| 590 | 590 | ob_start(); |
@@ -598,10 +598,10 @@ discard block |
||
| 598 | 598 | // generate submit button |
| 599 | 599 | $sbmt_btn = new EE_Submit_Input( |
| 600 | 600 | array( |
| 601 | - 'html_name' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
| 602 | - 'html_id' => 'spco-go-to-step-' . $this->checkout->next_step->slug(), |
|
| 601 | + 'html_name' => 'spco-go-to-step-'.$this->checkout->next_step->slug(), |
|
| 602 | + 'html_id' => 'spco-go-to-step-'.$this->checkout->next_step->slug(), |
|
| 603 | 603 | 'html_class' => 'spco-next-step-btn', |
| 604 | - 'other_html_attributes' => ' rel="' . $this->slug() . '"', |
|
| 604 | + 'other_html_attributes' => ' rel="'.$this->slug().'"', |
|
| 605 | 605 | 'default' => $this->submit_button_text(), |
| 606 | 606 | ) |
| 607 | 607 | ); |
@@ -609,7 +609,7 @@ discard block |
||
| 609 | 609 | $sbmt_btn_html = $sbmt_btn->get_html_for_input(); |
| 610 | 610 | $html .= EEH_HTML::div( |
| 611 | 611 | apply_filters('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', $sbmt_btn_html, $this), |
| 612 | - 'spco-' . $this->slug() . '-whats-next-buttons-dv', |
|
| 612 | + 'spco-'.$this->slug().'-whats-next-buttons-dv', |
|
| 613 | 613 | 'spco-whats-next-buttons' |
| 614 | 614 | ); |
| 615 | 615 | return $html; |
@@ -19,7 +19,7 @@ discard block |
||
| 19 | 19 | use InvalidArgumentException; |
| 20 | 20 | use WP_Post; |
| 21 | 21 | |
| 22 | -defined('EVENT_ESPRESSO_VERSION')|| exit('No direct script access allowed'); |
|
| 22 | +defined('EVENT_ESPRESSO_VERSION') || exit('No direct script access allowed'); |
|
| 23 | 23 | |
| 24 | 24 | |
| 25 | 25 | |
@@ -140,11 +140,11 @@ discard block |
||
| 140 | 140 | } |
| 141 | 141 | } else { |
| 142 | 142 | $user_msg = __('No Event object or an invalid Event object was supplied.', 'event_espresso'); |
| 143 | - $dev_msg = $user_msg . __( |
|
| 143 | + $dev_msg = $user_msg.__( |
|
| 144 | 144 | 'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.', |
| 145 | 145 | 'event_espresso' |
| 146 | 146 | ); |
| 147 | - EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 147 | + EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 148 | 148 | return false; |
| 149 | 149 | } |
| 150 | 150 | return true; |
@@ -208,7 +208,7 @@ discard block |
||
| 208 | 208 | // reset filter for displaying submit button |
| 209 | 209 | remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true'); |
| 210 | 210 | // poke and prod incoming event till it tells us what it is |
| 211 | - if (! $this->setEvent($event)) { |
|
| 211 | + if ( ! $this->setEvent($event)) { |
|
| 212 | 212 | return false; |
| 213 | 213 | } |
| 214 | 214 | // begin gathering template arguments by getting event status |
@@ -238,14 +238,14 @@ discard block |
||
| 238 | 238 | return $this->noTicketAvailableMessage(); |
| 239 | 239 | } |
| 240 | 240 | // redirecting to another site for registration ?? |
| 241 | - $external_url = (string)$this->event->external_url(); |
|
| 241 | + $external_url = (string) $this->event->external_url(); |
|
| 242 | 242 | // if redirecting to another site for registration, then we don't load the TS |
| 243 | 243 | $ticket_selector = $external_url |
| 244 | 244 | ? $this->externalEventRegistration() |
| 245 | 245 | : $this->loadTicketSelector($tickets, $template_args); |
| 246 | 246 | // now set up the form (but not for the admin) |
| 247 | 247 | $ticket_selector = $this->display_full_ui() |
| 248 | - ? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector |
|
| 248 | + ? $this->formOpen($this->event->ID(), $external_url).$ticket_selector |
|
| 249 | 249 | : $ticket_selector; |
| 250 | 250 | // submit button and form close tag |
| 251 | 251 | $ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : ''; |
@@ -295,10 +295,10 @@ discard block |
||
| 295 | 295 | */ |
| 296 | 296 | protected function expiredEventMessage() |
| 297 | 297 | { |
| 298 | - return '<div class="ee-event-expired-notice"><span class="important-notice">' . esc_html__( |
|
| 298 | + return '<div class="ee-event-expired-notice"><span class="important-notice">'.esc_html__( |
|
| 299 | 299 | 'We\'re sorry, but all tickets sales have ended because the event is expired.', |
| 300 | 300 | 'event_espresso' |
| 301 | - ) . '</span></div><!-- .ee-event-expired-notice -->'; |
|
| 301 | + ).'</span></div><!-- .ee-event-expired-notice -->'; |
|
| 302 | 302 | } |
| 303 | 303 | |
| 304 | 304 | |
@@ -329,7 +329,7 @@ discard block |
||
| 329 | 329 | } |
| 330 | 330 | return ' |
| 331 | 331 | <div class="ee-event-expired-notice"> |
| 332 | - <span class="important-notice">' . $no_ticket_available_msg . '</span> |
|
| 332 | + <span class="important-notice">' . $no_ticket_available_msg.'</span> |
|
| 333 | 333 | </div><!-- .ee-event-expired-notice -->'; |
| 334 | 334 | } |
| 335 | 335 | |
@@ -362,7 +362,7 @@ discard block |
||
| 362 | 362 | '</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->' |
| 363 | 363 | ); |
| 364 | 364 | } |
| 365 | - return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>'; |
|
| 365 | + return '<p><span class="important-notice">'.$sales_closed_msg.'</span></p>'; |
|
| 366 | 366 | } |
| 367 | 367 | |
| 368 | 368 | |
@@ -430,9 +430,9 @@ discard block |
||
| 430 | 430 | * @param string '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to |
| 431 | 431 | * @param int $EVT_ID The Event ID |
| 432 | 432 | */ |
| 433 | - $template_args['anchor_id'] = apply_filters( |
|
| 433 | + $template_args['anchor_id'] = apply_filters( |
|
| 434 | 434 | 'FHEE__EE_Ticket_Selector__redirect_anchor_id', |
| 435 | - '#tkt-slctr-tbl-' . $this->event->ID(), |
|
| 435 | + '#tkt-slctr-tbl-'.$this->event->ID(), |
|
| 436 | 436 | $this->event->ID() |
| 437 | 437 | ); |
| 438 | 438 | $template_args['tickets'] = $tickets; |
@@ -523,8 +523,8 @@ discard block |
||
| 523 | 523 | // if redirecting, we don't need any anything else |
| 524 | 524 | if ($external_url) { |
| 525 | 525 | $html = '<form method="GET" '; |
| 526 | - $html .= 'action="' . EEH_URL::refactor_url($external_url) . '" '; |
|
| 527 | - $html .= 'name="ticket-selector-form-' . $ID . '"'; |
|
| 526 | + $html .= 'action="'.EEH_URL::refactor_url($external_url).'" '; |
|
| 527 | + $html .= 'name="ticket-selector-form-'.$ID.'"'; |
|
| 528 | 528 | // open link in new window ? |
| 529 | 529 | $html .= apply_filters( |
| 530 | 530 | 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank', |
@@ -536,17 +536,17 @@ discard block |
||
| 536 | 536 | $html .= '>'; |
| 537 | 537 | $query_args = EEH_URL::get_query_string($external_url); |
| 538 | 538 | foreach ((array) $query_args as $query_arg => $value) { |
| 539 | - $html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">'; |
|
| 539 | + $html .= '<input type="hidden" name="'.$query_arg.'" value="'.$value.'">'; |
|
| 540 | 540 | } |
| 541 | 541 | return $html; |
| 542 | 542 | } |
| 543 | 543 | // if there is no submit button, then don't start building a form |
| 544 | 544 | // because the "View Details" button will build its own form |
| 545 | - if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) { |
|
| 545 | + if ( ! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) { |
|
| 546 | 546 | return ''; |
| 547 | 547 | } |
| 548 | 548 | $checkout_url = EEH_Event_View::event_link_url($ID); |
| 549 | - if (! $checkout_url) { |
|
| 549 | + if ( ! $checkout_url) { |
|
| 550 | 550 | EE_Error::add_error( |
| 551 | 551 | esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'), |
| 552 | 552 | __FILE__, |
@@ -557,8 +557,8 @@ discard block |
||
| 557 | 557 | // set no cache headers and constants |
| 558 | 558 | EE_System::do_not_cache(); |
| 559 | 559 | $html = '<form method="POST" '; |
| 560 | - $html .= 'action="' . $checkout_url . '" '; |
|
| 561 | - $html .= 'name="ticket-selector-form-' . $ID . '"'; |
|
| 560 | + $html .= 'action="'.$checkout_url.'" '; |
|
| 561 | + $html .= 'name="ticket-selector-form-'.$ID.'"'; |
|
| 562 | 562 | $html .= $this->iframe ? ' target="_blank"' : ''; |
| 563 | 563 | $html .= '>'; |
| 564 | 564 | $html .= '<input type="hidden" name="ee" value="process_ticket_selections">'; |
@@ -585,7 +585,7 @@ discard block |
||
| 585 | 585 | $html .= empty($external_url) |
| 586 | 586 | ? $this->ticketSelectorEndDiv() |
| 587 | 587 | : $this->clearTicketSelector(); |
| 588 | - $html .= '<br/>' . $this->formClose(); |
|
| 588 | + $html .= '<br/>'.$this->formClose(); |
|
| 589 | 589 | } elseif ($this->getMaxAttendees() === 1) { |
| 590 | 590 | // its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1) |
| 591 | 591 | if ($this->event->is_sold_out()) { |
@@ -643,7 +643,7 @@ discard block |
||
| 643 | 643 | // no submit or view details button, and no additional content |
| 644 | 644 | $html .= $this->ticketSelectorEndDiv(); |
| 645 | 645 | } |
| 646 | - if (! $this->iframe && ! is_archive()) { |
|
| 646 | + if ( ! $this->iframe && ! is_archive()) { |
|
| 647 | 647 | $html .= EEH_Template::powered_by_event_espresso('', '', array('utm_content' => 'ticket_selector')); |
| 648 | 648 | } |
| 649 | 649 | } |
@@ -663,7 +663,7 @@ discard block |
||
| 663 | 663 | */ |
| 664 | 664 | public function displayRegisterNowButton() |
| 665 | 665 | { |
| 666 | - $btn_text = apply_filters( |
|
| 666 | + $btn_text = apply_filters( |
|
| 667 | 667 | 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text', |
| 668 | 668 | __('Register Now', 'event_espresso'), |
| 669 | 669 | $this->event |
@@ -671,14 +671,14 @@ discard block |
||
| 671 | 671 | $external_url = $this->event->external_url(); |
| 672 | 672 | $html = EEH_HTML::div( |
| 673 | 673 | '', |
| 674 | - 'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap', |
|
| 674 | + 'ticket-selector-submit-'.$this->event->ID().'-btn-wrap', |
|
| 675 | 675 | 'ticket-selector-submit-btn-wrap' |
| 676 | 676 | ); |
| 677 | - $html .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"'; |
|
| 677 | + $html .= '<input id="ticket-selector-submit-'.$this->event->ID().'-btn"'; |
|
| 678 | 678 | $html .= ' class="ticket-selector-submit-btn '; |
| 679 | 679 | $html .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"'; |
| 680 | - $html .= ' type="submit" value="' . $btn_text . '" />'; |
|
| 681 | - $html .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->'; |
|
| 680 | + $html .= ' type="submit" value="'.$btn_text.'" />'; |
|
| 681 | + $html .= EEH_HTML::divx().'<!-- .ticket-selector-submit-btn-wrap -->'; |
|
| 682 | 682 | $html .= apply_filters( |
| 683 | 683 | 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
| 684 | 684 | '', |
@@ -700,7 +700,7 @@ discard block |
||
| 700 | 700 | */ |
| 701 | 701 | public function displayViewDetailsButton($DWMTS = false) |
| 702 | 702 | { |
| 703 | - if (! $this->event->get_permalink()) { |
|
| 703 | + if ( ! $this->event->get_permalink()) { |
|
| 704 | 704 | EE_Error::add_error( |
| 705 | 705 | esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'), |
| 706 | 706 | __FILE__, |
@@ -724,7 +724,7 @@ discard block |
||
| 724 | 724 | ? ' target="_blank"' |
| 725 | 725 | : ''; |
| 726 | 726 | $view_details_btn .= '>'; |
| 727 | - $btn_text = apply_filters( |
|
| 727 | + $btn_text = apply_filters( |
|
| 728 | 728 | 'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text', |
| 729 | 729 | esc_html__('View Details', 'event_espresso'), |
| 730 | 730 | $this->event |
@@ -754,7 +754,7 @@ discard block |
||
| 754 | 754 | */ |
| 755 | 755 | public function ticketSelectorEndDiv() |
| 756 | 756 | { |
| 757 | - return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->'; |
|
| 757 | + return $this->clearTicketSelector().'</div><!-- ticketSelectorEndDiv -->'; |
|
| 758 | 758 | } |
| 759 | 759 | |
| 760 | 760 | |
@@ -36,749 +36,749 @@ |
||
| 36 | 36 | class DisplayTicketSelector |
| 37 | 37 | { |
| 38 | 38 | |
| 39 | - /** |
|
| 40 | - * event that ticket selector is being generated for |
|
| 41 | - * |
|
| 42 | - * @access protected |
|
| 43 | - * @var EE_Event $event |
|
| 44 | - */ |
|
| 45 | - protected $event; |
|
| 46 | - |
|
| 47 | - /** |
|
| 48 | - * Used to flag when the ticket selector is being called from an external iframe. |
|
| 49 | - * |
|
| 50 | - * @var bool $iframe |
|
| 51 | - */ |
|
| 52 | - protected $iframe = false; |
|
| 53 | - |
|
| 54 | - /** |
|
| 55 | - * max attendees that can register for event at one time |
|
| 56 | - * |
|
| 57 | - * @var int $max_attendees |
|
| 58 | - */ |
|
| 59 | - private $max_attendees = EE_INF; |
|
| 60 | - |
|
| 61 | - /** |
|
| 62 | - * @var string $date_format |
|
| 63 | - */ |
|
| 64 | - private $date_format; |
|
| 65 | - |
|
| 66 | - /** |
|
| 67 | - * @var string $time_format |
|
| 68 | - */ |
|
| 69 | - private $time_format; |
|
| 70 | - |
|
| 71 | - /** |
|
| 72 | - * @var boolean $display_full_ui |
|
| 73 | - */ |
|
| 74 | - private $display_full_ui; |
|
| 75 | - |
|
| 76 | - |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * DisplayTicketSelector constructor. |
|
| 80 | - * |
|
| 81 | - * @param bool $iframe |
|
| 82 | - */ |
|
| 83 | - public function __construct($iframe = false) |
|
| 84 | - { |
|
| 85 | - $this->iframe = $iframe; |
|
| 86 | - $this->date_format = apply_filters( |
|
| 87 | - 'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format', |
|
| 88 | - get_option('date_format') |
|
| 89 | - ); |
|
| 90 | - $this->time_format = apply_filters( |
|
| 91 | - 'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format', |
|
| 92 | - get_option('time_format') |
|
| 93 | - ); |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - |
|
| 97 | - /** |
|
| 98 | - * @return bool |
|
| 99 | - */ |
|
| 100 | - public function isIframe() |
|
| 101 | - { |
|
| 102 | - return $this->iframe; |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - |
|
| 106 | - |
|
| 107 | - /** |
|
| 108 | - * @param boolean $iframe |
|
| 109 | - */ |
|
| 110 | - public function setIframe($iframe = true) |
|
| 111 | - { |
|
| 112 | - $this->iframe = filter_var($iframe, FILTER_VALIDATE_BOOLEAN); |
|
| 113 | - } |
|
| 114 | - |
|
| 115 | - |
|
| 116 | - /** |
|
| 117 | - * finds and sets the \EE_Event object for use throughout class |
|
| 118 | - * |
|
| 119 | - * @param mixed $event |
|
| 120 | - * @return bool |
|
| 121 | - * @throws EE_Error |
|
| 122 | - * @throws InvalidDataTypeException |
|
| 123 | - * @throws InvalidInterfaceException |
|
| 124 | - * @throws InvalidArgumentException |
|
| 125 | - */ |
|
| 126 | - protected function setEvent($event = null) |
|
| 127 | - { |
|
| 128 | - if ($event === null) { |
|
| 129 | - global $post; |
|
| 130 | - $event = $post; |
|
| 131 | - } |
|
| 132 | - if ($event instanceof EE_Event) { |
|
| 133 | - $this->event = $event; |
|
| 134 | - } elseif ($event instanceof WP_Post) { |
|
| 135 | - if (isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) { |
|
| 136 | - $this->event = $event->EE_Event; |
|
| 137 | - } elseif ($event->post_type === 'espresso_events') { |
|
| 138 | - $event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event); |
|
| 139 | - $this->event = $event->EE_Event; |
|
| 140 | - } |
|
| 141 | - } else { |
|
| 142 | - $user_msg = __('No Event object or an invalid Event object was supplied.', 'event_espresso'); |
|
| 143 | - $dev_msg = $user_msg . __( |
|
| 144 | - 'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.', |
|
| 145 | - 'event_espresso' |
|
| 146 | - ); |
|
| 147 | - EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 148 | - return false; |
|
| 149 | - } |
|
| 150 | - return true; |
|
| 151 | - } |
|
| 152 | - |
|
| 153 | - |
|
| 154 | - |
|
| 155 | - /** |
|
| 156 | - * @return int |
|
| 157 | - */ |
|
| 158 | - public function getMaxAttendees() |
|
| 159 | - { |
|
| 160 | - return $this->max_attendees; |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - |
|
| 164 | - |
|
| 165 | - /** |
|
| 166 | - * @param int $max_attendees |
|
| 167 | - */ |
|
| 168 | - public function setMaxAttendees($max_attendees) |
|
| 169 | - { |
|
| 170 | - $this->max_attendees = absint( |
|
| 171 | - apply_filters( |
|
| 172 | - 'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets', |
|
| 173 | - $max_attendees |
|
| 174 | - ) |
|
| 175 | - ); |
|
| 176 | - } |
|
| 177 | - |
|
| 178 | - |
|
| 179 | - |
|
| 180 | - /** |
|
| 181 | - * Returns whether or not the full ticket selector should be shown or not. |
|
| 182 | - * Currently, it displays on the frontend (including ajax requests) but not the backend |
|
| 183 | - * |
|
| 184 | - * @return bool |
|
| 185 | - */ |
|
| 186 | - private function display_full_ui() |
|
| 187 | - { |
|
| 188 | - if ($this->display_full_ui === null) { |
|
| 189 | - $this->display_full_ui = ! is_admin() || (defined('DOING_AJAX') && DOING_AJAX); |
|
| 190 | - } |
|
| 191 | - return $this->display_full_ui; |
|
| 192 | - } |
|
| 193 | - |
|
| 194 | - |
|
| 195 | - /** |
|
| 196 | - * creates buttons for selecting number of attendees for an event |
|
| 197 | - * |
|
| 198 | - * @param WP_Post|int $event |
|
| 199 | - * @param bool $view_details |
|
| 200 | - * @return string |
|
| 201 | - * @throws EE_Error |
|
| 202 | - * @throws InvalidArgumentException |
|
| 203 | - * @throws InvalidDataTypeException |
|
| 204 | - * @throws InvalidInterfaceException |
|
| 205 | - */ |
|
| 206 | - public function display($event = null, $view_details = false) |
|
| 207 | - { |
|
| 208 | - // reset filter for displaying submit button |
|
| 209 | - remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true'); |
|
| 210 | - // poke and prod incoming event till it tells us what it is |
|
| 211 | - if (! $this->setEvent($event)) { |
|
| 212 | - return false; |
|
| 213 | - } |
|
| 214 | - // begin gathering template arguments by getting event status |
|
| 215 | - $template_args = array('event_status' => $this->event->get_active_status()); |
|
| 216 | - if ( |
|
| 217 | - $this->activeEventAndShowTicketSelector( |
|
| 218 | - $event, |
|
| 219 | - $template_args['event_status'], |
|
| 220 | - $view_details |
|
| 221 | - ) |
|
| 222 | - ) { |
|
| 223 | - return ! is_single() ? $this->displayViewDetailsButton() : ''; |
|
| 224 | - } |
|
| 225 | - // filter the maximum qty that can appear in the Ticket Selector qty dropdowns |
|
| 226 | - $this->setMaxAttendees($this->event->additional_limit()); |
|
| 227 | - if ($this->getMaxAttendees() < 1) { |
|
| 228 | - return $this->ticketSalesClosedMessage(); |
|
| 229 | - } |
|
| 230 | - // is the event expired ? |
|
| 231 | - $template_args['event_is_expired'] = $this->event->is_expired(); |
|
| 232 | - if ($template_args['event_is_expired']) { |
|
| 233 | - return $this->expiredEventMessage(); |
|
| 234 | - } |
|
| 235 | - // get all tickets for this event ordered by the datetime |
|
| 236 | - $tickets = $this->getTickets(); |
|
| 237 | - if (count($tickets) < 1) { |
|
| 238 | - return $this->noTicketAvailableMessage(); |
|
| 239 | - } |
|
| 240 | - // redirecting to another site for registration ?? |
|
| 241 | - $external_url = (string)$this->event->external_url(); |
|
| 242 | - // if redirecting to another site for registration, then we don't load the TS |
|
| 243 | - $ticket_selector = $external_url |
|
| 244 | - ? $this->externalEventRegistration() |
|
| 245 | - : $this->loadTicketSelector($tickets, $template_args); |
|
| 246 | - // now set up the form (but not for the admin) |
|
| 247 | - $ticket_selector = $this->display_full_ui() |
|
| 248 | - ? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector |
|
| 249 | - : $ticket_selector; |
|
| 250 | - // submit button and form close tag |
|
| 251 | - $ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : ''; |
|
| 252 | - return $ticket_selector; |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - |
|
| 256 | - |
|
| 257 | - /** |
|
| 258 | - * displayTicketSelector |
|
| 259 | - * examines the event properties and determines whether a Ticket Selector should be displayed |
|
| 260 | - * |
|
| 261 | - * @param WP_Post|int $event |
|
| 262 | - * @param string $_event_active_status |
|
| 263 | - * @param bool $view_details |
|
| 264 | - * @return bool |
|
| 265 | - * @throws EE_Error |
|
| 266 | - */ |
|
| 267 | - protected function activeEventAndShowTicketSelector($event, $_event_active_status, $view_details) |
|
| 268 | - { |
|
| 269 | - $event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event; |
|
| 270 | - return $this->display_full_ui() |
|
| 271 | - && ( |
|
| 272 | - ! $this->event->display_ticket_selector() |
|
| 273 | - || $view_details |
|
| 274 | - || post_password_required($event_post) |
|
| 275 | - || ( |
|
| 276 | - $_event_active_status !== EE_Datetime::active |
|
| 277 | - && $_event_active_status !== EE_Datetime::upcoming |
|
| 278 | - && $_event_active_status !== EE_Datetime::sold_out |
|
| 279 | - && ! ( |
|
| 280 | - $_event_active_status === EE_Datetime::inactive |
|
| 281 | - && is_user_logged_in() |
|
| 282 | - ) |
|
| 283 | - ) |
|
| 284 | - ); |
|
| 285 | - } |
|
| 286 | - |
|
| 287 | - |
|
| 288 | - |
|
| 289 | - /** |
|
| 290 | - * noTicketAvailableMessage |
|
| 291 | - * notice displayed if event is expired |
|
| 292 | - * |
|
| 293 | - * @return string |
|
| 294 | - * @throws EE_Error |
|
| 295 | - */ |
|
| 296 | - protected function expiredEventMessage() |
|
| 297 | - { |
|
| 298 | - return '<div class="ee-event-expired-notice"><span class="important-notice">' . esc_html__( |
|
| 299 | - 'We\'re sorry, but all tickets sales have ended because the event is expired.', |
|
| 300 | - 'event_espresso' |
|
| 301 | - ) . '</span></div><!-- .ee-event-expired-notice -->'; |
|
| 302 | - } |
|
| 303 | - |
|
| 304 | - |
|
| 305 | - |
|
| 306 | - /** |
|
| 307 | - * noTicketAvailableMessage |
|
| 308 | - * notice displayed if event has no more tickets available |
|
| 309 | - * |
|
| 310 | - * @return string |
|
| 311 | - * @throws EE_Error |
|
| 312 | - */ |
|
| 313 | - protected function noTicketAvailableMessage() |
|
| 314 | - { |
|
| 315 | - $no_ticket_available_msg = esc_html__('We\'re sorry, but all ticket sales have ended.', 'event_espresso'); |
|
| 316 | - if (current_user_can('edit_post', $this->event->ID())) { |
|
| 317 | - $no_ticket_available_msg .= sprintf( |
|
| 318 | - esc_html__( |
|
| 319 | - '%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s', |
|
| 320 | - 'event_espresso' |
|
| 321 | - ), |
|
| 322 | - '<div class="ee-attention" style="text-align: left;"><b>', |
|
| 323 | - '</b><br />', |
|
| 324 | - '<span class="edit-link"><a class="post-edit-link" href="' |
|
| 325 | - . get_edit_post_link($this->event->ID()) |
|
| 326 | - . '">', |
|
| 327 | - '</a></span></div><!-- .ee-attention noTicketAvailableMessage -->' |
|
| 328 | - ); |
|
| 329 | - } |
|
| 330 | - return ' |
|
| 39 | + /** |
|
| 40 | + * event that ticket selector is being generated for |
|
| 41 | + * |
|
| 42 | + * @access protected |
|
| 43 | + * @var EE_Event $event |
|
| 44 | + */ |
|
| 45 | + protected $event; |
|
| 46 | + |
|
| 47 | + /** |
|
| 48 | + * Used to flag when the ticket selector is being called from an external iframe. |
|
| 49 | + * |
|
| 50 | + * @var bool $iframe |
|
| 51 | + */ |
|
| 52 | + protected $iframe = false; |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * max attendees that can register for event at one time |
|
| 56 | + * |
|
| 57 | + * @var int $max_attendees |
|
| 58 | + */ |
|
| 59 | + private $max_attendees = EE_INF; |
|
| 60 | + |
|
| 61 | + /** |
|
| 62 | + * @var string $date_format |
|
| 63 | + */ |
|
| 64 | + private $date_format; |
|
| 65 | + |
|
| 66 | + /** |
|
| 67 | + * @var string $time_format |
|
| 68 | + */ |
|
| 69 | + private $time_format; |
|
| 70 | + |
|
| 71 | + /** |
|
| 72 | + * @var boolean $display_full_ui |
|
| 73 | + */ |
|
| 74 | + private $display_full_ui; |
|
| 75 | + |
|
| 76 | + |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * DisplayTicketSelector constructor. |
|
| 80 | + * |
|
| 81 | + * @param bool $iframe |
|
| 82 | + */ |
|
| 83 | + public function __construct($iframe = false) |
|
| 84 | + { |
|
| 85 | + $this->iframe = $iframe; |
|
| 86 | + $this->date_format = apply_filters( |
|
| 87 | + 'FHEE__EED_Ticket_Selector__display_ticket_selector__date_format', |
|
| 88 | + get_option('date_format') |
|
| 89 | + ); |
|
| 90 | + $this->time_format = apply_filters( |
|
| 91 | + 'FHEE__EED_Ticket_Selector__display_ticket_selector__time_format', |
|
| 92 | + get_option('time_format') |
|
| 93 | + ); |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + |
|
| 97 | + /** |
|
| 98 | + * @return bool |
|
| 99 | + */ |
|
| 100 | + public function isIframe() |
|
| 101 | + { |
|
| 102 | + return $this->iframe; |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + |
|
| 106 | + |
|
| 107 | + /** |
|
| 108 | + * @param boolean $iframe |
|
| 109 | + */ |
|
| 110 | + public function setIframe($iframe = true) |
|
| 111 | + { |
|
| 112 | + $this->iframe = filter_var($iframe, FILTER_VALIDATE_BOOLEAN); |
|
| 113 | + } |
|
| 114 | + |
|
| 115 | + |
|
| 116 | + /** |
|
| 117 | + * finds and sets the \EE_Event object for use throughout class |
|
| 118 | + * |
|
| 119 | + * @param mixed $event |
|
| 120 | + * @return bool |
|
| 121 | + * @throws EE_Error |
|
| 122 | + * @throws InvalidDataTypeException |
|
| 123 | + * @throws InvalidInterfaceException |
|
| 124 | + * @throws InvalidArgumentException |
|
| 125 | + */ |
|
| 126 | + protected function setEvent($event = null) |
|
| 127 | + { |
|
| 128 | + if ($event === null) { |
|
| 129 | + global $post; |
|
| 130 | + $event = $post; |
|
| 131 | + } |
|
| 132 | + if ($event instanceof EE_Event) { |
|
| 133 | + $this->event = $event; |
|
| 134 | + } elseif ($event instanceof WP_Post) { |
|
| 135 | + if (isset($event->EE_Event) && $event->EE_Event instanceof EE_Event) { |
|
| 136 | + $this->event = $event->EE_Event; |
|
| 137 | + } elseif ($event->post_type === 'espresso_events') { |
|
| 138 | + $event->EE_Event = EEM_Event::instance()->instantiate_class_from_post_object($event); |
|
| 139 | + $this->event = $event->EE_Event; |
|
| 140 | + } |
|
| 141 | + } else { |
|
| 142 | + $user_msg = __('No Event object or an invalid Event object was supplied.', 'event_espresso'); |
|
| 143 | + $dev_msg = $user_msg . __( |
|
| 144 | + 'In order to generate a ticket selector, please ensure you are passing either an EE_Event object or a WP_Post object of the post type "espresso_event" to the EE_Ticket_Selector class constructor.', |
|
| 145 | + 'event_espresso' |
|
| 146 | + ); |
|
| 147 | + EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 148 | + return false; |
|
| 149 | + } |
|
| 150 | + return true; |
|
| 151 | + } |
|
| 152 | + |
|
| 153 | + |
|
| 154 | + |
|
| 155 | + /** |
|
| 156 | + * @return int |
|
| 157 | + */ |
|
| 158 | + public function getMaxAttendees() |
|
| 159 | + { |
|
| 160 | + return $this->max_attendees; |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + |
|
| 164 | + |
|
| 165 | + /** |
|
| 166 | + * @param int $max_attendees |
|
| 167 | + */ |
|
| 168 | + public function setMaxAttendees($max_attendees) |
|
| 169 | + { |
|
| 170 | + $this->max_attendees = absint( |
|
| 171 | + apply_filters( |
|
| 172 | + 'FHEE__EE_Ticket_Selector__display_ticket_selector__max_tickets', |
|
| 173 | + $max_attendees |
|
| 174 | + ) |
|
| 175 | + ); |
|
| 176 | + } |
|
| 177 | + |
|
| 178 | + |
|
| 179 | + |
|
| 180 | + /** |
|
| 181 | + * Returns whether or not the full ticket selector should be shown or not. |
|
| 182 | + * Currently, it displays on the frontend (including ajax requests) but not the backend |
|
| 183 | + * |
|
| 184 | + * @return bool |
|
| 185 | + */ |
|
| 186 | + private function display_full_ui() |
|
| 187 | + { |
|
| 188 | + if ($this->display_full_ui === null) { |
|
| 189 | + $this->display_full_ui = ! is_admin() || (defined('DOING_AJAX') && DOING_AJAX); |
|
| 190 | + } |
|
| 191 | + return $this->display_full_ui; |
|
| 192 | + } |
|
| 193 | + |
|
| 194 | + |
|
| 195 | + /** |
|
| 196 | + * creates buttons for selecting number of attendees for an event |
|
| 197 | + * |
|
| 198 | + * @param WP_Post|int $event |
|
| 199 | + * @param bool $view_details |
|
| 200 | + * @return string |
|
| 201 | + * @throws EE_Error |
|
| 202 | + * @throws InvalidArgumentException |
|
| 203 | + * @throws InvalidDataTypeException |
|
| 204 | + * @throws InvalidInterfaceException |
|
| 205 | + */ |
|
| 206 | + public function display($event = null, $view_details = false) |
|
| 207 | + { |
|
| 208 | + // reset filter for displaying submit button |
|
| 209 | + remove_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true'); |
|
| 210 | + // poke and prod incoming event till it tells us what it is |
|
| 211 | + if (! $this->setEvent($event)) { |
|
| 212 | + return false; |
|
| 213 | + } |
|
| 214 | + // begin gathering template arguments by getting event status |
|
| 215 | + $template_args = array('event_status' => $this->event->get_active_status()); |
|
| 216 | + if ( |
|
| 217 | + $this->activeEventAndShowTicketSelector( |
|
| 218 | + $event, |
|
| 219 | + $template_args['event_status'], |
|
| 220 | + $view_details |
|
| 221 | + ) |
|
| 222 | + ) { |
|
| 223 | + return ! is_single() ? $this->displayViewDetailsButton() : ''; |
|
| 224 | + } |
|
| 225 | + // filter the maximum qty that can appear in the Ticket Selector qty dropdowns |
|
| 226 | + $this->setMaxAttendees($this->event->additional_limit()); |
|
| 227 | + if ($this->getMaxAttendees() < 1) { |
|
| 228 | + return $this->ticketSalesClosedMessage(); |
|
| 229 | + } |
|
| 230 | + // is the event expired ? |
|
| 231 | + $template_args['event_is_expired'] = $this->event->is_expired(); |
|
| 232 | + if ($template_args['event_is_expired']) { |
|
| 233 | + return $this->expiredEventMessage(); |
|
| 234 | + } |
|
| 235 | + // get all tickets for this event ordered by the datetime |
|
| 236 | + $tickets = $this->getTickets(); |
|
| 237 | + if (count($tickets) < 1) { |
|
| 238 | + return $this->noTicketAvailableMessage(); |
|
| 239 | + } |
|
| 240 | + // redirecting to another site for registration ?? |
|
| 241 | + $external_url = (string)$this->event->external_url(); |
|
| 242 | + // if redirecting to another site for registration, then we don't load the TS |
|
| 243 | + $ticket_selector = $external_url |
|
| 244 | + ? $this->externalEventRegistration() |
|
| 245 | + : $this->loadTicketSelector($tickets, $template_args); |
|
| 246 | + // now set up the form (but not for the admin) |
|
| 247 | + $ticket_selector = $this->display_full_ui() |
|
| 248 | + ? $this->formOpen($this->event->ID(), $external_url) . $ticket_selector |
|
| 249 | + : $ticket_selector; |
|
| 250 | + // submit button and form close tag |
|
| 251 | + $ticket_selector .= $this->display_full_ui() ? $this->displaySubmitButton($external_url) : ''; |
|
| 252 | + return $ticket_selector; |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + |
|
| 256 | + |
|
| 257 | + /** |
|
| 258 | + * displayTicketSelector |
|
| 259 | + * examines the event properties and determines whether a Ticket Selector should be displayed |
|
| 260 | + * |
|
| 261 | + * @param WP_Post|int $event |
|
| 262 | + * @param string $_event_active_status |
|
| 263 | + * @param bool $view_details |
|
| 264 | + * @return bool |
|
| 265 | + * @throws EE_Error |
|
| 266 | + */ |
|
| 267 | + protected function activeEventAndShowTicketSelector($event, $_event_active_status, $view_details) |
|
| 268 | + { |
|
| 269 | + $event_post = $this->event instanceof EE_Event ? $this->event->ID() : $event; |
|
| 270 | + return $this->display_full_ui() |
|
| 271 | + && ( |
|
| 272 | + ! $this->event->display_ticket_selector() |
|
| 273 | + || $view_details |
|
| 274 | + || post_password_required($event_post) |
|
| 275 | + || ( |
|
| 276 | + $_event_active_status !== EE_Datetime::active |
|
| 277 | + && $_event_active_status !== EE_Datetime::upcoming |
|
| 278 | + && $_event_active_status !== EE_Datetime::sold_out |
|
| 279 | + && ! ( |
|
| 280 | + $_event_active_status === EE_Datetime::inactive |
|
| 281 | + && is_user_logged_in() |
|
| 282 | + ) |
|
| 283 | + ) |
|
| 284 | + ); |
|
| 285 | + } |
|
| 286 | + |
|
| 287 | + |
|
| 288 | + |
|
| 289 | + /** |
|
| 290 | + * noTicketAvailableMessage |
|
| 291 | + * notice displayed if event is expired |
|
| 292 | + * |
|
| 293 | + * @return string |
|
| 294 | + * @throws EE_Error |
|
| 295 | + */ |
|
| 296 | + protected function expiredEventMessage() |
|
| 297 | + { |
|
| 298 | + return '<div class="ee-event-expired-notice"><span class="important-notice">' . esc_html__( |
|
| 299 | + 'We\'re sorry, but all tickets sales have ended because the event is expired.', |
|
| 300 | + 'event_espresso' |
|
| 301 | + ) . '</span></div><!-- .ee-event-expired-notice -->'; |
|
| 302 | + } |
|
| 303 | + |
|
| 304 | + |
|
| 305 | + |
|
| 306 | + /** |
|
| 307 | + * noTicketAvailableMessage |
|
| 308 | + * notice displayed if event has no more tickets available |
|
| 309 | + * |
|
| 310 | + * @return string |
|
| 311 | + * @throws EE_Error |
|
| 312 | + */ |
|
| 313 | + protected function noTicketAvailableMessage() |
|
| 314 | + { |
|
| 315 | + $no_ticket_available_msg = esc_html__('We\'re sorry, but all ticket sales have ended.', 'event_espresso'); |
|
| 316 | + if (current_user_can('edit_post', $this->event->ID())) { |
|
| 317 | + $no_ticket_available_msg .= sprintf( |
|
| 318 | + esc_html__( |
|
| 319 | + '%1$sNote to Event Admin:%2$sNo tickets were found for this event. This effectively turns off ticket sales. Please ensure that at least one ticket is available for if you want people to be able to register.%3$s(click to edit this event)%4$s', |
|
| 320 | + 'event_espresso' |
|
| 321 | + ), |
|
| 322 | + '<div class="ee-attention" style="text-align: left;"><b>', |
|
| 323 | + '</b><br />', |
|
| 324 | + '<span class="edit-link"><a class="post-edit-link" href="' |
|
| 325 | + . get_edit_post_link($this->event->ID()) |
|
| 326 | + . '">', |
|
| 327 | + '</a></span></div><!-- .ee-attention noTicketAvailableMessage -->' |
|
| 328 | + ); |
|
| 329 | + } |
|
| 330 | + return ' |
|
| 331 | 331 | <div class="ee-event-expired-notice"> |
| 332 | 332 | <span class="important-notice">' . $no_ticket_available_msg . '</span> |
| 333 | 333 | </div><!-- .ee-event-expired-notice -->'; |
| 334 | - } |
|
| 335 | - |
|
| 336 | - |
|
| 337 | - |
|
| 338 | - /** |
|
| 339 | - * ticketSalesClosed |
|
| 340 | - * notice displayed if event ticket sales are turned off |
|
| 341 | - * |
|
| 342 | - * @return string |
|
| 343 | - * @throws EE_Error |
|
| 344 | - */ |
|
| 345 | - protected function ticketSalesClosedMessage() |
|
| 346 | - { |
|
| 347 | - $sales_closed_msg = esc_html__( |
|
| 348 | - 'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.', |
|
| 349 | - 'event_espresso' |
|
| 350 | - ); |
|
| 351 | - if (current_user_can('edit_post', $this->event->ID())) { |
|
| 352 | - $sales_closed_msg .= sprintf( |
|
| 353 | - esc_html__( |
|
| 354 | - '%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s', |
|
| 355 | - 'event_espresso' |
|
| 356 | - ), |
|
| 357 | - '<div class="ee-attention" style="text-align: left;"><b>', |
|
| 358 | - '</b><br />', |
|
| 359 | - '<span class="edit-link"><a class="post-edit-link" href="' |
|
| 360 | - . get_edit_post_link($this->event->ID()) |
|
| 361 | - . '">', |
|
| 362 | - '</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->' |
|
| 363 | - ); |
|
| 364 | - } |
|
| 365 | - return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>'; |
|
| 366 | - } |
|
| 367 | - |
|
| 368 | - |
|
| 369 | - |
|
| 370 | - /** |
|
| 371 | - * getTickets |
|
| 372 | - * |
|
| 373 | - * @return \EE_Base_Class[]|\EE_Ticket[] |
|
| 374 | - * @throws EE_Error |
|
| 375 | - * @throws InvalidDataTypeException |
|
| 376 | - * @throws InvalidInterfaceException |
|
| 377 | - * @throws InvalidArgumentException |
|
| 378 | - */ |
|
| 379 | - protected function getTickets() |
|
| 380 | - { |
|
| 381 | - $ticket_query_args = array( |
|
| 382 | - array('Datetime.EVT_ID' => $this->event->ID()), |
|
| 383 | - 'order_by' => array( |
|
| 384 | - 'TKT_order' => 'ASC', |
|
| 385 | - 'TKT_required' => 'DESC', |
|
| 386 | - 'TKT_start_date' => 'ASC', |
|
| 387 | - 'TKT_end_date' => 'ASC', |
|
| 388 | - 'Datetime.DTT_EVT_start' => 'DESC', |
|
| 389 | - ), |
|
| 390 | - ); |
|
| 391 | - if ( |
|
| 392 | - ! ( |
|
| 393 | - EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config |
|
| 394 | - && EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector->show_expired_tickets |
|
| 395 | - ) |
|
| 396 | - ) { |
|
| 397 | - //use the correct applicable time query depending on what version of core is being run. |
|
| 398 | - $current_time = method_exists('EEM_Datetime', 'current_time_for_query') |
|
| 399 | - ? time() |
|
| 400 | - : current_time('timestamp'); |
|
| 401 | - $ticket_query_args[0]['TKT_end_date'] = array('>', $current_time); |
|
| 402 | - } |
|
| 403 | - return EEM_Ticket::instance()->get_all($ticket_query_args); |
|
| 404 | - } |
|
| 405 | - |
|
| 406 | - |
|
| 407 | - |
|
| 408 | - /** |
|
| 409 | - * loadTicketSelector |
|
| 410 | - * begins to assemble template arguments |
|
| 411 | - * and decides whether to load a "simple" ticket selector, or the standard |
|
| 412 | - * |
|
| 413 | - * @param \EE_Ticket[] $tickets |
|
| 414 | - * @param array $template_args |
|
| 415 | - * @return string |
|
| 416 | - * @throws EE_Error |
|
| 417 | - */ |
|
| 418 | - protected function loadTicketSelector(array $tickets, array $template_args) |
|
| 419 | - { |
|
| 420 | - $template_args['event'] = $this->event; |
|
| 421 | - $template_args['EVT_ID'] = $this->event->ID(); |
|
| 422 | - $template_args['event_is_expired'] = $this->event->is_expired(); |
|
| 423 | - $template_args['max_atndz'] = $this->getMaxAttendees(); |
|
| 424 | - $template_args['date_format'] = $this->date_format; |
|
| 425 | - $template_args['time_format'] = $this->time_format; |
|
| 426 | - /** |
|
| 427 | - * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected |
|
| 428 | - * |
|
| 429 | - * @since 4.9.13 |
|
| 430 | - * @param string '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to |
|
| 431 | - * @param int $EVT_ID The Event ID |
|
| 432 | - */ |
|
| 433 | - $template_args['anchor_id'] = apply_filters( |
|
| 434 | - 'FHEE__EE_Ticket_Selector__redirect_anchor_id', |
|
| 435 | - '#tkt-slctr-tbl-' . $this->event->ID(), |
|
| 436 | - $this->event->ID() |
|
| 437 | - ); |
|
| 438 | - $template_args['tickets'] = $tickets; |
|
| 439 | - $template_args['ticket_count'] = count($tickets); |
|
| 440 | - $ticket_selector = $this->simpleTicketSelector($tickets, $template_args); |
|
| 441 | - return $ticket_selector instanceof TicketSelectorSimple |
|
| 442 | - ? $ticket_selector |
|
| 443 | - : new TicketSelectorStandard( |
|
| 444 | - $this->event, |
|
| 445 | - $tickets, |
|
| 446 | - $this->getMaxAttendees(), |
|
| 447 | - $template_args, |
|
| 448 | - $this->date_format, |
|
| 449 | - $this->time_format |
|
| 450 | - ); |
|
| 451 | - } |
|
| 452 | - |
|
| 453 | - |
|
| 454 | - |
|
| 455 | - /** |
|
| 456 | - * simpleTicketSelector |
|
| 457 | - * there's one ticket, and max attendees is set to one, |
|
| 458 | - * so if the event is free, then this is a "simple" ticket selector |
|
| 459 | - * a.k.a. "Dude Where's my Ticket Selector?" |
|
| 460 | - * |
|
| 461 | - * @param \EE_Ticket[] $tickets |
|
| 462 | - * @param array $template_args |
|
| 463 | - * @return string |
|
| 464 | - * @throws EE_Error |
|
| 465 | - */ |
|
| 466 | - protected function simpleTicketSelector($tickets, array $template_args) |
|
| 467 | - { |
|
| 468 | - // if there is only ONE ticket with a max qty of ONE |
|
| 469 | - if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) { |
|
| 470 | - return ''; |
|
| 471 | - } |
|
| 472 | - /** @var \EE_Ticket $ticket */ |
|
| 473 | - $ticket = reset($tickets); |
|
| 474 | - // if the ticket is free... then not much need for the ticket selector |
|
| 475 | - if ( |
|
| 476 | - apply_filters( |
|
| 477 | - 'FHEE__ticket_selector_chart_template__hide_ticket_selector', |
|
| 478 | - $ticket->is_free(), |
|
| 479 | - $this->event->ID() |
|
| 480 | - ) |
|
| 481 | - ) { |
|
| 482 | - return new TicketSelectorSimple( |
|
| 483 | - $this->event, |
|
| 484 | - $ticket, |
|
| 485 | - $this->getMaxAttendees(), |
|
| 486 | - $template_args |
|
| 487 | - ); |
|
| 488 | - } |
|
| 489 | - return ''; |
|
| 490 | - } |
|
| 491 | - |
|
| 492 | - |
|
| 493 | - |
|
| 494 | - /** |
|
| 495 | - * externalEventRegistration |
|
| 496 | - * |
|
| 497 | - * @return string |
|
| 498 | - */ |
|
| 499 | - public function externalEventRegistration() |
|
| 500 | - { |
|
| 501 | - // if not we still need to trigger the display of the submit button |
|
| 502 | - add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true'); |
|
| 503 | - //display notice to admin that registration is external |
|
| 504 | - return $this->display_full_ui() |
|
| 505 | - ? esc_html__( |
|
| 506 | - 'Registration is at an external URL for this event.', |
|
| 507 | - 'event_espresso' |
|
| 508 | - ) |
|
| 509 | - : ''; |
|
| 510 | - } |
|
| 511 | - |
|
| 512 | - |
|
| 513 | - |
|
| 514 | - /** |
|
| 515 | - * formOpen |
|
| 516 | - * |
|
| 517 | - * @param int $ID |
|
| 518 | - * @param string $external_url |
|
| 519 | - * @return string |
|
| 520 | - */ |
|
| 521 | - public function formOpen($ID = 0, $external_url = '') |
|
| 522 | - { |
|
| 523 | - // if redirecting, we don't need any anything else |
|
| 524 | - if ($external_url) { |
|
| 525 | - $html = '<form method="GET" '; |
|
| 526 | - $html .= 'action="' . EEH_URL::refactor_url($external_url) . '" '; |
|
| 527 | - $html .= 'name="ticket-selector-form-' . $ID . '"'; |
|
| 528 | - // open link in new window ? |
|
| 529 | - $html .= apply_filters( |
|
| 530 | - 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank', |
|
| 531 | - $this->isIframe(), |
|
| 532 | - $this |
|
| 533 | - ) |
|
| 534 | - ? ' target="_blank"' |
|
| 535 | - : ''; |
|
| 536 | - $html .= '>'; |
|
| 537 | - $query_args = EEH_URL::get_query_string($external_url); |
|
| 538 | - foreach ((array) $query_args as $query_arg => $value) { |
|
| 539 | - $html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">'; |
|
| 540 | - } |
|
| 541 | - return $html; |
|
| 542 | - } |
|
| 543 | - // if there is no submit button, then don't start building a form |
|
| 544 | - // because the "View Details" button will build its own form |
|
| 545 | - if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) { |
|
| 546 | - return ''; |
|
| 547 | - } |
|
| 548 | - $checkout_url = EEH_Event_View::event_link_url($ID); |
|
| 549 | - if (! $checkout_url) { |
|
| 550 | - EE_Error::add_error( |
|
| 551 | - esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'), |
|
| 552 | - __FILE__, |
|
| 553 | - __FUNCTION__, |
|
| 554 | - __LINE__ |
|
| 555 | - ); |
|
| 556 | - } |
|
| 557 | - // set no cache headers and constants |
|
| 558 | - EE_System::do_not_cache(); |
|
| 559 | - $html = '<form method="POST" '; |
|
| 560 | - $html .= 'action="' . $checkout_url . '" '; |
|
| 561 | - $html .= 'name="ticket-selector-form-' . $ID . '"'; |
|
| 562 | - $html .= $this->iframe ? ' target="_blank"' : ''; |
|
| 563 | - $html .= '>'; |
|
| 564 | - $html .= '<input type="hidden" name="ee" value="process_ticket_selections">'; |
|
| 565 | - $html = apply_filters('FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event); |
|
| 566 | - return $html; |
|
| 567 | - } |
|
| 568 | - |
|
| 569 | - |
|
| 570 | - |
|
| 571 | - /** |
|
| 572 | - * displaySubmitButton |
|
| 573 | - * |
|
| 574 | - * @param string $external_url |
|
| 575 | - * @return string |
|
| 576 | - * @throws EE_Error |
|
| 577 | - */ |
|
| 578 | - public function displaySubmitButton($external_url = '') |
|
| 579 | - { |
|
| 580 | - $html = ''; |
|
| 581 | - if ($this->display_full_ui()) { |
|
| 582 | - // standard TS displayed with submit button, ie: "Register Now" |
|
| 583 | - if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) { |
|
| 584 | - $html .= $this->displayRegisterNowButton(); |
|
| 585 | - $html .= empty($external_url) |
|
| 586 | - ? $this->ticketSelectorEndDiv() |
|
| 587 | - : $this->clearTicketSelector(); |
|
| 588 | - $html .= '<br/>' . $this->formClose(); |
|
| 589 | - } elseif ($this->getMaxAttendees() === 1) { |
|
| 590 | - // its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1) |
|
| 591 | - if ($this->event->is_sold_out()) { |
|
| 592 | - // then instead of a View Details or Submit button, just display a "Sold Out" message |
|
| 593 | - $html .= apply_filters( |
|
| 594 | - 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg', |
|
| 595 | - sprintf( |
|
| 596 | - __( |
|
| 597 | - '%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s', |
|
| 598 | - 'event_espresso' |
|
| 599 | - ), |
|
| 600 | - '<p class="no-ticket-selector-msg clear-float">', |
|
| 601 | - $this->event->name(), |
|
| 602 | - '</p>', |
|
| 603 | - '<br />' |
|
| 604 | - ), |
|
| 605 | - $this->event |
|
| 606 | - ); |
|
| 607 | - if ( |
|
| 608 | - apply_filters( |
|
| 609 | - 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button', |
|
| 610 | - false, |
|
| 611 | - $this->event |
|
| 612 | - ) |
|
| 613 | - ) { |
|
| 614 | - $html .= $this->displayRegisterNowButton(); |
|
| 615 | - } |
|
| 616 | - // sold out DWMTS event, no TS, no submit or view details button, but has additional content |
|
| 617 | - $html .= $this->ticketSelectorEndDiv(); |
|
| 618 | - } elseif ( |
|
| 619 | - apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false) |
|
| 620 | - && ! is_single() |
|
| 621 | - ) { |
|
| 622 | - // this is a "Dude Where's my Ticket Selector?" (DWMTS) type event, |
|
| 623 | - // but no tickets are available, so display event's "View Details" button. |
|
| 624 | - // it is being viewed via somewhere other than a single post |
|
| 625 | - $html .= $this->displayViewDetailsButton(true); |
|
| 626 | - } else { |
|
| 627 | - $html .= $this->ticketSelectorEndDiv(); |
|
| 628 | - } |
|
| 629 | - } elseif (is_archive()) { |
|
| 630 | - // event list, no tickets available so display event's "View Details" button |
|
| 631 | - $html .= $this->ticketSelectorEndDiv(); |
|
| 632 | - $html .= $this->displayViewDetailsButton(); |
|
| 633 | - } else { |
|
| 634 | - if ( |
|
| 635 | - apply_filters( |
|
| 636 | - 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button', |
|
| 637 | - false, |
|
| 638 | - $this->event |
|
| 639 | - ) |
|
| 640 | - ) { |
|
| 641 | - $html .= $this->displayRegisterNowButton(); |
|
| 642 | - } |
|
| 643 | - // no submit or view details button, and no additional content |
|
| 644 | - $html .= $this->ticketSelectorEndDiv(); |
|
| 645 | - } |
|
| 646 | - if (! $this->iframe && ! is_archive()) { |
|
| 647 | - $html .= EEH_Template::powered_by_event_espresso('', '', array('utm_content' => 'ticket_selector')); |
|
| 648 | - } |
|
| 649 | - } |
|
| 650 | - return apply_filters( |
|
| 651 | - 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html', |
|
| 652 | - $html, |
|
| 653 | - $this->event, |
|
| 654 | - $this |
|
| 655 | - ); |
|
| 656 | - } |
|
| 657 | - |
|
| 658 | - |
|
| 659 | - |
|
| 660 | - /** |
|
| 661 | - * @return string |
|
| 662 | - * @throws EE_Error |
|
| 663 | - */ |
|
| 664 | - public function displayRegisterNowButton() |
|
| 665 | - { |
|
| 666 | - $btn_text = apply_filters( |
|
| 667 | - 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text', |
|
| 668 | - __('Register Now', 'event_espresso'), |
|
| 669 | - $this->event |
|
| 670 | - ); |
|
| 671 | - $external_url = $this->event->external_url(); |
|
| 672 | - $html = EEH_HTML::div( |
|
| 673 | - '', |
|
| 674 | - 'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap', |
|
| 675 | - 'ticket-selector-submit-btn-wrap' |
|
| 676 | - ); |
|
| 677 | - $html .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"'; |
|
| 678 | - $html .= ' class="ticket-selector-submit-btn '; |
|
| 679 | - $html .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"'; |
|
| 680 | - $html .= ' type="submit" value="' . $btn_text . '" />'; |
|
| 681 | - $html .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->'; |
|
| 682 | - $html .= apply_filters( |
|
| 683 | - 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
|
| 684 | - '', |
|
| 685 | - $this->event, |
|
| 686 | - $this->iframe |
|
| 687 | - ); |
|
| 688 | - return $html; |
|
| 689 | - } |
|
| 690 | - |
|
| 691 | - |
|
| 692 | - /** |
|
| 693 | - * displayViewDetailsButton |
|
| 694 | - * |
|
| 695 | - * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event |
|
| 696 | - * (ie: $_max_atndz === 1) where there are no available tickets, |
|
| 697 | - * either because they are sold out, expired, or not yet on sale. |
|
| 698 | - * In this case, we need to close the form BEFORE adding any closing divs |
|
| 699 | - * @return string |
|
| 700 | - * @throws EE_Error |
|
| 701 | - */ |
|
| 702 | - public function displayViewDetailsButton($DWMTS = false) |
|
| 703 | - { |
|
| 704 | - if (! $this->event->get_permalink()) { |
|
| 705 | - EE_Error::add_error( |
|
| 706 | - esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'), |
|
| 707 | - __FILE__, |
|
| 708 | - __FUNCTION__, |
|
| 709 | - __LINE__ |
|
| 710 | - ); |
|
| 711 | - } |
|
| 712 | - $view_details_btn = '<form method="POST" action="'; |
|
| 713 | - $view_details_btn .= apply_filters( |
|
| 714 | - 'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url', |
|
| 715 | - $this->event->get_permalink(), |
|
| 716 | - $this->event |
|
| 717 | - ); |
|
| 718 | - $view_details_btn .= '"'; |
|
| 719 | - // open link in new window ? |
|
| 720 | - $view_details_btn .= apply_filters( |
|
| 721 | - 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank', |
|
| 722 | - $this->isIframe(), |
|
| 723 | - $this |
|
| 724 | - ) |
|
| 725 | - ? ' target="_blank"' |
|
| 726 | - : ''; |
|
| 727 | - $view_details_btn .= '>'; |
|
| 728 | - $btn_text = apply_filters( |
|
| 729 | - 'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text', |
|
| 730 | - esc_html__('View Details', 'event_espresso'), |
|
| 731 | - $this->event |
|
| 732 | - ); |
|
| 733 | - $view_details_btn .= '<input id="ticket-selector-submit-' |
|
| 734 | - . $this->event->ID() |
|
| 735 | - . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="' |
|
| 736 | - . $btn_text |
|
| 737 | - . '" />'; |
|
| 738 | - $view_details_btn .= apply_filters('FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event); |
|
| 739 | - if ($DWMTS) { |
|
| 740 | - $view_details_btn .= $this->formClose(); |
|
| 741 | - $view_details_btn .= $this->ticketSelectorEndDiv(); |
|
| 742 | - $view_details_btn .= '<br/>'; |
|
| 743 | - } else { |
|
| 744 | - $view_details_btn .= $this->clearTicketSelector(); |
|
| 745 | - $view_details_btn .= '<br/>'; |
|
| 746 | - $view_details_btn .= $this->formClose(); |
|
| 747 | - } |
|
| 748 | - return $view_details_btn; |
|
| 749 | - } |
|
| 750 | - |
|
| 751 | - |
|
| 752 | - |
|
| 753 | - /** |
|
| 754 | - * @return string |
|
| 755 | - */ |
|
| 756 | - public function ticketSelectorEndDiv() |
|
| 757 | - { |
|
| 758 | - return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->'; |
|
| 759 | - } |
|
| 760 | - |
|
| 761 | - |
|
| 762 | - |
|
| 763 | - /** |
|
| 764 | - * @return string |
|
| 765 | - */ |
|
| 766 | - public function clearTicketSelector() |
|
| 767 | - { |
|
| 768 | - // standard TS displayed, appears after a "Register Now" or "view Details" button |
|
| 769 | - return '<div class="clear"></div><!-- clearTicketSelector -->'; |
|
| 770 | - } |
|
| 771 | - |
|
| 772 | - |
|
| 773 | - |
|
| 774 | - /** |
|
| 775 | - * @access public |
|
| 776 | - * @return string |
|
| 777 | - */ |
|
| 778 | - public function formClose() |
|
| 779 | - { |
|
| 780 | - return '</form>'; |
|
| 781 | - } |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + |
|
| 337 | + |
|
| 338 | + /** |
|
| 339 | + * ticketSalesClosed |
|
| 340 | + * notice displayed if event ticket sales are turned off |
|
| 341 | + * |
|
| 342 | + * @return string |
|
| 343 | + * @throws EE_Error |
|
| 344 | + */ |
|
| 345 | + protected function ticketSalesClosedMessage() |
|
| 346 | + { |
|
| 347 | + $sales_closed_msg = esc_html__( |
|
| 348 | + 'We\'re sorry, but ticket sales have been closed at this time. Please check back again later.', |
|
| 349 | + 'event_espresso' |
|
| 350 | + ); |
|
| 351 | + if (current_user_can('edit_post', $this->event->ID())) { |
|
| 352 | + $sales_closed_msg .= sprintf( |
|
| 353 | + esc_html__( |
|
| 354 | + '%sNote to Event Admin:%sThe "Maximum number of tickets allowed per order for this event" in the Event Registration Options has been set to "0". This effectively turns off ticket sales. %s(click to edit this event)%s', |
|
| 355 | + 'event_espresso' |
|
| 356 | + ), |
|
| 357 | + '<div class="ee-attention" style="text-align: left;"><b>', |
|
| 358 | + '</b><br />', |
|
| 359 | + '<span class="edit-link"><a class="post-edit-link" href="' |
|
| 360 | + . get_edit_post_link($this->event->ID()) |
|
| 361 | + . '">', |
|
| 362 | + '</a></span></div><!-- .ee-attention ticketSalesClosedMessage -->' |
|
| 363 | + ); |
|
| 364 | + } |
|
| 365 | + return '<p><span class="important-notice">' . $sales_closed_msg . '</span></p>'; |
|
| 366 | + } |
|
| 367 | + |
|
| 368 | + |
|
| 369 | + |
|
| 370 | + /** |
|
| 371 | + * getTickets |
|
| 372 | + * |
|
| 373 | + * @return \EE_Base_Class[]|\EE_Ticket[] |
|
| 374 | + * @throws EE_Error |
|
| 375 | + * @throws InvalidDataTypeException |
|
| 376 | + * @throws InvalidInterfaceException |
|
| 377 | + * @throws InvalidArgumentException |
|
| 378 | + */ |
|
| 379 | + protected function getTickets() |
|
| 380 | + { |
|
| 381 | + $ticket_query_args = array( |
|
| 382 | + array('Datetime.EVT_ID' => $this->event->ID()), |
|
| 383 | + 'order_by' => array( |
|
| 384 | + 'TKT_order' => 'ASC', |
|
| 385 | + 'TKT_required' => 'DESC', |
|
| 386 | + 'TKT_start_date' => 'ASC', |
|
| 387 | + 'TKT_end_date' => 'ASC', |
|
| 388 | + 'Datetime.DTT_EVT_start' => 'DESC', |
|
| 389 | + ), |
|
| 390 | + ); |
|
| 391 | + if ( |
|
| 392 | + ! ( |
|
| 393 | + EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config |
|
| 394 | + && EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector->show_expired_tickets |
|
| 395 | + ) |
|
| 396 | + ) { |
|
| 397 | + //use the correct applicable time query depending on what version of core is being run. |
|
| 398 | + $current_time = method_exists('EEM_Datetime', 'current_time_for_query') |
|
| 399 | + ? time() |
|
| 400 | + : current_time('timestamp'); |
|
| 401 | + $ticket_query_args[0]['TKT_end_date'] = array('>', $current_time); |
|
| 402 | + } |
|
| 403 | + return EEM_Ticket::instance()->get_all($ticket_query_args); |
|
| 404 | + } |
|
| 405 | + |
|
| 406 | + |
|
| 407 | + |
|
| 408 | + /** |
|
| 409 | + * loadTicketSelector |
|
| 410 | + * begins to assemble template arguments |
|
| 411 | + * and decides whether to load a "simple" ticket selector, or the standard |
|
| 412 | + * |
|
| 413 | + * @param \EE_Ticket[] $tickets |
|
| 414 | + * @param array $template_args |
|
| 415 | + * @return string |
|
| 416 | + * @throws EE_Error |
|
| 417 | + */ |
|
| 418 | + protected function loadTicketSelector(array $tickets, array $template_args) |
|
| 419 | + { |
|
| 420 | + $template_args['event'] = $this->event; |
|
| 421 | + $template_args['EVT_ID'] = $this->event->ID(); |
|
| 422 | + $template_args['event_is_expired'] = $this->event->is_expired(); |
|
| 423 | + $template_args['max_atndz'] = $this->getMaxAttendees(); |
|
| 424 | + $template_args['date_format'] = $this->date_format; |
|
| 425 | + $template_args['time_format'] = $this->time_format; |
|
| 426 | + /** |
|
| 427 | + * Filters the anchor ID used when redirecting to the Ticket Selector if no quantity selected |
|
| 428 | + * |
|
| 429 | + * @since 4.9.13 |
|
| 430 | + * @param string '#tkt-slctr-tbl-' . $EVT_ID The html ID to anchor to |
|
| 431 | + * @param int $EVT_ID The Event ID |
|
| 432 | + */ |
|
| 433 | + $template_args['anchor_id'] = apply_filters( |
|
| 434 | + 'FHEE__EE_Ticket_Selector__redirect_anchor_id', |
|
| 435 | + '#tkt-slctr-tbl-' . $this->event->ID(), |
|
| 436 | + $this->event->ID() |
|
| 437 | + ); |
|
| 438 | + $template_args['tickets'] = $tickets; |
|
| 439 | + $template_args['ticket_count'] = count($tickets); |
|
| 440 | + $ticket_selector = $this->simpleTicketSelector($tickets, $template_args); |
|
| 441 | + return $ticket_selector instanceof TicketSelectorSimple |
|
| 442 | + ? $ticket_selector |
|
| 443 | + : new TicketSelectorStandard( |
|
| 444 | + $this->event, |
|
| 445 | + $tickets, |
|
| 446 | + $this->getMaxAttendees(), |
|
| 447 | + $template_args, |
|
| 448 | + $this->date_format, |
|
| 449 | + $this->time_format |
|
| 450 | + ); |
|
| 451 | + } |
|
| 452 | + |
|
| 453 | + |
|
| 454 | + |
|
| 455 | + /** |
|
| 456 | + * simpleTicketSelector |
|
| 457 | + * there's one ticket, and max attendees is set to one, |
|
| 458 | + * so if the event is free, then this is a "simple" ticket selector |
|
| 459 | + * a.k.a. "Dude Where's my Ticket Selector?" |
|
| 460 | + * |
|
| 461 | + * @param \EE_Ticket[] $tickets |
|
| 462 | + * @param array $template_args |
|
| 463 | + * @return string |
|
| 464 | + * @throws EE_Error |
|
| 465 | + */ |
|
| 466 | + protected function simpleTicketSelector($tickets, array $template_args) |
|
| 467 | + { |
|
| 468 | + // if there is only ONE ticket with a max qty of ONE |
|
| 469 | + if (count($tickets) > 1 || $this->getMaxAttendees() !== 1) { |
|
| 470 | + return ''; |
|
| 471 | + } |
|
| 472 | + /** @var \EE_Ticket $ticket */ |
|
| 473 | + $ticket = reset($tickets); |
|
| 474 | + // if the ticket is free... then not much need for the ticket selector |
|
| 475 | + if ( |
|
| 476 | + apply_filters( |
|
| 477 | + 'FHEE__ticket_selector_chart_template__hide_ticket_selector', |
|
| 478 | + $ticket->is_free(), |
|
| 479 | + $this->event->ID() |
|
| 480 | + ) |
|
| 481 | + ) { |
|
| 482 | + return new TicketSelectorSimple( |
|
| 483 | + $this->event, |
|
| 484 | + $ticket, |
|
| 485 | + $this->getMaxAttendees(), |
|
| 486 | + $template_args |
|
| 487 | + ); |
|
| 488 | + } |
|
| 489 | + return ''; |
|
| 490 | + } |
|
| 491 | + |
|
| 492 | + |
|
| 493 | + |
|
| 494 | + /** |
|
| 495 | + * externalEventRegistration |
|
| 496 | + * |
|
| 497 | + * @return string |
|
| 498 | + */ |
|
| 499 | + public function externalEventRegistration() |
|
| 500 | + { |
|
| 501 | + // if not we still need to trigger the display of the submit button |
|
| 502 | + add_filter('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', '__return_true'); |
|
| 503 | + //display notice to admin that registration is external |
|
| 504 | + return $this->display_full_ui() |
|
| 505 | + ? esc_html__( |
|
| 506 | + 'Registration is at an external URL for this event.', |
|
| 507 | + 'event_espresso' |
|
| 508 | + ) |
|
| 509 | + : ''; |
|
| 510 | + } |
|
| 511 | + |
|
| 512 | + |
|
| 513 | + |
|
| 514 | + /** |
|
| 515 | + * formOpen |
|
| 516 | + * |
|
| 517 | + * @param int $ID |
|
| 518 | + * @param string $external_url |
|
| 519 | + * @return string |
|
| 520 | + */ |
|
| 521 | + public function formOpen($ID = 0, $external_url = '') |
|
| 522 | + { |
|
| 523 | + // if redirecting, we don't need any anything else |
|
| 524 | + if ($external_url) { |
|
| 525 | + $html = '<form method="GET" '; |
|
| 526 | + $html .= 'action="' . EEH_URL::refactor_url($external_url) . '" '; |
|
| 527 | + $html .= 'name="ticket-selector-form-' . $ID . '"'; |
|
| 528 | + // open link in new window ? |
|
| 529 | + $html .= apply_filters( |
|
| 530 | + 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__formOpen__external_url_target_blank', |
|
| 531 | + $this->isIframe(), |
|
| 532 | + $this |
|
| 533 | + ) |
|
| 534 | + ? ' target="_blank"' |
|
| 535 | + : ''; |
|
| 536 | + $html .= '>'; |
|
| 537 | + $query_args = EEH_URL::get_query_string($external_url); |
|
| 538 | + foreach ((array) $query_args as $query_arg => $value) { |
|
| 539 | + $html .= '<input type="hidden" name="' . $query_arg . '" value="' . $value . '">'; |
|
| 540 | + } |
|
| 541 | + return $html; |
|
| 542 | + } |
|
| 543 | + // if there is no submit button, then don't start building a form |
|
| 544 | + // because the "View Details" button will build its own form |
|
| 545 | + if (! apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) { |
|
| 546 | + return ''; |
|
| 547 | + } |
|
| 548 | + $checkout_url = EEH_Event_View::event_link_url($ID); |
|
| 549 | + if (! $checkout_url) { |
|
| 550 | + EE_Error::add_error( |
|
| 551 | + esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'), |
|
| 552 | + __FILE__, |
|
| 553 | + __FUNCTION__, |
|
| 554 | + __LINE__ |
|
| 555 | + ); |
|
| 556 | + } |
|
| 557 | + // set no cache headers and constants |
|
| 558 | + EE_System::do_not_cache(); |
|
| 559 | + $html = '<form method="POST" '; |
|
| 560 | + $html .= 'action="' . $checkout_url . '" '; |
|
| 561 | + $html .= 'name="ticket-selector-form-' . $ID . '"'; |
|
| 562 | + $html .= $this->iframe ? ' target="_blank"' : ''; |
|
| 563 | + $html .= '>'; |
|
| 564 | + $html .= '<input type="hidden" name="ee" value="process_ticket_selections">'; |
|
| 565 | + $html = apply_filters('FHEE__EE_Ticket_Selector__ticket_selector_form_open__html', $html, $this->event); |
|
| 566 | + return $html; |
|
| 567 | + } |
|
| 568 | + |
|
| 569 | + |
|
| 570 | + |
|
| 571 | + /** |
|
| 572 | + * displaySubmitButton |
|
| 573 | + * |
|
| 574 | + * @param string $external_url |
|
| 575 | + * @return string |
|
| 576 | + * @throws EE_Error |
|
| 577 | + */ |
|
| 578 | + public function displaySubmitButton($external_url = '') |
|
| 579 | + { |
|
| 580 | + $html = ''; |
|
| 581 | + if ($this->display_full_ui()) { |
|
| 582 | + // standard TS displayed with submit button, ie: "Register Now" |
|
| 583 | + if (apply_filters('FHEE__EE_Ticket_Selector__display_ticket_selector_submit', false)) { |
|
| 584 | + $html .= $this->displayRegisterNowButton(); |
|
| 585 | + $html .= empty($external_url) |
|
| 586 | + ? $this->ticketSelectorEndDiv() |
|
| 587 | + : $this->clearTicketSelector(); |
|
| 588 | + $html .= '<br/>' . $this->formClose(); |
|
| 589 | + } elseif ($this->getMaxAttendees() === 1) { |
|
| 590 | + // its a "Dude Where's my Ticket Selector?" (DWMTS) type event (ie: $_max_atndz === 1) |
|
| 591 | + if ($this->event->is_sold_out()) { |
|
| 592 | + // then instead of a View Details or Submit button, just display a "Sold Out" message |
|
| 593 | + $html .= apply_filters( |
|
| 594 | + 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__sold_out_msg', |
|
| 595 | + sprintf( |
|
| 596 | + __( |
|
| 597 | + '%1$s"%2$s" is currently sold out.%4$sPlease check back again later, as spots may become available.%3$s', |
|
| 598 | + 'event_espresso' |
|
| 599 | + ), |
|
| 600 | + '<p class="no-ticket-selector-msg clear-float">', |
|
| 601 | + $this->event->name(), |
|
| 602 | + '</p>', |
|
| 603 | + '<br />' |
|
| 604 | + ), |
|
| 605 | + $this->event |
|
| 606 | + ); |
|
| 607 | + if ( |
|
| 608 | + apply_filters( |
|
| 609 | + 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button', |
|
| 610 | + false, |
|
| 611 | + $this->event |
|
| 612 | + ) |
|
| 613 | + ) { |
|
| 614 | + $html .= $this->displayRegisterNowButton(); |
|
| 615 | + } |
|
| 616 | + // sold out DWMTS event, no TS, no submit or view details button, but has additional content |
|
| 617 | + $html .= $this->ticketSelectorEndDiv(); |
|
| 618 | + } elseif ( |
|
| 619 | + apply_filters('FHEE__EE_Ticket_Selector__hide_ticket_selector', false) |
|
| 620 | + && ! is_single() |
|
| 621 | + ) { |
|
| 622 | + // this is a "Dude Where's my Ticket Selector?" (DWMTS) type event, |
|
| 623 | + // but no tickets are available, so display event's "View Details" button. |
|
| 624 | + // it is being viewed via somewhere other than a single post |
|
| 625 | + $html .= $this->displayViewDetailsButton(true); |
|
| 626 | + } else { |
|
| 627 | + $html .= $this->ticketSelectorEndDiv(); |
|
| 628 | + } |
|
| 629 | + } elseif (is_archive()) { |
|
| 630 | + // event list, no tickets available so display event's "View Details" button |
|
| 631 | + $html .= $this->ticketSelectorEndDiv(); |
|
| 632 | + $html .= $this->displayViewDetailsButton(); |
|
| 633 | + } else { |
|
| 634 | + if ( |
|
| 635 | + apply_filters( |
|
| 636 | + 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__no_tickets_but_display_register_now_button', |
|
| 637 | + false, |
|
| 638 | + $this->event |
|
| 639 | + ) |
|
| 640 | + ) { |
|
| 641 | + $html .= $this->displayRegisterNowButton(); |
|
| 642 | + } |
|
| 643 | + // no submit or view details button, and no additional content |
|
| 644 | + $html .= $this->ticketSelectorEndDiv(); |
|
| 645 | + } |
|
| 646 | + if (! $this->iframe && ! is_archive()) { |
|
| 647 | + $html .= EEH_Template::powered_by_event_espresso('', '', array('utm_content' => 'ticket_selector')); |
|
| 648 | + } |
|
| 649 | + } |
|
| 650 | + return apply_filters( |
|
| 651 | + 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displaySubmitButton__html', |
|
| 652 | + $html, |
|
| 653 | + $this->event, |
|
| 654 | + $this |
|
| 655 | + ); |
|
| 656 | + } |
|
| 657 | + |
|
| 658 | + |
|
| 659 | + |
|
| 660 | + /** |
|
| 661 | + * @return string |
|
| 662 | + * @throws EE_Error |
|
| 663 | + */ |
|
| 664 | + public function displayRegisterNowButton() |
|
| 665 | + { |
|
| 666 | + $btn_text = apply_filters( |
|
| 667 | + 'FHEE__EE_Ticket_Selector__display_ticket_selector_submit__btn_text', |
|
| 668 | + __('Register Now', 'event_espresso'), |
|
| 669 | + $this->event |
|
| 670 | + ); |
|
| 671 | + $external_url = $this->event->external_url(); |
|
| 672 | + $html = EEH_HTML::div( |
|
| 673 | + '', |
|
| 674 | + 'ticket-selector-submit-' . $this->event->ID() . '-btn-wrap', |
|
| 675 | + 'ticket-selector-submit-btn-wrap' |
|
| 676 | + ); |
|
| 677 | + $html .= '<input id="ticket-selector-submit-' . $this->event->ID() . '-btn"'; |
|
| 678 | + $html .= ' class="ticket-selector-submit-btn '; |
|
| 679 | + $html .= empty($external_url) ? 'ticket-selector-submit-ajax"' : '"'; |
|
| 680 | + $html .= ' type="submit" value="' . $btn_text . '" />'; |
|
| 681 | + $html .= EEH_HTML::divx() . '<!-- .ticket-selector-submit-btn-wrap -->'; |
|
| 682 | + $html .= apply_filters( |
|
| 683 | + 'FHEE__EE_Ticket_Selector__after_ticket_selector_submit', |
|
| 684 | + '', |
|
| 685 | + $this->event, |
|
| 686 | + $this->iframe |
|
| 687 | + ); |
|
| 688 | + return $html; |
|
| 689 | + } |
|
| 690 | + |
|
| 691 | + |
|
| 692 | + /** |
|
| 693 | + * displayViewDetailsButton |
|
| 694 | + * |
|
| 695 | + * @param bool $DWMTS indicates a "Dude Where's my Ticket Selector?" (DWMTS) type event |
|
| 696 | + * (ie: $_max_atndz === 1) where there are no available tickets, |
|
| 697 | + * either because they are sold out, expired, or not yet on sale. |
|
| 698 | + * In this case, we need to close the form BEFORE adding any closing divs |
|
| 699 | + * @return string |
|
| 700 | + * @throws EE_Error |
|
| 701 | + */ |
|
| 702 | + public function displayViewDetailsButton($DWMTS = false) |
|
| 703 | + { |
|
| 704 | + if (! $this->event->get_permalink()) { |
|
| 705 | + EE_Error::add_error( |
|
| 706 | + esc_html__('The URL for the Event Details page could not be retrieved.', 'event_espresso'), |
|
| 707 | + __FILE__, |
|
| 708 | + __FUNCTION__, |
|
| 709 | + __LINE__ |
|
| 710 | + ); |
|
| 711 | + } |
|
| 712 | + $view_details_btn = '<form method="POST" action="'; |
|
| 713 | + $view_details_btn .= apply_filters( |
|
| 714 | + 'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_url', |
|
| 715 | + $this->event->get_permalink(), |
|
| 716 | + $this->event |
|
| 717 | + ); |
|
| 718 | + $view_details_btn .= '"'; |
|
| 719 | + // open link in new window ? |
|
| 720 | + $view_details_btn .= apply_filters( |
|
| 721 | + 'FHEE__EventEspresso_modules_ticket_selector_DisplayTicketSelector__displayViewDetailsButton__url_target_blank', |
|
| 722 | + $this->isIframe(), |
|
| 723 | + $this |
|
| 724 | + ) |
|
| 725 | + ? ' target="_blank"' |
|
| 726 | + : ''; |
|
| 727 | + $view_details_btn .= '>'; |
|
| 728 | + $btn_text = apply_filters( |
|
| 729 | + 'FHEE__EE_Ticket_Selector__display_view_details_btn__btn_text', |
|
| 730 | + esc_html__('View Details', 'event_espresso'), |
|
| 731 | + $this->event |
|
| 732 | + ); |
|
| 733 | + $view_details_btn .= '<input id="ticket-selector-submit-' |
|
| 734 | + . $this->event->ID() |
|
| 735 | + . '-btn" class="ticket-selector-submit-btn view-details-btn" type="submit" value="' |
|
| 736 | + . $btn_text |
|
| 737 | + . '" />'; |
|
| 738 | + $view_details_btn .= apply_filters('FHEE__EE_Ticket_Selector__after_view_details_btn', '', $this->event); |
|
| 739 | + if ($DWMTS) { |
|
| 740 | + $view_details_btn .= $this->formClose(); |
|
| 741 | + $view_details_btn .= $this->ticketSelectorEndDiv(); |
|
| 742 | + $view_details_btn .= '<br/>'; |
|
| 743 | + } else { |
|
| 744 | + $view_details_btn .= $this->clearTicketSelector(); |
|
| 745 | + $view_details_btn .= '<br/>'; |
|
| 746 | + $view_details_btn .= $this->formClose(); |
|
| 747 | + } |
|
| 748 | + return $view_details_btn; |
|
| 749 | + } |
|
| 750 | + |
|
| 751 | + |
|
| 752 | + |
|
| 753 | + /** |
|
| 754 | + * @return string |
|
| 755 | + */ |
|
| 756 | + public function ticketSelectorEndDiv() |
|
| 757 | + { |
|
| 758 | + return $this->clearTicketSelector() . '</div><!-- ticketSelectorEndDiv -->'; |
|
| 759 | + } |
|
| 760 | + |
|
| 761 | + |
|
| 762 | + |
|
| 763 | + /** |
|
| 764 | + * @return string |
|
| 765 | + */ |
|
| 766 | + public function clearTicketSelector() |
|
| 767 | + { |
|
| 768 | + // standard TS displayed, appears after a "Register Now" or "view Details" button |
|
| 769 | + return '<div class="clear"></div><!-- clearTicketSelector -->'; |
|
| 770 | + } |
|
| 771 | + |
|
| 772 | + |
|
| 773 | + |
|
| 774 | + /** |
|
| 775 | + * @access public |
|
| 776 | + * @return string |
|
| 777 | + */ |
|
| 778 | + public function formClose() |
|
| 779 | + { |
|
| 780 | + return '</form>'; |
|
| 781 | + } |
|
| 782 | 782 | |
| 783 | 783 | |
| 784 | 784 | |
@@ -14,262 +14,262 @@ |
||
| 14 | 14 | class EEH_URL |
| 15 | 15 | { |
| 16 | 16 | |
| 17 | - /** |
|
| 18 | - * _add_query_arg |
|
| 19 | - * adds nonce to array of arguments then calls WP add_query_arg function |
|
| 20 | - * |
|
| 21 | - * @access public |
|
| 22 | - * @param array $args |
|
| 23 | - * @param string $url |
|
| 24 | - * @param bool $exclude_nonce If true then the nonce will be excluded from the generated url. |
|
| 25 | - * @return string |
|
| 26 | - */ |
|
| 27 | - public static function add_query_args_and_nonce($args = array(), $url = '', $exclude_nonce = false) |
|
| 28 | - { |
|
| 29 | - if (empty($url)) { |
|
| 30 | - $user_msg = esc_html__( |
|
| 31 | - 'An error occurred. A URL is a required parameter for the add_query_args_and_nonce method.', |
|
| 32 | - 'event_espresso' |
|
| 33 | - ); |
|
| 34 | - $dev_msg = $user_msg . "\n" |
|
| 35 | - . sprintf( |
|
| 36 | - esc_html__( |
|
| 37 | - 'In order to dynamically generate nonces for your actions, you need to supply a valid URL as a second parameter for the %s method.', |
|
| 38 | - 'event_espresso' |
|
| 39 | - ), |
|
| 40 | - __CLASS__ . '::add_query_args_and_nonce' |
|
| 41 | - ); |
|
| 42 | - EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 43 | - } |
|
| 44 | - // check that an action exists and add nonce |
|
| 45 | - if (! $exclude_nonce) { |
|
| 46 | - if (isset($args['action']) && ! empty($args['action'])) { |
|
| 47 | - $args = array_merge( |
|
| 48 | - $args, |
|
| 49 | - array( |
|
| 50 | - $args['action'] . '_nonce' => wp_create_nonce($args['action'] . '_nonce') |
|
| 51 | - ) |
|
| 52 | - ); |
|
| 53 | - } else { |
|
| 54 | - $args = array_merge( |
|
| 55 | - $args, |
|
| 56 | - array( |
|
| 57 | - 'action' => 'default', 'default_nonce' => wp_create_nonce('default_nonce') |
|
| 58 | - ) |
|
| 59 | - ); |
|
| 60 | - } |
|
| 61 | - } |
|
| 17 | + /** |
|
| 18 | + * _add_query_arg |
|
| 19 | + * adds nonce to array of arguments then calls WP add_query_arg function |
|
| 20 | + * |
|
| 21 | + * @access public |
|
| 22 | + * @param array $args |
|
| 23 | + * @param string $url |
|
| 24 | + * @param bool $exclude_nonce If true then the nonce will be excluded from the generated url. |
|
| 25 | + * @return string |
|
| 26 | + */ |
|
| 27 | + public static function add_query_args_and_nonce($args = array(), $url = '', $exclude_nonce = false) |
|
| 28 | + { |
|
| 29 | + if (empty($url)) { |
|
| 30 | + $user_msg = esc_html__( |
|
| 31 | + 'An error occurred. A URL is a required parameter for the add_query_args_and_nonce method.', |
|
| 32 | + 'event_espresso' |
|
| 33 | + ); |
|
| 34 | + $dev_msg = $user_msg . "\n" |
|
| 35 | + . sprintf( |
|
| 36 | + esc_html__( |
|
| 37 | + 'In order to dynamically generate nonces for your actions, you need to supply a valid URL as a second parameter for the %s method.', |
|
| 38 | + 'event_espresso' |
|
| 39 | + ), |
|
| 40 | + __CLASS__ . '::add_query_args_and_nonce' |
|
| 41 | + ); |
|
| 42 | + EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 43 | + } |
|
| 44 | + // check that an action exists and add nonce |
|
| 45 | + if (! $exclude_nonce) { |
|
| 46 | + if (isset($args['action']) && ! empty($args['action'])) { |
|
| 47 | + $args = array_merge( |
|
| 48 | + $args, |
|
| 49 | + array( |
|
| 50 | + $args['action'] . '_nonce' => wp_create_nonce($args['action'] . '_nonce') |
|
| 51 | + ) |
|
| 52 | + ); |
|
| 53 | + } else { |
|
| 54 | + $args = array_merge( |
|
| 55 | + $args, |
|
| 56 | + array( |
|
| 57 | + 'action' => 'default', 'default_nonce' => wp_create_nonce('default_nonce') |
|
| 58 | + ) |
|
| 59 | + ); |
|
| 60 | + } |
|
| 61 | + } |
|
| 62 | 62 | |
| 63 | - //finally, let's always add a return address (if present) :) |
|
| 64 | - $args = ! empty($_REQUEST['action']) && ! isset($_REQUEST['return']) |
|
| 65 | - ? array_merge($args, array('return' => $_REQUEST['action'])) |
|
| 66 | - : $args; |
|
| 63 | + //finally, let's always add a return address (if present) :) |
|
| 64 | + $args = ! empty($_REQUEST['action']) && ! isset($_REQUEST['return']) |
|
| 65 | + ? array_merge($args, array('return' => $_REQUEST['action'])) |
|
| 66 | + : $args; |
|
| 67 | 67 | |
| 68 | - return add_query_arg($args, $url); |
|
| 69 | - } |
|
| 68 | + return add_query_arg($args, $url); |
|
| 69 | + } |
|
| 70 | 70 | |
| 71 | 71 | |
| 72 | - /** |
|
| 73 | - * Returns whether not the remote file exists. |
|
| 74 | - * Checking via GET because HEAD requests are blocked on some server configurations. |
|
| 75 | - * |
|
| 76 | - * @param string $url |
|
| 77 | - * @param array $args the arguments that should be passed through to the wp_remote_request call. |
|
| 78 | - * @return boolean |
|
| 79 | - */ |
|
| 80 | - public static function remote_file_exists($url, $args = array()) |
|
| 81 | - { |
|
| 82 | - $results = wp_remote_request( |
|
| 83 | - $url, |
|
| 84 | - array_merge( |
|
| 85 | - array( |
|
| 86 | - 'method' => 'GET', |
|
| 87 | - 'redirection' => 1, |
|
| 88 | - ), |
|
| 89 | - $args |
|
| 90 | - ) |
|
| 91 | - ); |
|
| 92 | - if (! $results instanceof WP_Error && |
|
| 93 | - isset($results['response']) && |
|
| 94 | - isset($results['response']['code']) && |
|
| 95 | - $results['response']['code'] == '200') { |
|
| 96 | - return true; |
|
| 97 | - } else { |
|
| 98 | - return false; |
|
| 99 | - } |
|
| 100 | - } |
|
| 72 | + /** |
|
| 73 | + * Returns whether not the remote file exists. |
|
| 74 | + * Checking via GET because HEAD requests are blocked on some server configurations. |
|
| 75 | + * |
|
| 76 | + * @param string $url |
|
| 77 | + * @param array $args the arguments that should be passed through to the wp_remote_request call. |
|
| 78 | + * @return boolean |
|
| 79 | + */ |
|
| 80 | + public static function remote_file_exists($url, $args = array()) |
|
| 81 | + { |
|
| 82 | + $results = wp_remote_request( |
|
| 83 | + $url, |
|
| 84 | + array_merge( |
|
| 85 | + array( |
|
| 86 | + 'method' => 'GET', |
|
| 87 | + 'redirection' => 1, |
|
| 88 | + ), |
|
| 89 | + $args |
|
| 90 | + ) |
|
| 91 | + ); |
|
| 92 | + if (! $results instanceof WP_Error && |
|
| 93 | + isset($results['response']) && |
|
| 94 | + isset($results['response']['code']) && |
|
| 95 | + $results['response']['code'] == '200') { |
|
| 96 | + return true; |
|
| 97 | + } else { |
|
| 98 | + return false; |
|
| 99 | + } |
|
| 100 | + } |
|
| 101 | 101 | |
| 102 | 102 | |
| 103 | - /** |
|
| 104 | - * refactor_url |
|
| 105 | - * primarily used for removing the query string from a URL |
|
| 106 | - * |
|
| 107 | - * @param string $url |
|
| 108 | - * @param bool $remove_query - TRUE (default) will strip off any URL params, ie: ?this=1&that=2 |
|
| 109 | - * @param bool $base_url_only - TRUE will only return the scheme and host with no other parameters |
|
| 110 | - * @return string |
|
| 111 | - */ |
|
| 112 | - public static function refactor_url($url = '', $remove_query = true, $base_url_only = false) |
|
| 113 | - { |
|
| 114 | - // break apart incoming URL |
|
| 115 | - $url_bits = parse_url($url); |
|
| 116 | - // HTTP or HTTPS ? |
|
| 117 | - $scheme = isset($url_bits['scheme']) ? $url_bits['scheme'] . '://' : 'http://'; |
|
| 118 | - // domain |
|
| 119 | - $host = isset($url_bits['host']) ? $url_bits['host'] : ''; |
|
| 120 | - // if only the base URL is requested, then return that now |
|
| 121 | - if ($base_url_only) { |
|
| 122 | - return $scheme . $host; |
|
| 123 | - } |
|
| 124 | - $port = isset($url_bits['port']) ? ':' . $url_bits['port'] : ''; |
|
| 125 | - $user = isset($url_bits['user']) ? $url_bits['user'] : ''; |
|
| 126 | - $pass = isset($url_bits['pass']) ? ':' . $url_bits['pass'] : ''; |
|
| 127 | - $pass = ($user || $pass) ? $pass . '@' : ''; |
|
| 128 | - $path = isset($url_bits['path']) ? $url_bits['path'] : ''; |
|
| 129 | - // if the query string is not required, then return what we have so far |
|
| 130 | - if ($remove_query) { |
|
| 131 | - return $scheme . $user . $pass . $host . $port . $path; |
|
| 132 | - } |
|
| 133 | - $query = isset($url_bits['query']) ? '?' . $url_bits['query'] : ''; |
|
| 134 | - $fragment = isset($url_bits['fragment']) ? '#' . $url_bits['fragment'] : ''; |
|
| 135 | - return $scheme . $user . $pass . $host . $port . $path . $query . $fragment; |
|
| 136 | - } |
|
| 103 | + /** |
|
| 104 | + * refactor_url |
|
| 105 | + * primarily used for removing the query string from a URL |
|
| 106 | + * |
|
| 107 | + * @param string $url |
|
| 108 | + * @param bool $remove_query - TRUE (default) will strip off any URL params, ie: ?this=1&that=2 |
|
| 109 | + * @param bool $base_url_only - TRUE will only return the scheme and host with no other parameters |
|
| 110 | + * @return string |
|
| 111 | + */ |
|
| 112 | + public static function refactor_url($url = '', $remove_query = true, $base_url_only = false) |
|
| 113 | + { |
|
| 114 | + // break apart incoming URL |
|
| 115 | + $url_bits = parse_url($url); |
|
| 116 | + // HTTP or HTTPS ? |
|
| 117 | + $scheme = isset($url_bits['scheme']) ? $url_bits['scheme'] . '://' : 'http://'; |
|
| 118 | + // domain |
|
| 119 | + $host = isset($url_bits['host']) ? $url_bits['host'] : ''; |
|
| 120 | + // if only the base URL is requested, then return that now |
|
| 121 | + if ($base_url_only) { |
|
| 122 | + return $scheme . $host; |
|
| 123 | + } |
|
| 124 | + $port = isset($url_bits['port']) ? ':' . $url_bits['port'] : ''; |
|
| 125 | + $user = isset($url_bits['user']) ? $url_bits['user'] : ''; |
|
| 126 | + $pass = isset($url_bits['pass']) ? ':' . $url_bits['pass'] : ''; |
|
| 127 | + $pass = ($user || $pass) ? $pass . '@' : ''; |
|
| 128 | + $path = isset($url_bits['path']) ? $url_bits['path'] : ''; |
|
| 129 | + // if the query string is not required, then return what we have so far |
|
| 130 | + if ($remove_query) { |
|
| 131 | + return $scheme . $user . $pass . $host . $port . $path; |
|
| 132 | + } |
|
| 133 | + $query = isset($url_bits['query']) ? '?' . $url_bits['query'] : ''; |
|
| 134 | + $fragment = isset($url_bits['fragment']) ? '#' . $url_bits['fragment'] : ''; |
|
| 135 | + return $scheme . $user . $pass . $host . $port . $path . $query . $fragment; |
|
| 136 | + } |
|
| 137 | 137 | |
| 138 | 138 | |
| 139 | - /** |
|
| 140 | - * get_query_string |
|
| 141 | - * returns just the query string from a URL, formatted by default into an array of key value pairs |
|
| 142 | - * |
|
| 143 | - * @param string $url |
|
| 144 | - * @param bool $as_array TRUE (default) will return query params as an array of key value pairs, FALSE will |
|
| 145 | - * simply return the query string |
|
| 146 | - * @return string|array |
|
| 147 | - */ |
|
| 148 | - public static function get_query_string($url = '', $as_array = true) |
|
| 149 | - { |
|
| 150 | - // decode, then break apart incoming URL |
|
| 151 | - $url_bits = parse_url(html_entity_decode($url)); |
|
| 152 | - // grab query string from URL |
|
| 153 | - $query = isset($url_bits['query']) ? $url_bits['query'] : ''; |
|
| 154 | - // if we don't want the query string formatted into an array of key => value pairs, then just return it as is |
|
| 155 | - if (! $as_array) { |
|
| 156 | - return $query; |
|
| 157 | - } |
|
| 158 | - // if no query string exists then just return an empty array now |
|
| 159 | - if (empty($query)) { |
|
| 160 | - return array(); |
|
| 161 | - } |
|
| 162 | - // empty array to hold results |
|
| 163 | - $query_params = array(); |
|
| 164 | - // now break apart the query string into separate params |
|
| 165 | - $query = explode('&', $query); |
|
| 166 | - // loop thru our query params |
|
| 167 | - foreach ($query as $query_args) { |
|
| 168 | - // break apart the key value pairs |
|
| 169 | - $query_args = explode('=', $query_args); |
|
| 170 | - // and add to our results array |
|
| 171 | - $query_params[$query_args[0]] = $query_args[1]; |
|
| 172 | - } |
|
| 173 | - return $query_params; |
|
| 174 | - } |
|
| 139 | + /** |
|
| 140 | + * get_query_string |
|
| 141 | + * returns just the query string from a URL, formatted by default into an array of key value pairs |
|
| 142 | + * |
|
| 143 | + * @param string $url |
|
| 144 | + * @param bool $as_array TRUE (default) will return query params as an array of key value pairs, FALSE will |
|
| 145 | + * simply return the query string |
|
| 146 | + * @return string|array |
|
| 147 | + */ |
|
| 148 | + public static function get_query_string($url = '', $as_array = true) |
|
| 149 | + { |
|
| 150 | + // decode, then break apart incoming URL |
|
| 151 | + $url_bits = parse_url(html_entity_decode($url)); |
|
| 152 | + // grab query string from URL |
|
| 153 | + $query = isset($url_bits['query']) ? $url_bits['query'] : ''; |
|
| 154 | + // if we don't want the query string formatted into an array of key => value pairs, then just return it as is |
|
| 155 | + if (! $as_array) { |
|
| 156 | + return $query; |
|
| 157 | + } |
|
| 158 | + // if no query string exists then just return an empty array now |
|
| 159 | + if (empty($query)) { |
|
| 160 | + return array(); |
|
| 161 | + } |
|
| 162 | + // empty array to hold results |
|
| 163 | + $query_params = array(); |
|
| 164 | + // now break apart the query string into separate params |
|
| 165 | + $query = explode('&', $query); |
|
| 166 | + // loop thru our query params |
|
| 167 | + foreach ($query as $query_args) { |
|
| 168 | + // break apart the key value pairs |
|
| 169 | + $query_args = explode('=', $query_args); |
|
| 170 | + // and add to our results array |
|
| 171 | + $query_params[$query_args[0]] = $query_args[1]; |
|
| 172 | + } |
|
| 173 | + return $query_params; |
|
| 174 | + } |
|
| 175 | 175 | |
| 176 | 176 | |
| 177 | - /** |
|
| 178 | - * prevent_prefetching |
|
| 179 | - * |
|
| 180 | - * @return void |
|
| 181 | - */ |
|
| 182 | - public static function prevent_prefetching() |
|
| 183 | - { |
|
| 184 | - // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes |
|
| 185 | - // with the registration process |
|
| 186 | - remove_action('wp_head', 'adjacent_posts_rel_link_wp_head'); |
|
| 187 | - } |
|
| 177 | + /** |
|
| 178 | + * prevent_prefetching |
|
| 179 | + * |
|
| 180 | + * @return void |
|
| 181 | + */ |
|
| 182 | + public static function prevent_prefetching() |
|
| 183 | + { |
|
| 184 | + // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes |
|
| 185 | + // with the registration process |
|
| 186 | + remove_action('wp_head', 'adjacent_posts_rel_link_wp_head'); |
|
| 187 | + } |
|
| 188 | 188 | |
| 189 | 189 | |
| 190 | - /** |
|
| 191 | - * This generates a unique site-specific string. |
|
| 192 | - * An example usage for this string would be to save as a unique identifier for a record in the db for usage in |
|
| 193 | - * urls. |
|
| 194 | - * |
|
| 195 | - * @param string $prefix Use this to prefix the string with something. |
|
| 196 | - * @return string |
|
| 197 | - */ |
|
| 198 | - public static function generate_unique_token($prefix = '') |
|
| 199 | - { |
|
| 200 | - $token = md5(uniqid() . mt_rand()); |
|
| 201 | - return $prefix ? $prefix . '_' . $token : $token; |
|
| 202 | - } |
|
| 190 | + /** |
|
| 191 | + * This generates a unique site-specific string. |
|
| 192 | + * An example usage for this string would be to save as a unique identifier for a record in the db for usage in |
|
| 193 | + * urls. |
|
| 194 | + * |
|
| 195 | + * @param string $prefix Use this to prefix the string with something. |
|
| 196 | + * @return string |
|
| 197 | + */ |
|
| 198 | + public static function generate_unique_token($prefix = '') |
|
| 199 | + { |
|
| 200 | + $token = md5(uniqid() . mt_rand()); |
|
| 201 | + return $prefix ? $prefix . '_' . $token : $token; |
|
| 202 | + } |
|
| 203 | 203 | |
| 204 | 204 | |
| 205 | - /** |
|
| 206 | - * filter_input_server_url |
|
| 207 | - * uses filter_input() to sanitize one of the INPUT_SERVER URL values |
|
| 208 | - * but adds a backup in case filter_input() returns nothing, which can erringly happen on some servers |
|
| 209 | - * |
|
| 210 | - * @param string $server_variable |
|
| 211 | - * @return string |
|
| 212 | - */ |
|
| 213 | - public static function filter_input_server_url($server_variable = 'REQUEST_URI') |
|
| 214 | - { |
|
| 215 | - $URL = ''; |
|
| 216 | - $server_variables = array( |
|
| 217 | - 'REQUEST_URI' => 1, |
|
| 218 | - 'HTTP_HOST' => 1, |
|
| 219 | - 'PHP_SELF' => 1, |
|
| 220 | - ); |
|
| 221 | - $server_variable = strtoupper($server_variable); |
|
| 222 | - // whitelist INPUT_SERVER var |
|
| 223 | - if (isset($server_variables[$server_variable])) { |
|
| 224 | - $URL = filter_input(INPUT_SERVER, $server_variable, FILTER_SANITIZE_URL, FILTER_NULL_ON_FAILURE); |
|
| 225 | - if (empty($URL)) { |
|
| 226 | - // fallback sanitization if the above fails |
|
| 227 | - $URL = wp_sanitize_redirect($_SERVER[$server_variable]); |
|
| 228 | - } |
|
| 229 | - } |
|
| 230 | - return $URL; |
|
| 231 | - } |
|
| 205 | + /** |
|
| 206 | + * filter_input_server_url |
|
| 207 | + * uses filter_input() to sanitize one of the INPUT_SERVER URL values |
|
| 208 | + * but adds a backup in case filter_input() returns nothing, which can erringly happen on some servers |
|
| 209 | + * |
|
| 210 | + * @param string $server_variable |
|
| 211 | + * @return string |
|
| 212 | + */ |
|
| 213 | + public static function filter_input_server_url($server_variable = 'REQUEST_URI') |
|
| 214 | + { |
|
| 215 | + $URL = ''; |
|
| 216 | + $server_variables = array( |
|
| 217 | + 'REQUEST_URI' => 1, |
|
| 218 | + 'HTTP_HOST' => 1, |
|
| 219 | + 'PHP_SELF' => 1, |
|
| 220 | + ); |
|
| 221 | + $server_variable = strtoupper($server_variable); |
|
| 222 | + // whitelist INPUT_SERVER var |
|
| 223 | + if (isset($server_variables[$server_variable])) { |
|
| 224 | + $URL = filter_input(INPUT_SERVER, $server_variable, FILTER_SANITIZE_URL, FILTER_NULL_ON_FAILURE); |
|
| 225 | + if (empty($URL)) { |
|
| 226 | + // fallback sanitization if the above fails |
|
| 227 | + $URL = wp_sanitize_redirect($_SERVER[$server_variable]); |
|
| 228 | + } |
|
| 229 | + } |
|
| 230 | + return $URL; |
|
| 231 | + } |
|
| 232 | 232 | |
| 233 | 233 | |
| 234 | - /** |
|
| 235 | - * Gets the current page's full URL. |
|
| 236 | - * |
|
| 237 | - * @return string |
|
| 238 | - */ |
|
| 239 | - public static function current_url() |
|
| 240 | - { |
|
| 241 | - $url = ''; |
|
| 242 | - if (isset($_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'])) { |
|
| 243 | - $url = is_ssl() ? 'https://' : 'http://'; |
|
| 244 | - $url .= \EEH_URL::filter_input_server_url('HTTP_HOST'); |
|
| 245 | - $url .= \EEH_URL::filter_input_server_url('REQUEST_URI'); |
|
| 246 | - } |
|
| 247 | - return $url; |
|
| 248 | - } |
|
| 234 | + /** |
|
| 235 | + * Gets the current page's full URL. |
|
| 236 | + * |
|
| 237 | + * @return string |
|
| 238 | + */ |
|
| 239 | + public static function current_url() |
|
| 240 | + { |
|
| 241 | + $url = ''; |
|
| 242 | + if (isset($_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'])) { |
|
| 243 | + $url = is_ssl() ? 'https://' : 'http://'; |
|
| 244 | + $url .= \EEH_URL::filter_input_server_url('HTTP_HOST'); |
|
| 245 | + $url .= \EEH_URL::filter_input_server_url('REQUEST_URI'); |
|
| 246 | + } |
|
| 247 | + return $url; |
|
| 248 | + } |
|
| 249 | 249 | |
| 250 | 250 | |
| 251 | - /** |
|
| 252 | - * Identical in functionality to EEH_current_url except it removes any provided query_parameters from it. |
|
| 253 | - * |
|
| 254 | - * @param array $query_parameters An array of query_parameters to remove from the current url. |
|
| 255 | - * @since 4.9.46.rc.029 |
|
| 256 | - * @return string |
|
| 257 | - */ |
|
| 258 | - public static function current_url_without_query_paramaters(array $query_parameters) |
|
| 259 | - { |
|
| 260 | - return remove_query_arg($query_parameters, EEH_URL::current_url()); |
|
| 261 | - } |
|
| 251 | + /** |
|
| 252 | + * Identical in functionality to EEH_current_url except it removes any provided query_parameters from it. |
|
| 253 | + * |
|
| 254 | + * @param array $query_parameters An array of query_parameters to remove from the current url. |
|
| 255 | + * @since 4.9.46.rc.029 |
|
| 256 | + * @return string |
|
| 257 | + */ |
|
| 258 | + public static function current_url_without_query_paramaters(array $query_parameters) |
|
| 259 | + { |
|
| 260 | + return remove_query_arg($query_parameters, EEH_URL::current_url()); |
|
| 261 | + } |
|
| 262 | 262 | |
| 263 | 263 | |
| 264 | - /** |
|
| 265 | - * @param string $location |
|
| 266 | - * @param int $status |
|
| 267 | - * @param string $exit_notice |
|
| 268 | - */ |
|
| 269 | - public static function safeRedirectAndExit($location, $status = 302, $exit_notice = '') |
|
| 270 | - { |
|
| 271 | - EE_Error::get_notices(false, true); |
|
| 272 | - wp_safe_redirect($location, $status); |
|
| 273 | - exit($exit_notice); |
|
| 274 | - } |
|
| 264 | + /** |
|
| 265 | + * @param string $location |
|
| 266 | + * @param int $status |
|
| 267 | + * @param string $exit_notice |
|
| 268 | + */ |
|
| 269 | + public static function safeRedirectAndExit($location, $status = 302, $exit_notice = '') |
|
| 270 | + { |
|
| 271 | + EE_Error::get_notices(false, true); |
|
| 272 | + wp_safe_redirect($location, $status); |
|
| 273 | + exit($exit_notice); |
|
| 274 | + } |
|
| 275 | 275 | } |
@@ -18,27 +18,27 @@ discard block |
||
| 18 | 18 | class EE_Invisible_Recaptcha_Display_Strategy extends EE_Display_Strategy_Base |
| 19 | 19 | { |
| 20 | 20 | |
| 21 | - /** |
|
| 22 | - * @return EE_Form_Input_Base|EE_Invisible_Recaptcha_Input |
|
| 23 | - */ |
|
| 24 | - public function input() |
|
| 25 | - { |
|
| 26 | - return $this->_input; |
|
| 27 | - } |
|
| 28 | - |
|
| 29 | - |
|
| 30 | - /** |
|
| 31 | - * returns HTML and javascript related to the displaying of this input |
|
| 32 | - * |
|
| 33 | - * @return string |
|
| 34 | - * @throws InvalidInterfaceException |
|
| 35 | - * @throws InvalidDataTypeException |
|
| 36 | - * @throws InvalidArgumentException |
|
| 37 | - */ |
|
| 38 | - public function display() |
|
| 39 | - { |
|
| 40 | - wp_enqueue_script(EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_GOOGLE_INVISIBLE_RECAPTCHA); |
|
| 41 | - return <<<EOD |
|
| 21 | + /** |
|
| 22 | + * @return EE_Form_Input_Base|EE_Invisible_Recaptcha_Input |
|
| 23 | + */ |
|
| 24 | + public function input() |
|
| 25 | + { |
|
| 26 | + return $this->_input; |
|
| 27 | + } |
|
| 28 | + |
|
| 29 | + |
|
| 30 | + /** |
|
| 31 | + * returns HTML and javascript related to the displaying of this input |
|
| 32 | + * |
|
| 33 | + * @return string |
|
| 34 | + * @throws InvalidInterfaceException |
|
| 35 | + * @throws InvalidDataTypeException |
|
| 36 | + * @throws InvalidArgumentException |
|
| 37 | + */ |
|
| 38 | + public function display() |
|
| 39 | + { |
|
| 40 | + wp_enqueue_script(EE_Invisible_Recaptcha_Input::SCRIPT_HANDLE_GOOGLE_INVISIBLE_RECAPTCHA); |
|
| 41 | + return <<<EOD |
|
| 42 | 42 | <div id="g-recaptcha-{$this->input()->recaptchaId()}" |
| 43 | 43 | class="g-recaptcha" |
| 44 | 44 | data-sitekey="{$this->input()->siteKey()}" |
@@ -48,5 +48,5 @@ discard block |
||
| 48 | 48 | > |
| 49 | 49 | </div> |
| 50 | 50 | EOD; |
| 51 | - } |
|
| 51 | + } |
|
| 52 | 52 | } |
@@ -14,138 +14,138 @@ |
||
| 14 | 14 | class EE_Div_Per_Section_Layout extends EE_Form_Section_Layout_Base |
| 15 | 15 | { |
| 16 | 16 | |
| 17 | - /** |
|
| 18 | - * opening div tag for a form |
|
| 19 | - * |
|
| 20 | - * @return string |
|
| 21 | - */ |
|
| 22 | - public function layout_form_begin() |
|
| 23 | - { |
|
| 24 | - return EEH_HTML::div( |
|
| 25 | - '', |
|
| 26 | - $this->_form_section->html_id(), |
|
| 27 | - $this->_form_section->html_class(), |
|
| 28 | - $this->_form_section->html_style() |
|
| 29 | - ); |
|
| 30 | - } |
|
| 31 | - |
|
| 32 | - |
|
| 33 | - |
|
| 34 | - /** |
|
| 35 | - * Lays out the row for the input, including label and errors |
|
| 36 | - * |
|
| 37 | - * @param EE_Form_Input_Base $input |
|
| 38 | - * @return string |
|
| 39 | - * @throws \EE_Error |
|
| 40 | - */ |
|
| 41 | - public function layout_input($input) |
|
| 42 | - { |
|
| 43 | - $html = ''; |
|
| 44 | - // set something unique for the id |
|
| 45 | - $html_id = (string)$input->html_id() !== '' |
|
| 46 | - ? (string)$input->html_id() |
|
| 47 | - : spl_object_hash($input); |
|
| 48 | - // and add a generic input type class |
|
| 49 | - $html_class = sanitize_key(str_replace('_', '-', get_class($input))) . '-dv'; |
|
| 50 | - if ($input instanceof EE_Hidden_Input) { |
|
| 51 | - $html .= EEH_HTML::nl() . $input->get_html_for_input(); |
|
| 52 | - } else if ($input instanceof EE_Submit_Input) { |
|
| 53 | - $html .= EEH_HTML::div( |
|
| 54 | - $input->get_html_for_input(), |
|
| 55 | - $html_id . '-submit-dv', |
|
| 56 | - "{$input->html_class()}-submit-dv {$html_class}" |
|
| 57 | - ); |
|
| 58 | - } else if ($input instanceof EE_Select_Input) { |
|
| 59 | - $html .= EEH_HTML::div( |
|
| 60 | - EEH_HTML::nl(1) . $input->get_html_for_label() . |
|
| 61 | - EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 62 | - EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 63 | - EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 64 | - $html_id . '-input-dv', |
|
| 65 | - "{$input->html_class()}-input-dv {$html_class}" |
|
| 66 | - ); |
|
| 67 | - } else if ($input instanceof EE_Form_Input_With_Options_Base) { |
|
| 68 | - $html .= EEH_HTML::div( |
|
| 69 | - EEH_HTML::nl() . $this->_display_label_for_option_type_question($input) . |
|
| 70 | - EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 71 | - EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 72 | - EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 73 | - $html_id . '-input-dv', |
|
| 74 | - "{$input->html_class()}-input-dv {$html_class}" |
|
| 75 | - ); |
|
| 76 | - } else { |
|
| 77 | - $html .= EEH_HTML::div( |
|
| 78 | - EEH_HTML::nl(1) . $input->get_html_for_label() . |
|
| 79 | - EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 80 | - EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 81 | - EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 82 | - $html_id . '-input-dv', |
|
| 83 | - "{$input->html_class()}-input-dv {$html_class}" |
|
| 84 | - ); |
|
| 85 | - } |
|
| 86 | - return $html; |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - |
|
| 90 | - |
|
| 91 | - /** |
|
| 92 | - * |
|
| 93 | - * _display_label_for_option_type_question |
|
| 94 | - * Gets the HTML for the 'label', which is just text for this (because labels |
|
| 95 | - * should be for each input) |
|
| 96 | - * |
|
| 97 | - * @param EE_Form_Input_With_Options_Base $input |
|
| 98 | - * @return string |
|
| 99 | - */ |
|
| 100 | - protected function _display_label_for_option_type_question(EE_Form_Input_With_Options_Base $input) |
|
| 101 | - { |
|
| 102 | - if ($input->display_html_label_text()) { |
|
| 103 | - $html_label_text = $input->html_label_text(); |
|
| 104 | - $label_html = EEH_HTML::div( |
|
| 105 | - $input->required() |
|
| 106 | - ? $html_label_text . EEH_HTML::span('*', '', 'ee-asterisk') |
|
| 107 | - : $html_label_text, |
|
| 108 | - $input->html_label_id(), |
|
| 109 | - $input->required() |
|
| 110 | - ? 'ee-required-label ' . $input->html_label_class() |
|
| 111 | - : $input->html_label_class(), |
|
| 112 | - $input->html_label_style(), |
|
| 113 | - $input->html_other_attributes() |
|
| 114 | - ); |
|
| 115 | - // if no content was provided to EEH_HTML::div() above (ie: an empty label), |
|
| 116 | - // then we need to close the div manually |
|
| 117 | - if(empty($html_label_text)){ |
|
| 118 | - $label_html .= EEH_HTML::divx($input->html_label_id(), $input->html_label_class()); |
|
| 119 | - } |
|
| 120 | - return $label_html; |
|
| 121 | - } |
|
| 122 | - return ''; |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - |
|
| 126 | - |
|
| 127 | - /** |
|
| 128 | - * Lays out a row for the subsection |
|
| 129 | - * |
|
| 130 | - * @param EE_Form_Section_Proper $form_section |
|
| 131 | - * @return string |
|
| 132 | - */ |
|
| 133 | - public function layout_subsection($form_section) |
|
| 134 | - { |
|
| 135 | - return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - |
|
| 139 | - |
|
| 140 | - /** |
|
| 141 | - * closing div tag for a form |
|
| 142 | - * |
|
| 143 | - * @return string |
|
| 144 | - */ |
|
| 145 | - public function layout_form_end() |
|
| 146 | - { |
|
| 147 | - return EEH_HTML::divx($this->_form_section->html_id(), $this->_form_section->html_class()); |
|
| 148 | - } |
|
| 17 | + /** |
|
| 18 | + * opening div tag for a form |
|
| 19 | + * |
|
| 20 | + * @return string |
|
| 21 | + */ |
|
| 22 | + public function layout_form_begin() |
|
| 23 | + { |
|
| 24 | + return EEH_HTML::div( |
|
| 25 | + '', |
|
| 26 | + $this->_form_section->html_id(), |
|
| 27 | + $this->_form_section->html_class(), |
|
| 28 | + $this->_form_section->html_style() |
|
| 29 | + ); |
|
| 30 | + } |
|
| 31 | + |
|
| 32 | + |
|
| 33 | + |
|
| 34 | + /** |
|
| 35 | + * Lays out the row for the input, including label and errors |
|
| 36 | + * |
|
| 37 | + * @param EE_Form_Input_Base $input |
|
| 38 | + * @return string |
|
| 39 | + * @throws \EE_Error |
|
| 40 | + */ |
|
| 41 | + public function layout_input($input) |
|
| 42 | + { |
|
| 43 | + $html = ''; |
|
| 44 | + // set something unique for the id |
|
| 45 | + $html_id = (string)$input->html_id() !== '' |
|
| 46 | + ? (string)$input->html_id() |
|
| 47 | + : spl_object_hash($input); |
|
| 48 | + // and add a generic input type class |
|
| 49 | + $html_class = sanitize_key(str_replace('_', '-', get_class($input))) . '-dv'; |
|
| 50 | + if ($input instanceof EE_Hidden_Input) { |
|
| 51 | + $html .= EEH_HTML::nl() . $input->get_html_for_input(); |
|
| 52 | + } else if ($input instanceof EE_Submit_Input) { |
|
| 53 | + $html .= EEH_HTML::div( |
|
| 54 | + $input->get_html_for_input(), |
|
| 55 | + $html_id . '-submit-dv', |
|
| 56 | + "{$input->html_class()}-submit-dv {$html_class}" |
|
| 57 | + ); |
|
| 58 | + } else if ($input instanceof EE_Select_Input) { |
|
| 59 | + $html .= EEH_HTML::div( |
|
| 60 | + EEH_HTML::nl(1) . $input->get_html_for_label() . |
|
| 61 | + EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 62 | + EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 63 | + EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 64 | + $html_id . '-input-dv', |
|
| 65 | + "{$input->html_class()}-input-dv {$html_class}" |
|
| 66 | + ); |
|
| 67 | + } else if ($input instanceof EE_Form_Input_With_Options_Base) { |
|
| 68 | + $html .= EEH_HTML::div( |
|
| 69 | + EEH_HTML::nl() . $this->_display_label_for_option_type_question($input) . |
|
| 70 | + EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 71 | + EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 72 | + EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 73 | + $html_id . '-input-dv', |
|
| 74 | + "{$input->html_class()}-input-dv {$html_class}" |
|
| 75 | + ); |
|
| 76 | + } else { |
|
| 77 | + $html .= EEH_HTML::div( |
|
| 78 | + EEH_HTML::nl(1) . $input->get_html_for_label() . |
|
| 79 | + EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 80 | + EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 81 | + EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 82 | + $html_id . '-input-dv', |
|
| 83 | + "{$input->html_class()}-input-dv {$html_class}" |
|
| 84 | + ); |
|
| 85 | + } |
|
| 86 | + return $html; |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + |
|
| 90 | + |
|
| 91 | + /** |
|
| 92 | + * |
|
| 93 | + * _display_label_for_option_type_question |
|
| 94 | + * Gets the HTML for the 'label', which is just text for this (because labels |
|
| 95 | + * should be for each input) |
|
| 96 | + * |
|
| 97 | + * @param EE_Form_Input_With_Options_Base $input |
|
| 98 | + * @return string |
|
| 99 | + */ |
|
| 100 | + protected function _display_label_for_option_type_question(EE_Form_Input_With_Options_Base $input) |
|
| 101 | + { |
|
| 102 | + if ($input->display_html_label_text()) { |
|
| 103 | + $html_label_text = $input->html_label_text(); |
|
| 104 | + $label_html = EEH_HTML::div( |
|
| 105 | + $input->required() |
|
| 106 | + ? $html_label_text . EEH_HTML::span('*', '', 'ee-asterisk') |
|
| 107 | + : $html_label_text, |
|
| 108 | + $input->html_label_id(), |
|
| 109 | + $input->required() |
|
| 110 | + ? 'ee-required-label ' . $input->html_label_class() |
|
| 111 | + : $input->html_label_class(), |
|
| 112 | + $input->html_label_style(), |
|
| 113 | + $input->html_other_attributes() |
|
| 114 | + ); |
|
| 115 | + // if no content was provided to EEH_HTML::div() above (ie: an empty label), |
|
| 116 | + // then we need to close the div manually |
|
| 117 | + if(empty($html_label_text)){ |
|
| 118 | + $label_html .= EEH_HTML::divx($input->html_label_id(), $input->html_label_class()); |
|
| 119 | + } |
|
| 120 | + return $label_html; |
|
| 121 | + } |
|
| 122 | + return ''; |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + |
|
| 126 | + |
|
| 127 | + /** |
|
| 128 | + * Lays out a row for the subsection |
|
| 129 | + * |
|
| 130 | + * @param EE_Form_Section_Proper $form_section |
|
| 131 | + * @return string |
|
| 132 | + */ |
|
| 133 | + public function layout_subsection($form_section) |
|
| 134 | + { |
|
| 135 | + return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + |
|
| 139 | + |
|
| 140 | + /** |
|
| 141 | + * closing div tag for a form |
|
| 142 | + * |
|
| 143 | + * @return string |
|
| 144 | + */ |
|
| 145 | + public function layout_form_end() |
|
| 146 | + { |
|
| 147 | + return EEH_HTML::divx($this->_form_section->html_id(), $this->_form_section->html_class()); |
|
| 148 | + } |
|
| 149 | 149 | |
| 150 | 150 | |
| 151 | 151 | |
@@ -42,44 +42,44 @@ discard block |
||
| 42 | 42 | { |
| 43 | 43 | $html = ''; |
| 44 | 44 | // set something unique for the id |
| 45 | - $html_id = (string)$input->html_id() !== '' |
|
| 46 | - ? (string)$input->html_id() |
|
| 45 | + $html_id = (string) $input->html_id() !== '' |
|
| 46 | + ? (string) $input->html_id() |
|
| 47 | 47 | : spl_object_hash($input); |
| 48 | 48 | // and add a generic input type class |
| 49 | - $html_class = sanitize_key(str_replace('_', '-', get_class($input))) . '-dv'; |
|
| 49 | + $html_class = sanitize_key(str_replace('_', '-', get_class($input))).'-dv'; |
|
| 50 | 50 | if ($input instanceof EE_Hidden_Input) { |
| 51 | - $html .= EEH_HTML::nl() . $input->get_html_for_input(); |
|
| 51 | + $html .= EEH_HTML::nl().$input->get_html_for_input(); |
|
| 52 | 52 | } else if ($input instanceof EE_Submit_Input) { |
| 53 | 53 | $html .= EEH_HTML::div( |
| 54 | 54 | $input->get_html_for_input(), |
| 55 | - $html_id . '-submit-dv', |
|
| 55 | + $html_id.'-submit-dv', |
|
| 56 | 56 | "{$input->html_class()}-submit-dv {$html_class}" |
| 57 | 57 | ); |
| 58 | 58 | } else if ($input instanceof EE_Select_Input) { |
| 59 | 59 | $html .= EEH_HTML::div( |
| 60 | - EEH_HTML::nl(1) . $input->get_html_for_label() . |
|
| 61 | - EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 62 | - EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 63 | - EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 64 | - $html_id . '-input-dv', |
|
| 60 | + EEH_HTML::nl(1).$input->get_html_for_label(). |
|
| 61 | + EEH_HTML::nl().$input->get_html_for_errors(). |
|
| 62 | + EEH_HTML::nl().$input->get_html_for_input(). |
|
| 63 | + EEH_HTML::nl().$input->get_html_for_help(), |
|
| 64 | + $html_id.'-input-dv', |
|
| 65 | 65 | "{$input->html_class()}-input-dv {$html_class}" |
| 66 | 66 | ); |
| 67 | 67 | } else if ($input instanceof EE_Form_Input_With_Options_Base) { |
| 68 | 68 | $html .= EEH_HTML::div( |
| 69 | - EEH_HTML::nl() . $this->_display_label_for_option_type_question($input) . |
|
| 70 | - EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 71 | - EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 72 | - EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 73 | - $html_id . '-input-dv', |
|
| 69 | + EEH_HTML::nl().$this->_display_label_for_option_type_question($input). |
|
| 70 | + EEH_HTML::nl().$input->get_html_for_errors(). |
|
| 71 | + EEH_HTML::nl().$input->get_html_for_input(). |
|
| 72 | + EEH_HTML::nl().$input->get_html_for_help(), |
|
| 73 | + $html_id.'-input-dv', |
|
| 74 | 74 | "{$input->html_class()}-input-dv {$html_class}" |
| 75 | 75 | ); |
| 76 | 76 | } else { |
| 77 | 77 | $html .= EEH_HTML::div( |
| 78 | - EEH_HTML::nl(1) . $input->get_html_for_label() . |
|
| 79 | - EEH_HTML::nl() . $input->get_html_for_errors() . |
|
| 80 | - EEH_HTML::nl() . $input->get_html_for_input() . |
|
| 81 | - EEH_HTML::nl() . $input->get_html_for_help(), |
|
| 82 | - $html_id . '-input-dv', |
|
| 78 | + EEH_HTML::nl(1).$input->get_html_for_label(). |
|
| 79 | + EEH_HTML::nl().$input->get_html_for_errors(). |
|
| 80 | + EEH_HTML::nl().$input->get_html_for_input(). |
|
| 81 | + EEH_HTML::nl().$input->get_html_for_help(), |
|
| 82 | + $html_id.'-input-dv', |
|
| 83 | 83 | "{$input->html_class()}-input-dv {$html_class}" |
| 84 | 84 | ); |
| 85 | 85 | } |
@@ -103,18 +103,18 @@ discard block |
||
| 103 | 103 | $html_label_text = $input->html_label_text(); |
| 104 | 104 | $label_html = EEH_HTML::div( |
| 105 | 105 | $input->required() |
| 106 | - ? $html_label_text . EEH_HTML::span('*', '', 'ee-asterisk') |
|
| 106 | + ? $html_label_text.EEH_HTML::span('*', '', 'ee-asterisk') |
|
| 107 | 107 | : $html_label_text, |
| 108 | 108 | $input->html_label_id(), |
| 109 | 109 | $input->required() |
| 110 | - ? 'ee-required-label ' . $input->html_label_class() |
|
| 110 | + ? 'ee-required-label '.$input->html_label_class() |
|
| 111 | 111 | : $input->html_label_class(), |
| 112 | 112 | $input->html_label_style(), |
| 113 | 113 | $input->html_other_attributes() |
| 114 | 114 | ); |
| 115 | 115 | // if no content was provided to EEH_HTML::div() above (ie: an empty label), |
| 116 | 116 | // then we need to close the div manually |
| 117 | - if(empty($html_label_text)){ |
|
| 117 | + if (empty($html_label_text)) { |
|
| 118 | 118 | $label_html .= EEH_HTML::divx($input->html_label_id(), $input->html_label_class()); |
| 119 | 119 | } |
| 120 | 120 | return $label_html; |
@@ -132,7 +132,7 @@ discard block |
||
| 132 | 132 | */ |
| 133 | 133 | public function layout_subsection($form_section) |
| 134 | 134 | { |
| 135 | - return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1); |
|
| 135 | + return EEH_HTML::nl(1).$form_section->get_html().EEH_HTML::nl(-1); |
|
| 136 | 136 | } |
| 137 | 137 | |
| 138 | 138 | |