@@ -781,7 +781,7 @@ |
||
| 781 | 781 | /** |
| 782 | 782 | * Gets the event that's related to the ticket, if this line item represents a ticket. |
| 783 | 783 | * |
| 784 | - * @return EE_Event|null |
|
| 784 | + * @return EE_Base_Class|null |
|
| 785 | 785 | * @throws EE_Error |
| 786 | 786 | * @throws InvalidArgumentException |
| 787 | 787 | * @throws InvalidDataTypeException |
@@ -88,7 +88,7 @@ discard block |
||
| 88 | 88 | protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
| 89 | 89 | { |
| 90 | 90 | parent::__construct($fieldValues, $bydb, $timezone); |
| 91 | - if (! $this->get('LIN_code')) { |
|
| 91 | + if ( ! $this->get('LIN_code')) { |
|
| 92 | 92 | $this->set_code($this->generate_code()); |
| 93 | 93 | } |
| 94 | 94 | } |
@@ -155,7 +155,7 @@ discard block |
||
| 155 | 155 | public function name() |
| 156 | 156 | { |
| 157 | 157 | $name = $this->get('LIN_name'); |
| 158 | - if (! $name) { |
|
| 158 | + if ( ! $name) { |
|
| 159 | 159 | $name = ucwords(str_replace('-', ' ', $this->type())); |
| 160 | 160 | } |
| 161 | 161 | return $name; |
@@ -615,7 +615,7 @@ discard block |
||
| 615 | 615 | ) |
| 616 | 616 | ); |
| 617 | 617 | } |
| 618 | - if (! is_array($this->_children)) { |
|
| 618 | + if ( ! is_array($this->_children)) { |
|
| 619 | 619 | $this->_children = array(); |
| 620 | 620 | } |
| 621 | 621 | return $this->_children; |
@@ -856,7 +856,7 @@ discard block |
||
| 856 | 856 | } |
| 857 | 857 | return $line_item->save(); |
| 858 | 858 | } |
| 859 | - $this->_children[ $line_item->code() ] = $line_item; |
|
| 859 | + $this->_children[$line_item->code()] = $line_item; |
|
| 860 | 860 | if ($line_item->parent() !== $this) { |
| 861 | 861 | $line_item->set_parent($this); |
| 862 | 862 | } |
@@ -880,7 +880,7 @@ discard block |
||
| 880 | 880 | public function set_parent($line_item) |
| 881 | 881 | { |
| 882 | 882 | if ($this->ID()) { |
| 883 | - if (! $line_item->ID()) { |
|
| 883 | + if ( ! $line_item->ID()) { |
|
| 884 | 884 | $line_item->save(); |
| 885 | 885 | } |
| 886 | 886 | $this->set_parent_ID($line_item->ID()); |
@@ -912,8 +912,8 @@ discard block |
||
| 912 | 912 | array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
| 913 | 913 | ); |
| 914 | 914 | } |
| 915 | - return isset($this->_children[ $code ]) |
|
| 916 | - ? $this->_children[ $code ] |
|
| 915 | + return isset($this->_children[$code]) |
|
| 916 | + ? $this->_children[$code] |
|
| 917 | 917 | : null; |
| 918 | 918 | } |
| 919 | 919 | |
@@ -973,8 +973,8 @@ discard block |
||
| 973 | 973 | } |
| 974 | 974 | return $items_deleted; |
| 975 | 975 | } |
| 976 | - if (isset($this->_children[ $code ])) { |
|
| 977 | - unset($this->_children[ $code ]); |
|
| 976 | + if (isset($this->_children[$code])) { |
|
| 977 | + unset($this->_children[$code]); |
|
| 978 | 978 | return 1; |
| 979 | 979 | } |
| 980 | 980 | return 0; |
@@ -1015,7 +1015,7 @@ discard block |
||
| 1015 | 1015 | public function generate_code() |
| 1016 | 1016 | { |
| 1017 | 1017 | // each line item in the cart requires a unique identifier |
| 1018 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
| 1018 | + return md5($this->get('OBJ_type').$this->get('OBJ_ID').microtime()); |
|
| 1019 | 1019 | } |
| 1020 | 1020 | |
| 1021 | 1021 | |
@@ -1220,7 +1220,7 @@ discard block |
||
| 1220 | 1220 | $has_children = ! empty($my_children); |
| 1221 | 1221 | if ($has_children && $this->is_line_item()) { |
| 1222 | 1222 | $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
| 1223 | - } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 1223 | + } elseif ( ! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 1224 | 1224 | $total = $this->unit_price() * $this->quantity(); |
| 1225 | 1225 | } elseif ($this->is_sub_total() || $this->is_total()) { |
| 1226 | 1226 | $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
@@ -1229,18 +1229,18 @@ discard block |
||
| 1229 | 1229 | return 0; |
| 1230 | 1230 | } |
| 1231 | 1231 | // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
| 1232 | - if (! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
| 1232 | + if ( ! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
| 1233 | 1233 | ) { |
| 1234 | 1234 | if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
| 1235 | 1235 | $this->set_quantity(1); |
| 1236 | 1236 | } |
| 1237 | - if (! $this->is_percent()) { |
|
| 1237 | + if ( ! $this->is_percent()) { |
|
| 1238 | 1238 | $this->set_unit_price($total); |
| 1239 | 1239 | } |
| 1240 | 1240 | } |
| 1241 | 1241 | // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
| 1242 | 1242 | // so it ought to be |
| 1243 | - if (! $this->is_total()) { |
|
| 1243 | + if ( ! $this->is_total()) { |
|
| 1244 | 1244 | $this->set_total($total); |
| 1245 | 1245 | // if not a percent line item, make sure we keep the unit price in sync |
| 1246 | 1246 | if ($has_children |
@@ -1587,7 +1587,7 @@ discard block |
||
| 1587 | 1587 | public function save_this_and_descendants_to_txn($txn_id = null) |
| 1588 | 1588 | { |
| 1589 | 1589 | $count = 0; |
| 1590 | - if (! $txn_id) { |
|
| 1590 | + if ( ! $txn_id) { |
|
| 1591 | 1591 | $txn_id = $this->TXN_ID(); |
| 1592 | 1592 | } |
| 1593 | 1593 | $this->set_TXN_ID($txn_id); |
@@ -14,1739 +14,1739 @@ |
||
| 14 | 14 | class EE_Line_Item extends EE_Base_Class implements EEI_Line_Item |
| 15 | 15 | { |
| 16 | 16 | |
| 17 | - /** |
|
| 18 | - * for children line items (currently not a normal relation) |
|
| 19 | - * |
|
| 20 | - * @type EE_Line_Item[] |
|
| 21 | - */ |
|
| 22 | - protected $_children = array(); |
|
| 23 | - |
|
| 24 | - /** |
|
| 25 | - * for the parent line item |
|
| 26 | - * |
|
| 27 | - * @var EE_Line_Item |
|
| 28 | - */ |
|
| 29 | - protected $_parent; |
|
| 30 | - |
|
| 31 | - |
|
| 32 | - /** |
|
| 33 | - * @param array $props_n_values incoming values |
|
| 34 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 35 | - * used.) |
|
| 36 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 37 | - * date_format and the second value is the time format |
|
| 38 | - * @return EE_Line_Item |
|
| 39 | - * @throws EE_Error |
|
| 40 | - * @throws InvalidArgumentException |
|
| 41 | - * @throws InvalidDataTypeException |
|
| 42 | - * @throws InvalidInterfaceException |
|
| 43 | - * @throws ReflectionException |
|
| 44 | - */ |
|
| 45 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
| 46 | - { |
|
| 47 | - $has_object = parent::_check_for_object( |
|
| 48 | - $props_n_values, |
|
| 49 | - __CLASS__, |
|
| 50 | - $timezone, |
|
| 51 | - $date_formats |
|
| 52 | - ); |
|
| 53 | - return $has_object |
|
| 54 | - ? $has_object |
|
| 55 | - : new self($props_n_values, false, $timezone); |
|
| 56 | - } |
|
| 57 | - |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * @param array $props_n_values incoming values from the database |
|
| 61 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 62 | - * the website will be used. |
|
| 63 | - * @return EE_Line_Item |
|
| 64 | - * @throws EE_Error |
|
| 65 | - * @throws InvalidArgumentException |
|
| 66 | - * @throws InvalidDataTypeException |
|
| 67 | - * @throws InvalidInterfaceException |
|
| 68 | - * @throws ReflectionException |
|
| 69 | - */ |
|
| 70 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
| 71 | - { |
|
| 72 | - return new self($props_n_values, true, $timezone); |
|
| 73 | - } |
|
| 74 | - |
|
| 75 | - |
|
| 76 | - /** |
|
| 77 | - * Adds some defaults if they're not specified |
|
| 78 | - * |
|
| 79 | - * @param array $fieldValues |
|
| 80 | - * @param bool $bydb |
|
| 81 | - * @param string $timezone |
|
| 82 | - * @throws EE_Error |
|
| 83 | - * @throws InvalidArgumentException |
|
| 84 | - * @throws InvalidDataTypeException |
|
| 85 | - * @throws InvalidInterfaceException |
|
| 86 | - * @throws ReflectionException |
|
| 87 | - */ |
|
| 88 | - protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
| 89 | - { |
|
| 90 | - parent::__construct($fieldValues, $bydb, $timezone); |
|
| 91 | - if (! $this->get('LIN_code')) { |
|
| 92 | - $this->set_code($this->generate_code()); |
|
| 93 | - } |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - |
|
| 97 | - /** |
|
| 98 | - * Gets ID |
|
| 99 | - * |
|
| 100 | - * @return int |
|
| 101 | - * @throws EE_Error |
|
| 102 | - * @throws InvalidArgumentException |
|
| 103 | - * @throws InvalidDataTypeException |
|
| 104 | - * @throws InvalidInterfaceException |
|
| 105 | - * @throws ReflectionException |
|
| 106 | - */ |
|
| 107 | - public function ID() |
|
| 108 | - { |
|
| 109 | - return $this->get('LIN_ID'); |
|
| 110 | - } |
|
| 111 | - |
|
| 112 | - |
|
| 113 | - /** |
|
| 114 | - * Gets TXN_ID |
|
| 115 | - * |
|
| 116 | - * @return int |
|
| 117 | - * @throws EE_Error |
|
| 118 | - * @throws InvalidArgumentException |
|
| 119 | - * @throws InvalidDataTypeException |
|
| 120 | - * @throws InvalidInterfaceException |
|
| 121 | - * @throws ReflectionException |
|
| 122 | - */ |
|
| 123 | - public function TXN_ID() |
|
| 124 | - { |
|
| 125 | - return $this->get('TXN_ID'); |
|
| 126 | - } |
|
| 127 | - |
|
| 128 | - |
|
| 129 | - /** |
|
| 130 | - * Sets TXN_ID |
|
| 131 | - * |
|
| 132 | - * @param int $TXN_ID |
|
| 133 | - * @throws EE_Error |
|
| 134 | - * @throws InvalidArgumentException |
|
| 135 | - * @throws InvalidDataTypeException |
|
| 136 | - * @throws InvalidInterfaceException |
|
| 137 | - * @throws ReflectionException |
|
| 138 | - */ |
|
| 139 | - public function set_TXN_ID($TXN_ID) |
|
| 140 | - { |
|
| 141 | - $this->set('TXN_ID', $TXN_ID); |
|
| 142 | - } |
|
| 143 | - |
|
| 144 | - |
|
| 145 | - /** |
|
| 146 | - * Gets name |
|
| 147 | - * |
|
| 148 | - * @return string |
|
| 149 | - * @throws EE_Error |
|
| 150 | - * @throws InvalidArgumentException |
|
| 151 | - * @throws InvalidDataTypeException |
|
| 152 | - * @throws InvalidInterfaceException |
|
| 153 | - * @throws ReflectionException |
|
| 154 | - */ |
|
| 155 | - public function name() |
|
| 156 | - { |
|
| 157 | - $name = $this->get('LIN_name'); |
|
| 158 | - if (! $name) { |
|
| 159 | - $name = ucwords(str_replace('-', ' ', $this->type())); |
|
| 160 | - } |
|
| 161 | - return $name; |
|
| 162 | - } |
|
| 163 | - |
|
| 164 | - |
|
| 165 | - /** |
|
| 166 | - * Sets name |
|
| 167 | - * |
|
| 168 | - * @param string $name |
|
| 169 | - * @throws EE_Error |
|
| 170 | - * @throws InvalidArgumentException |
|
| 171 | - * @throws InvalidDataTypeException |
|
| 172 | - * @throws InvalidInterfaceException |
|
| 173 | - * @throws ReflectionException |
|
| 174 | - */ |
|
| 175 | - public function set_name($name) |
|
| 176 | - { |
|
| 177 | - $this->set('LIN_name', $name); |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - |
|
| 181 | - /** |
|
| 182 | - * Gets desc |
|
| 183 | - * |
|
| 184 | - * @return string |
|
| 185 | - * @throws EE_Error |
|
| 186 | - * @throws InvalidArgumentException |
|
| 187 | - * @throws InvalidDataTypeException |
|
| 188 | - * @throws InvalidInterfaceException |
|
| 189 | - * @throws ReflectionException |
|
| 190 | - */ |
|
| 191 | - public function desc() |
|
| 192 | - { |
|
| 193 | - return $this->get('LIN_desc'); |
|
| 194 | - } |
|
| 195 | - |
|
| 196 | - |
|
| 197 | - /** |
|
| 198 | - * Sets desc |
|
| 199 | - * |
|
| 200 | - * @param string $desc |
|
| 201 | - * @throws EE_Error |
|
| 202 | - * @throws InvalidArgumentException |
|
| 203 | - * @throws InvalidDataTypeException |
|
| 204 | - * @throws InvalidInterfaceException |
|
| 205 | - * @throws ReflectionException |
|
| 206 | - */ |
|
| 207 | - public function set_desc($desc) |
|
| 208 | - { |
|
| 209 | - $this->set('LIN_desc', $desc); |
|
| 210 | - } |
|
| 211 | - |
|
| 212 | - |
|
| 213 | - /** |
|
| 214 | - * Gets quantity |
|
| 215 | - * |
|
| 216 | - * @return int |
|
| 217 | - * @throws EE_Error |
|
| 218 | - * @throws InvalidArgumentException |
|
| 219 | - * @throws InvalidDataTypeException |
|
| 220 | - * @throws InvalidInterfaceException |
|
| 221 | - * @throws ReflectionException |
|
| 222 | - */ |
|
| 223 | - public function quantity() |
|
| 224 | - { |
|
| 225 | - return $this->get('LIN_quantity'); |
|
| 226 | - } |
|
| 227 | - |
|
| 228 | - |
|
| 229 | - /** |
|
| 230 | - * Sets quantity |
|
| 231 | - * |
|
| 232 | - * @param int $quantity |
|
| 233 | - * @throws EE_Error |
|
| 234 | - * @throws InvalidArgumentException |
|
| 235 | - * @throws InvalidDataTypeException |
|
| 236 | - * @throws InvalidInterfaceException |
|
| 237 | - * @throws ReflectionException |
|
| 238 | - */ |
|
| 239 | - public function set_quantity($quantity) |
|
| 240 | - { |
|
| 241 | - $this->set('LIN_quantity', max($quantity, 0)); |
|
| 242 | - } |
|
| 243 | - |
|
| 244 | - |
|
| 245 | - /** |
|
| 246 | - * Gets item_id |
|
| 247 | - * |
|
| 248 | - * @return string |
|
| 249 | - * @throws EE_Error |
|
| 250 | - * @throws InvalidArgumentException |
|
| 251 | - * @throws InvalidDataTypeException |
|
| 252 | - * @throws InvalidInterfaceException |
|
| 253 | - * @throws ReflectionException |
|
| 254 | - */ |
|
| 255 | - public function OBJ_ID() |
|
| 256 | - { |
|
| 257 | - return $this->get('OBJ_ID'); |
|
| 258 | - } |
|
| 259 | - |
|
| 260 | - |
|
| 261 | - /** |
|
| 262 | - * Sets item_id |
|
| 263 | - * |
|
| 264 | - * @param string $item_id |
|
| 265 | - * @throws EE_Error |
|
| 266 | - * @throws InvalidArgumentException |
|
| 267 | - * @throws InvalidDataTypeException |
|
| 268 | - * @throws InvalidInterfaceException |
|
| 269 | - * @throws ReflectionException |
|
| 270 | - */ |
|
| 271 | - public function set_OBJ_ID($item_id) |
|
| 272 | - { |
|
| 273 | - $this->set('OBJ_ID', $item_id); |
|
| 274 | - } |
|
| 275 | - |
|
| 276 | - |
|
| 277 | - /** |
|
| 278 | - * Gets item_type |
|
| 279 | - * |
|
| 280 | - * @return string |
|
| 281 | - * @throws EE_Error |
|
| 282 | - * @throws InvalidArgumentException |
|
| 283 | - * @throws InvalidDataTypeException |
|
| 284 | - * @throws InvalidInterfaceException |
|
| 285 | - * @throws ReflectionException |
|
| 286 | - */ |
|
| 287 | - public function OBJ_type() |
|
| 288 | - { |
|
| 289 | - return $this->get('OBJ_type'); |
|
| 290 | - } |
|
| 291 | - |
|
| 292 | - |
|
| 293 | - /** |
|
| 294 | - * Gets item_type |
|
| 295 | - * |
|
| 296 | - * @return string |
|
| 297 | - * @throws EE_Error |
|
| 298 | - * @throws InvalidArgumentException |
|
| 299 | - * @throws InvalidDataTypeException |
|
| 300 | - * @throws InvalidInterfaceException |
|
| 301 | - * @throws ReflectionException |
|
| 302 | - */ |
|
| 303 | - public function OBJ_type_i18n() |
|
| 304 | - { |
|
| 305 | - $obj_type = $this->OBJ_type(); |
|
| 306 | - switch ($obj_type) { |
|
| 307 | - case EEM_Line_Item::OBJ_TYPE_EVENT: |
|
| 308 | - $obj_type = esc_html__('Event', 'event_espresso'); |
|
| 309 | - break; |
|
| 310 | - case EEM_Line_Item::OBJ_TYPE_PRICE: |
|
| 311 | - $obj_type = esc_html__('Price', 'event_espresso'); |
|
| 312 | - break; |
|
| 313 | - case EEM_Line_Item::OBJ_TYPE_PROMOTION: |
|
| 314 | - $obj_type = esc_html__('Promotion', 'event_espresso'); |
|
| 315 | - break; |
|
| 316 | - case EEM_Line_Item::OBJ_TYPE_TICKET: |
|
| 317 | - $obj_type = esc_html__('Ticket', 'event_espresso'); |
|
| 318 | - break; |
|
| 319 | - case EEM_Line_Item::OBJ_TYPE_TRANSACTION: |
|
| 320 | - $obj_type = esc_html__('Transaction', 'event_espresso'); |
|
| 321 | - break; |
|
| 322 | - } |
|
| 323 | - return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
| 324 | - } |
|
| 325 | - |
|
| 326 | - |
|
| 327 | - /** |
|
| 328 | - * Sets item_type |
|
| 329 | - * |
|
| 330 | - * @param string $OBJ_type |
|
| 331 | - * @throws EE_Error |
|
| 332 | - * @throws InvalidArgumentException |
|
| 333 | - * @throws InvalidDataTypeException |
|
| 334 | - * @throws InvalidInterfaceException |
|
| 335 | - * @throws ReflectionException |
|
| 336 | - */ |
|
| 337 | - public function set_OBJ_type($OBJ_type) |
|
| 338 | - { |
|
| 339 | - $this->set('OBJ_type', $OBJ_type); |
|
| 340 | - } |
|
| 341 | - |
|
| 342 | - |
|
| 343 | - /** |
|
| 344 | - * Gets unit_price |
|
| 345 | - * |
|
| 346 | - * @return float |
|
| 347 | - * @throws EE_Error |
|
| 348 | - * @throws InvalidArgumentException |
|
| 349 | - * @throws InvalidDataTypeException |
|
| 350 | - * @throws InvalidInterfaceException |
|
| 351 | - * @throws ReflectionException |
|
| 352 | - */ |
|
| 353 | - public function unit_price() |
|
| 354 | - { |
|
| 355 | - return $this->get('LIN_unit_price'); |
|
| 356 | - } |
|
| 357 | - |
|
| 358 | - |
|
| 359 | - /** |
|
| 360 | - * Sets unit_price |
|
| 361 | - * |
|
| 362 | - * @param float $unit_price |
|
| 363 | - * @throws EE_Error |
|
| 364 | - * @throws InvalidArgumentException |
|
| 365 | - * @throws InvalidDataTypeException |
|
| 366 | - * @throws InvalidInterfaceException |
|
| 367 | - * @throws ReflectionException |
|
| 368 | - */ |
|
| 369 | - public function set_unit_price($unit_price) |
|
| 370 | - { |
|
| 371 | - $this->set('LIN_unit_price', $unit_price); |
|
| 372 | - } |
|
| 373 | - |
|
| 374 | - |
|
| 375 | - /** |
|
| 376 | - * Checks if this item is a percentage modifier or not |
|
| 377 | - * |
|
| 378 | - * @return boolean |
|
| 379 | - * @throws EE_Error |
|
| 380 | - * @throws InvalidArgumentException |
|
| 381 | - * @throws InvalidDataTypeException |
|
| 382 | - * @throws InvalidInterfaceException |
|
| 383 | - * @throws ReflectionException |
|
| 384 | - */ |
|
| 385 | - public function is_percent() |
|
| 386 | - { |
|
| 387 | - if ($this->is_tax_sub_total()) { |
|
| 388 | - // tax subtotals HAVE a percent on them, that percentage only applies |
|
| 389 | - // to taxable items, so its' an exception. Treat it like a flat line item |
|
| 390 | - return false; |
|
| 391 | - } |
|
| 392 | - $unit_price = abs($this->get('LIN_unit_price')); |
|
| 393 | - $percent = abs($this->get('LIN_percent')); |
|
| 394 | - if ($unit_price < .001 && $percent) { |
|
| 395 | - return true; |
|
| 396 | - } |
|
| 397 | - if ($unit_price >= .001 && ! $percent) { |
|
| 398 | - return false; |
|
| 399 | - } |
|
| 400 | - if ($unit_price >= .001 && $percent) { |
|
| 401 | - throw new EE_Error( |
|
| 402 | - sprintf( |
|
| 403 | - esc_html__( |
|
| 404 | - 'A Line Item can not have a unit price of (%s) AND a percent (%s)!', |
|
| 405 | - 'event_espresso' |
|
| 406 | - ), |
|
| 407 | - $unit_price, |
|
| 408 | - $percent |
|
| 409 | - ) |
|
| 410 | - ); |
|
| 411 | - } |
|
| 412 | - // if they're both 0, assume its not a percent item |
|
| 413 | - return false; |
|
| 414 | - } |
|
| 415 | - |
|
| 416 | - |
|
| 417 | - /** |
|
| 418 | - * Gets percent (between 100-.001) |
|
| 419 | - * |
|
| 420 | - * @return float |
|
| 421 | - * @throws EE_Error |
|
| 422 | - * @throws InvalidArgumentException |
|
| 423 | - * @throws InvalidDataTypeException |
|
| 424 | - * @throws InvalidInterfaceException |
|
| 425 | - * @throws ReflectionException |
|
| 426 | - */ |
|
| 427 | - public function percent() |
|
| 428 | - { |
|
| 429 | - return $this->get('LIN_percent'); |
|
| 430 | - } |
|
| 431 | - |
|
| 432 | - |
|
| 433 | - /** |
|
| 434 | - * Sets percent (between 100-0.01) |
|
| 435 | - * |
|
| 436 | - * @param float $percent |
|
| 437 | - * @throws EE_Error |
|
| 438 | - * @throws InvalidArgumentException |
|
| 439 | - * @throws InvalidDataTypeException |
|
| 440 | - * @throws InvalidInterfaceException |
|
| 441 | - * @throws ReflectionException |
|
| 442 | - */ |
|
| 443 | - public function set_percent($percent) |
|
| 444 | - { |
|
| 445 | - $this->set('LIN_percent', $percent); |
|
| 446 | - } |
|
| 447 | - |
|
| 448 | - |
|
| 449 | - /** |
|
| 450 | - * Gets total |
|
| 451 | - * |
|
| 452 | - * @return float |
|
| 453 | - * @throws EE_Error |
|
| 454 | - * @throws InvalidArgumentException |
|
| 455 | - * @throws InvalidDataTypeException |
|
| 456 | - * @throws InvalidInterfaceException |
|
| 457 | - * @throws ReflectionException |
|
| 458 | - */ |
|
| 459 | - public function total() |
|
| 460 | - { |
|
| 461 | - return $this->get('LIN_total'); |
|
| 462 | - } |
|
| 463 | - |
|
| 464 | - |
|
| 465 | - /** |
|
| 466 | - * Sets total |
|
| 467 | - * |
|
| 468 | - * @param float $total |
|
| 469 | - * @throws EE_Error |
|
| 470 | - * @throws InvalidArgumentException |
|
| 471 | - * @throws InvalidDataTypeException |
|
| 472 | - * @throws InvalidInterfaceException |
|
| 473 | - * @throws ReflectionException |
|
| 474 | - */ |
|
| 475 | - public function set_total($total) |
|
| 476 | - { |
|
| 477 | - $this->set('LIN_total', $total); |
|
| 478 | - } |
|
| 479 | - |
|
| 480 | - |
|
| 481 | - /** |
|
| 482 | - * Gets order |
|
| 483 | - * |
|
| 484 | - * @return int |
|
| 485 | - * @throws EE_Error |
|
| 486 | - * @throws InvalidArgumentException |
|
| 487 | - * @throws InvalidDataTypeException |
|
| 488 | - * @throws InvalidInterfaceException |
|
| 489 | - * @throws ReflectionException |
|
| 490 | - */ |
|
| 491 | - public function order() |
|
| 492 | - { |
|
| 493 | - return $this->get('LIN_order'); |
|
| 494 | - } |
|
| 495 | - |
|
| 496 | - |
|
| 497 | - /** |
|
| 498 | - * Sets order |
|
| 499 | - * |
|
| 500 | - * @param int $order |
|
| 501 | - * @throws EE_Error |
|
| 502 | - * @throws InvalidArgumentException |
|
| 503 | - * @throws InvalidDataTypeException |
|
| 504 | - * @throws InvalidInterfaceException |
|
| 505 | - * @throws ReflectionException |
|
| 506 | - */ |
|
| 507 | - public function set_order($order) |
|
| 508 | - { |
|
| 509 | - $this->set('LIN_order', $order); |
|
| 510 | - } |
|
| 511 | - |
|
| 512 | - |
|
| 513 | - /** |
|
| 514 | - * Gets parent |
|
| 515 | - * |
|
| 516 | - * @return int |
|
| 517 | - * @throws EE_Error |
|
| 518 | - * @throws InvalidArgumentException |
|
| 519 | - * @throws InvalidDataTypeException |
|
| 520 | - * @throws InvalidInterfaceException |
|
| 521 | - * @throws ReflectionException |
|
| 522 | - */ |
|
| 523 | - public function parent_ID() |
|
| 524 | - { |
|
| 525 | - return $this->get('LIN_parent'); |
|
| 526 | - } |
|
| 527 | - |
|
| 528 | - |
|
| 529 | - /** |
|
| 530 | - * Sets parent |
|
| 531 | - * |
|
| 532 | - * @param int $parent |
|
| 533 | - * @throws EE_Error |
|
| 534 | - * @throws InvalidArgumentException |
|
| 535 | - * @throws InvalidDataTypeException |
|
| 536 | - * @throws InvalidInterfaceException |
|
| 537 | - * @throws ReflectionException |
|
| 538 | - */ |
|
| 539 | - public function set_parent_ID($parent) |
|
| 540 | - { |
|
| 541 | - $this->set('LIN_parent', $parent); |
|
| 542 | - } |
|
| 543 | - |
|
| 544 | - |
|
| 545 | - /** |
|
| 546 | - * Gets type |
|
| 547 | - * |
|
| 548 | - * @return string |
|
| 549 | - * @throws EE_Error |
|
| 550 | - * @throws InvalidArgumentException |
|
| 551 | - * @throws InvalidDataTypeException |
|
| 552 | - * @throws InvalidInterfaceException |
|
| 553 | - * @throws ReflectionException |
|
| 554 | - */ |
|
| 555 | - public function type() |
|
| 556 | - { |
|
| 557 | - return $this->get('LIN_type'); |
|
| 558 | - } |
|
| 559 | - |
|
| 560 | - |
|
| 561 | - /** |
|
| 562 | - * Sets type |
|
| 563 | - * |
|
| 564 | - * @param string $type |
|
| 565 | - * @throws EE_Error |
|
| 566 | - * @throws InvalidArgumentException |
|
| 567 | - * @throws InvalidDataTypeException |
|
| 568 | - * @throws InvalidInterfaceException |
|
| 569 | - * @throws ReflectionException |
|
| 570 | - */ |
|
| 571 | - public function set_type($type) |
|
| 572 | - { |
|
| 573 | - $this->set('LIN_type', $type); |
|
| 574 | - } |
|
| 575 | - |
|
| 576 | - |
|
| 577 | - /** |
|
| 578 | - * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
| 579 | - * 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 |
|
| 580 | - * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
| 581 | - * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
| 582 | - * |
|
| 583 | - * @return EE_Base_Class|EE_Line_Item |
|
| 584 | - * @throws EE_Error |
|
| 585 | - * @throws InvalidArgumentException |
|
| 586 | - * @throws InvalidDataTypeException |
|
| 587 | - * @throws InvalidInterfaceException |
|
| 588 | - * @throws ReflectionException |
|
| 589 | - */ |
|
| 590 | - public function parent() |
|
| 591 | - { |
|
| 592 | - return $this->ID() |
|
| 593 | - ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
| 594 | - : $this->_parent; |
|
| 595 | - } |
|
| 596 | - |
|
| 597 | - |
|
| 598 | - /** |
|
| 599 | - * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
| 600 | - * |
|
| 601 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 602 | - * @throws EE_Error |
|
| 603 | - * @throws InvalidArgumentException |
|
| 604 | - * @throws InvalidDataTypeException |
|
| 605 | - * @throws InvalidInterfaceException |
|
| 606 | - * @throws ReflectionException |
|
| 607 | - */ |
|
| 608 | - public function children() |
|
| 609 | - { |
|
| 610 | - if ($this->ID()) { |
|
| 611 | - return $this->get_model()->get_all( |
|
| 612 | - array( |
|
| 613 | - array('LIN_parent' => $this->ID()), |
|
| 614 | - 'order_by' => array('LIN_order' => 'ASC'), |
|
| 615 | - ) |
|
| 616 | - ); |
|
| 617 | - } |
|
| 618 | - if (! is_array($this->_children)) { |
|
| 619 | - $this->_children = array(); |
|
| 620 | - } |
|
| 621 | - return $this->_children; |
|
| 622 | - } |
|
| 623 | - |
|
| 624 | - |
|
| 625 | - /** |
|
| 626 | - * Gets code |
|
| 627 | - * |
|
| 628 | - * @return string |
|
| 629 | - * @throws EE_Error |
|
| 630 | - * @throws InvalidArgumentException |
|
| 631 | - * @throws InvalidDataTypeException |
|
| 632 | - * @throws InvalidInterfaceException |
|
| 633 | - * @throws ReflectionException |
|
| 634 | - */ |
|
| 635 | - public function code() |
|
| 636 | - { |
|
| 637 | - return $this->get('LIN_code'); |
|
| 638 | - } |
|
| 639 | - |
|
| 640 | - |
|
| 641 | - /** |
|
| 642 | - * Sets code |
|
| 643 | - * |
|
| 644 | - * @param string $code |
|
| 645 | - * @throws EE_Error |
|
| 646 | - * @throws InvalidArgumentException |
|
| 647 | - * @throws InvalidDataTypeException |
|
| 648 | - * @throws InvalidInterfaceException |
|
| 649 | - * @throws ReflectionException |
|
| 650 | - */ |
|
| 651 | - public function set_code($code) |
|
| 652 | - { |
|
| 653 | - $this->set('LIN_code', $code); |
|
| 654 | - } |
|
| 655 | - |
|
| 656 | - |
|
| 657 | - /** |
|
| 658 | - * Gets is_taxable |
|
| 659 | - * |
|
| 660 | - * @return boolean |
|
| 661 | - * @throws EE_Error |
|
| 662 | - * @throws InvalidArgumentException |
|
| 663 | - * @throws InvalidDataTypeException |
|
| 664 | - * @throws InvalidInterfaceException |
|
| 665 | - * @throws ReflectionException |
|
| 666 | - */ |
|
| 667 | - public function is_taxable() |
|
| 668 | - { |
|
| 669 | - return $this->get('LIN_is_taxable'); |
|
| 670 | - } |
|
| 671 | - |
|
| 672 | - |
|
| 673 | - /** |
|
| 674 | - * Sets is_taxable |
|
| 675 | - * |
|
| 676 | - * @param boolean $is_taxable |
|
| 677 | - * @throws EE_Error |
|
| 678 | - * @throws InvalidArgumentException |
|
| 679 | - * @throws InvalidDataTypeException |
|
| 680 | - * @throws InvalidInterfaceException |
|
| 681 | - * @throws ReflectionException |
|
| 682 | - */ |
|
| 683 | - public function set_is_taxable($is_taxable) |
|
| 684 | - { |
|
| 685 | - $this->set('LIN_is_taxable', $is_taxable); |
|
| 686 | - } |
|
| 687 | - |
|
| 688 | - |
|
| 689 | - /** |
|
| 690 | - * Gets the object that this model-joins-to. |
|
| 691 | - * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
| 692 | - * EEM_Promotion_Object |
|
| 693 | - * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
| 694 | - * |
|
| 695 | - * @return EE_Base_Class | NULL |
|
| 696 | - * @throws EE_Error |
|
| 697 | - * @throws InvalidArgumentException |
|
| 698 | - * @throws InvalidDataTypeException |
|
| 699 | - * @throws InvalidInterfaceException |
|
| 700 | - * @throws ReflectionException |
|
| 701 | - */ |
|
| 702 | - public function get_object() |
|
| 703 | - { |
|
| 704 | - $model_name_of_related_obj = $this->OBJ_type(); |
|
| 705 | - return $this->get_model()->has_relation($model_name_of_related_obj) |
|
| 706 | - ? $this->get_first_related($model_name_of_related_obj) |
|
| 707 | - : null; |
|
| 708 | - } |
|
| 709 | - |
|
| 710 | - |
|
| 711 | - /** |
|
| 712 | - * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
| 713 | - * (IE, if this line item is for a price or something else, will return NULL) |
|
| 714 | - * |
|
| 715 | - * @param array $query_params |
|
| 716 | - * @return EE_Base_Class|EE_Ticket |
|
| 717 | - * @throws EE_Error |
|
| 718 | - * @throws InvalidArgumentException |
|
| 719 | - * @throws InvalidDataTypeException |
|
| 720 | - * @throws InvalidInterfaceException |
|
| 721 | - * @throws ReflectionException |
|
| 722 | - */ |
|
| 723 | - public function ticket($query_params = array()) |
|
| 724 | - { |
|
| 725 | - // we're going to assume that when this method is called |
|
| 726 | - // we always want to receive the attached ticket EVEN if that ticket is archived. |
|
| 727 | - // This can be overridden via the incoming $query_params argument |
|
| 728 | - $remove_defaults = array('default_where_conditions' => 'none'); |
|
| 729 | - $query_params = array_merge($remove_defaults, $query_params); |
|
| 730 | - return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params); |
|
| 731 | - } |
|
| 732 | - |
|
| 733 | - |
|
| 734 | - /** |
|
| 735 | - * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
| 736 | - * |
|
| 737 | - * @return EE_Datetime | NULL |
|
| 738 | - * @throws EE_Error |
|
| 739 | - * @throws InvalidArgumentException |
|
| 740 | - * @throws InvalidDataTypeException |
|
| 741 | - * @throws InvalidInterfaceException |
|
| 742 | - * @throws ReflectionException |
|
| 743 | - */ |
|
| 744 | - public function get_ticket_datetime() |
|
| 745 | - { |
|
| 746 | - if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 747 | - $ticket = $this->ticket(); |
|
| 748 | - if ($ticket instanceof EE_Ticket) { |
|
| 749 | - $datetime = $ticket->first_datetime(); |
|
| 750 | - if ($datetime instanceof EE_Datetime) { |
|
| 751 | - return $datetime; |
|
| 752 | - } |
|
| 753 | - } |
|
| 754 | - } |
|
| 755 | - return null; |
|
| 756 | - } |
|
| 757 | - |
|
| 758 | - |
|
| 759 | - /** |
|
| 760 | - * Gets the event's name that's related to the ticket, if this is for |
|
| 761 | - * a ticket |
|
| 762 | - * |
|
| 763 | - * @return string |
|
| 764 | - * @throws EE_Error |
|
| 765 | - * @throws InvalidArgumentException |
|
| 766 | - * @throws InvalidDataTypeException |
|
| 767 | - * @throws InvalidInterfaceException |
|
| 768 | - * @throws ReflectionException |
|
| 769 | - */ |
|
| 770 | - public function ticket_event_name() |
|
| 771 | - { |
|
| 772 | - $event_name = esc_html__('Unknown', 'event_espresso'); |
|
| 773 | - $event = $this->ticket_event(); |
|
| 774 | - if ($event instanceof EE_Event) { |
|
| 775 | - $event_name = $event->name(); |
|
| 776 | - } |
|
| 777 | - return $event_name; |
|
| 778 | - } |
|
| 779 | - |
|
| 780 | - |
|
| 781 | - /** |
|
| 782 | - * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
| 783 | - * |
|
| 784 | - * @return EE_Event|null |
|
| 785 | - * @throws EE_Error |
|
| 786 | - * @throws InvalidArgumentException |
|
| 787 | - * @throws InvalidDataTypeException |
|
| 788 | - * @throws InvalidInterfaceException |
|
| 789 | - * @throws ReflectionException |
|
| 790 | - */ |
|
| 791 | - public function ticket_event() |
|
| 792 | - { |
|
| 793 | - $event = null; |
|
| 794 | - $ticket = $this->ticket(); |
|
| 795 | - if ($ticket instanceof EE_Ticket) { |
|
| 796 | - $datetime = $ticket->first_datetime(); |
|
| 797 | - if ($datetime instanceof EE_Datetime) { |
|
| 798 | - $event = $datetime->event(); |
|
| 799 | - } |
|
| 800 | - } |
|
| 801 | - return $event; |
|
| 802 | - } |
|
| 803 | - |
|
| 804 | - |
|
| 805 | - /** |
|
| 806 | - * Gets the first datetime for this lien item, assuming it's for a ticket |
|
| 807 | - * |
|
| 808 | - * @param string $date_format |
|
| 809 | - * @param string $time_format |
|
| 810 | - * @return string |
|
| 811 | - * @throws EE_Error |
|
| 812 | - * @throws InvalidArgumentException |
|
| 813 | - * @throws InvalidDataTypeException |
|
| 814 | - * @throws InvalidInterfaceException |
|
| 815 | - * @throws ReflectionException |
|
| 816 | - */ |
|
| 817 | - public function ticket_datetime_start($date_format = '', $time_format = '') |
|
| 818 | - { |
|
| 819 | - $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
| 820 | - $datetime = $this->get_ticket_datetime(); |
|
| 821 | - if ($datetime) { |
|
| 822 | - $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
| 823 | - } |
|
| 824 | - return $first_datetime_string; |
|
| 825 | - } |
|
| 826 | - |
|
| 827 | - |
|
| 828 | - /** |
|
| 829 | - * Adds the line item as a child to this line item. If there is another child line |
|
| 830 | - * item with the same LIN_code, it is overwritten by this new one |
|
| 831 | - * |
|
| 832 | - * @param EEI_Line_Item $line_item |
|
| 833 | - * @param bool $set_order |
|
| 834 | - * @return bool success |
|
| 835 | - * @throws EE_Error |
|
| 836 | - * @throws InvalidArgumentException |
|
| 837 | - * @throws InvalidDataTypeException |
|
| 838 | - * @throws InvalidInterfaceException |
|
| 839 | - * @throws ReflectionException |
|
| 840 | - */ |
|
| 841 | - public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
| 842 | - { |
|
| 843 | - // should we calculate the LIN_order for this line item ? |
|
| 844 | - if ($set_order || $line_item->order() === null) { |
|
| 845 | - $line_item->set_order(count($this->children())); |
|
| 846 | - } |
|
| 847 | - if ($this->ID()) { |
|
| 848 | - // check for any duplicate line items (with the same code), if so, this replaces it |
|
| 849 | - $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
| 850 | - if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
| 851 | - $this->delete_child_line_item($line_item_with_same_code->code()); |
|
| 852 | - } |
|
| 853 | - $line_item->set_parent_ID($this->ID()); |
|
| 854 | - if ($this->TXN_ID()) { |
|
| 855 | - $line_item->set_TXN_ID($this->TXN_ID()); |
|
| 856 | - } |
|
| 857 | - return $line_item->save(); |
|
| 858 | - } |
|
| 859 | - $this->_children[ $line_item->code() ] = $line_item; |
|
| 860 | - if ($line_item->parent() !== $this) { |
|
| 861 | - $line_item->set_parent($this); |
|
| 862 | - } |
|
| 863 | - return true; |
|
| 864 | - } |
|
| 865 | - |
|
| 866 | - |
|
| 867 | - /** |
|
| 868 | - * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
| 869 | - * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
| 870 | - * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
| 871 | - * the EE_Line_Item::_parent property. |
|
| 872 | - * |
|
| 873 | - * @param EE_Line_Item $line_item |
|
| 874 | - * @throws EE_Error |
|
| 875 | - * @throws InvalidArgumentException |
|
| 876 | - * @throws InvalidDataTypeException |
|
| 877 | - * @throws InvalidInterfaceException |
|
| 878 | - * @throws ReflectionException |
|
| 879 | - */ |
|
| 880 | - public function set_parent($line_item) |
|
| 881 | - { |
|
| 882 | - if ($this->ID()) { |
|
| 883 | - if (! $line_item->ID()) { |
|
| 884 | - $line_item->save(); |
|
| 885 | - } |
|
| 886 | - $this->set_parent_ID($line_item->ID()); |
|
| 887 | - $this->save(); |
|
| 888 | - } else { |
|
| 889 | - $this->_parent = $line_item; |
|
| 890 | - $this->set_parent_ID($line_item->ID()); |
|
| 891 | - } |
|
| 892 | - } |
|
| 893 | - |
|
| 894 | - |
|
| 895 | - /** |
|
| 896 | - * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
| 897 | - * you can modify this child line item and the parent (this object) can know about them |
|
| 898 | - * because it also has a reference to that line item |
|
| 899 | - * |
|
| 900 | - * @param string $code |
|
| 901 | - * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 902 | - * @throws EE_Error |
|
| 903 | - * @throws InvalidArgumentException |
|
| 904 | - * @throws InvalidDataTypeException |
|
| 905 | - * @throws InvalidInterfaceException |
|
| 906 | - * @throws ReflectionException |
|
| 907 | - */ |
|
| 908 | - public function get_child_line_item($code) |
|
| 909 | - { |
|
| 910 | - if ($this->ID()) { |
|
| 911 | - return $this->get_model()->get_one( |
|
| 912 | - array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
| 913 | - ); |
|
| 914 | - } |
|
| 915 | - return isset($this->_children[ $code ]) |
|
| 916 | - ? $this->_children[ $code ] |
|
| 917 | - : null; |
|
| 918 | - } |
|
| 919 | - |
|
| 920 | - |
|
| 921 | - /** |
|
| 922 | - * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
| 923 | - * cached on it) |
|
| 924 | - * |
|
| 925 | - * @return int |
|
| 926 | - * @throws EE_Error |
|
| 927 | - * @throws InvalidArgumentException |
|
| 928 | - * @throws InvalidDataTypeException |
|
| 929 | - * @throws InvalidInterfaceException |
|
| 930 | - * @throws ReflectionException |
|
| 931 | - */ |
|
| 932 | - public function delete_children_line_items() |
|
| 933 | - { |
|
| 934 | - if ($this->ID()) { |
|
| 935 | - return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
| 936 | - } |
|
| 937 | - $count = count($this->_children); |
|
| 938 | - $this->_children = array(); |
|
| 939 | - return $count; |
|
| 940 | - } |
|
| 941 | - |
|
| 942 | - |
|
| 943 | - /** |
|
| 944 | - * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
| 945 | - * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
| 946 | - * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
| 947 | - * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
| 948 | - * deleted) |
|
| 949 | - * |
|
| 950 | - * @param string $code |
|
| 951 | - * @param bool $stop_search_once_found |
|
| 952 | - * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
| 953 | - * the DB yet) |
|
| 954 | - * @throws EE_Error |
|
| 955 | - * @throws InvalidArgumentException |
|
| 956 | - * @throws InvalidDataTypeException |
|
| 957 | - * @throws InvalidInterfaceException |
|
| 958 | - * @throws ReflectionException |
|
| 959 | - */ |
|
| 960 | - public function delete_child_line_item($code, $stop_search_once_found = true) |
|
| 961 | - { |
|
| 962 | - if ($this->ID()) { |
|
| 963 | - $items_deleted = 0; |
|
| 964 | - if ($this->code() === $code) { |
|
| 965 | - $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
| 966 | - $items_deleted += (int) $this->delete(); |
|
| 967 | - if ($stop_search_once_found) { |
|
| 968 | - return $items_deleted; |
|
| 969 | - } |
|
| 970 | - } |
|
| 971 | - foreach ($this->children() as $child_line_item) { |
|
| 972 | - $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
| 973 | - } |
|
| 974 | - return $items_deleted; |
|
| 975 | - } |
|
| 976 | - if (isset($this->_children[ $code ])) { |
|
| 977 | - unset($this->_children[ $code ]); |
|
| 978 | - return 1; |
|
| 979 | - } |
|
| 980 | - return 0; |
|
| 981 | - } |
|
| 982 | - |
|
| 983 | - |
|
| 984 | - /** |
|
| 985 | - * If this line item is in the database, is of the type subtotal, and |
|
| 986 | - * has no children, why do we have it? It should be deleted so this function |
|
| 987 | - * does that |
|
| 988 | - * |
|
| 989 | - * @return boolean |
|
| 990 | - * @throws EE_Error |
|
| 991 | - * @throws InvalidArgumentException |
|
| 992 | - * @throws InvalidDataTypeException |
|
| 993 | - * @throws InvalidInterfaceException |
|
| 994 | - * @throws ReflectionException |
|
| 995 | - */ |
|
| 996 | - public function delete_if_childless_subtotal() |
|
| 997 | - { |
|
| 998 | - if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
| 999 | - return $this->delete(); |
|
| 1000 | - } |
|
| 1001 | - return false; |
|
| 1002 | - } |
|
| 1003 | - |
|
| 1004 | - |
|
| 1005 | - /** |
|
| 1006 | - * Creates a code and returns a string. doesn't assign the code to this model object |
|
| 1007 | - * |
|
| 1008 | - * @return string |
|
| 1009 | - * @throws EE_Error |
|
| 1010 | - * @throws InvalidArgumentException |
|
| 1011 | - * @throws InvalidDataTypeException |
|
| 1012 | - * @throws InvalidInterfaceException |
|
| 1013 | - * @throws ReflectionException |
|
| 1014 | - */ |
|
| 1015 | - public function generate_code() |
|
| 1016 | - { |
|
| 1017 | - // each line item in the cart requires a unique identifier |
|
| 1018 | - return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
| 1019 | - } |
|
| 1020 | - |
|
| 1021 | - |
|
| 1022 | - /** |
|
| 1023 | - * @return bool |
|
| 1024 | - * @throws EE_Error |
|
| 1025 | - * @throws InvalidArgumentException |
|
| 1026 | - * @throws InvalidDataTypeException |
|
| 1027 | - * @throws InvalidInterfaceException |
|
| 1028 | - * @throws ReflectionException |
|
| 1029 | - */ |
|
| 1030 | - public function is_tax() |
|
| 1031 | - { |
|
| 1032 | - return $this->type() === EEM_Line_Item::type_tax; |
|
| 1033 | - } |
|
| 1034 | - |
|
| 1035 | - |
|
| 1036 | - /** |
|
| 1037 | - * @return bool |
|
| 1038 | - * @throws EE_Error |
|
| 1039 | - * @throws InvalidArgumentException |
|
| 1040 | - * @throws InvalidDataTypeException |
|
| 1041 | - * @throws InvalidInterfaceException |
|
| 1042 | - * @throws ReflectionException |
|
| 1043 | - */ |
|
| 1044 | - public function is_tax_sub_total() |
|
| 1045 | - { |
|
| 1046 | - return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
| 1047 | - } |
|
| 1048 | - |
|
| 1049 | - |
|
| 1050 | - /** |
|
| 1051 | - * @return bool |
|
| 1052 | - * @throws EE_Error |
|
| 1053 | - * @throws InvalidArgumentException |
|
| 1054 | - * @throws InvalidDataTypeException |
|
| 1055 | - * @throws InvalidInterfaceException |
|
| 1056 | - * @throws ReflectionException |
|
| 1057 | - */ |
|
| 1058 | - public function is_line_item() |
|
| 1059 | - { |
|
| 1060 | - return $this->type() === EEM_Line_Item::type_line_item; |
|
| 1061 | - } |
|
| 1062 | - |
|
| 1063 | - |
|
| 1064 | - /** |
|
| 1065 | - * @return bool |
|
| 1066 | - * @throws EE_Error |
|
| 1067 | - * @throws InvalidArgumentException |
|
| 1068 | - * @throws InvalidDataTypeException |
|
| 1069 | - * @throws InvalidInterfaceException |
|
| 1070 | - * @throws ReflectionException |
|
| 1071 | - */ |
|
| 1072 | - public function is_sub_line_item() |
|
| 1073 | - { |
|
| 1074 | - return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
| 1075 | - } |
|
| 1076 | - |
|
| 1077 | - |
|
| 1078 | - /** |
|
| 1079 | - * @return bool |
|
| 1080 | - * @throws EE_Error |
|
| 1081 | - * @throws InvalidArgumentException |
|
| 1082 | - * @throws InvalidDataTypeException |
|
| 1083 | - * @throws InvalidInterfaceException |
|
| 1084 | - * @throws ReflectionException |
|
| 1085 | - */ |
|
| 1086 | - public function is_sub_total() |
|
| 1087 | - { |
|
| 1088 | - return $this->type() === EEM_Line_Item::type_sub_total; |
|
| 1089 | - } |
|
| 1090 | - |
|
| 1091 | - |
|
| 1092 | - /** |
|
| 1093 | - * Whether or not this line item is a cancellation line item |
|
| 1094 | - * |
|
| 1095 | - * @return boolean |
|
| 1096 | - * @throws EE_Error |
|
| 1097 | - * @throws InvalidArgumentException |
|
| 1098 | - * @throws InvalidDataTypeException |
|
| 1099 | - * @throws InvalidInterfaceException |
|
| 1100 | - * @throws ReflectionException |
|
| 1101 | - */ |
|
| 1102 | - public function is_cancellation() |
|
| 1103 | - { |
|
| 1104 | - return EEM_Line_Item::type_cancellation === $this->type(); |
|
| 1105 | - } |
|
| 1106 | - |
|
| 1107 | - |
|
| 1108 | - /** |
|
| 1109 | - * @return bool |
|
| 1110 | - * @throws EE_Error |
|
| 1111 | - * @throws InvalidArgumentException |
|
| 1112 | - * @throws InvalidDataTypeException |
|
| 1113 | - * @throws InvalidInterfaceException |
|
| 1114 | - * @throws ReflectionException |
|
| 1115 | - */ |
|
| 1116 | - public function is_total() |
|
| 1117 | - { |
|
| 1118 | - return $this->type() === EEM_Line_Item::type_total; |
|
| 1119 | - } |
|
| 1120 | - |
|
| 1121 | - |
|
| 1122 | - /** |
|
| 1123 | - * @return bool |
|
| 1124 | - * @throws EE_Error |
|
| 1125 | - * @throws InvalidArgumentException |
|
| 1126 | - * @throws InvalidDataTypeException |
|
| 1127 | - * @throws InvalidInterfaceException |
|
| 1128 | - * @throws ReflectionException |
|
| 1129 | - */ |
|
| 1130 | - public function is_cancelled() |
|
| 1131 | - { |
|
| 1132 | - return $this->type() === EEM_Line_Item::type_cancellation; |
|
| 1133 | - } |
|
| 1134 | - |
|
| 1135 | - |
|
| 1136 | - /** |
|
| 1137 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
| 1138 | - * @throws EE_Error |
|
| 1139 | - * @throws InvalidArgumentException |
|
| 1140 | - * @throws InvalidDataTypeException |
|
| 1141 | - * @throws InvalidInterfaceException |
|
| 1142 | - * @throws ReflectionException |
|
| 1143 | - */ |
|
| 1144 | - public function unit_price_no_code() |
|
| 1145 | - { |
|
| 1146 | - return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
| 1147 | - } |
|
| 1148 | - |
|
| 1149 | - |
|
| 1150 | - /** |
|
| 1151 | - * @return string like '2, 004.00', formatted according to the localized currency |
|
| 1152 | - * @throws EE_Error |
|
| 1153 | - * @throws InvalidArgumentException |
|
| 1154 | - * @throws InvalidDataTypeException |
|
| 1155 | - * @throws InvalidInterfaceException |
|
| 1156 | - * @throws ReflectionException |
|
| 1157 | - */ |
|
| 1158 | - public function total_no_code() |
|
| 1159 | - { |
|
| 1160 | - return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
| 1161 | - } |
|
| 1162 | - |
|
| 1163 | - |
|
| 1164 | - /** |
|
| 1165 | - * Gets the final total on this item, taking taxes into account. |
|
| 1166 | - * Has the side-effect of setting the sub-total as it was just calculated. |
|
| 1167 | - * If this is used on a grand-total line item, also updates the transaction's |
|
| 1168 | - * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
| 1169 | - * want to change a persistable transaction with info from a non-persistent line item) |
|
| 1170 | - * |
|
| 1171 | - * @param bool $update_txn_status |
|
| 1172 | - * @return float |
|
| 1173 | - * @throws EE_Error |
|
| 1174 | - * @throws InvalidArgumentException |
|
| 1175 | - * @throws InvalidDataTypeException |
|
| 1176 | - * @throws InvalidInterfaceException |
|
| 1177 | - * @throws ReflectionException |
|
| 1178 | - * @throws RuntimeException |
|
| 1179 | - */ |
|
| 1180 | - public function recalculate_total_including_taxes($update_txn_status = false) |
|
| 1181 | - { |
|
| 1182 | - $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
| 1183 | - $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
| 1184 | - $total = $pre_tax_total + $tax_total; |
|
| 1185 | - // no negative totals plz |
|
| 1186 | - $total = max($total, 0); |
|
| 1187 | - $this->set_total($total); |
|
| 1188 | - // only update the related transaction's total |
|
| 1189 | - // if we intend to save this line item and its a grand total |
|
| 1190 | - if ($this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
| 1191 | - && $this->transaction() |
|
| 1192 | - instanceof |
|
| 1193 | - EE_Transaction |
|
| 1194 | - ) { |
|
| 1195 | - $this->transaction()->set_total($total); |
|
| 1196 | - if ($update_txn_status) { |
|
| 1197 | - // don't save the TXN because that will be done below |
|
| 1198 | - // and the following method only saves if the status changes |
|
| 1199 | - $this->transaction()->update_status_based_on_total_paid(false); |
|
| 1200 | - } |
|
| 1201 | - if ($this->transaction()->ID()) { |
|
| 1202 | - $this->transaction()->save(); |
|
| 1203 | - } |
|
| 1204 | - } |
|
| 1205 | - $this->maybe_save(); |
|
| 1206 | - return $total; |
|
| 1207 | - } |
|
| 1208 | - |
|
| 1209 | - |
|
| 1210 | - /** |
|
| 1211 | - * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
| 1212 | - * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
| 1213 | - * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
| 1214 | - * when this is called on the grand total |
|
| 1215 | - * |
|
| 1216 | - * @return float |
|
| 1217 | - * @throws EE_Error |
|
| 1218 | - * @throws InvalidArgumentException |
|
| 1219 | - * @throws InvalidDataTypeException |
|
| 1220 | - * @throws InvalidInterfaceException |
|
| 1221 | - * @throws ReflectionException |
|
| 1222 | - */ |
|
| 1223 | - public function recalculate_pre_tax_total() |
|
| 1224 | - { |
|
| 1225 | - $total = 0; |
|
| 1226 | - $my_children = $this->children(); |
|
| 1227 | - $has_children = ! empty($my_children); |
|
| 1228 | - if ($has_children && $this->is_line_item()) { |
|
| 1229 | - $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
| 1230 | - } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 1231 | - $total = $this->unit_price() * $this->quantity(); |
|
| 1232 | - } elseif ($this->is_sub_total() || $this->is_total()) { |
|
| 1233 | - $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
| 1234 | - } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
| 1235 | - // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
| 1236 | - return 0; |
|
| 1237 | - } |
|
| 1238 | - // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
| 1239 | - if (! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
| 1240 | - ) { |
|
| 1241 | - if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
|
| 1242 | - $this->set_quantity(1); |
|
| 1243 | - } |
|
| 1244 | - if (! $this->is_percent()) { |
|
| 1245 | - $this->set_unit_price($total); |
|
| 1246 | - } |
|
| 1247 | - } |
|
| 1248 | - // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
| 1249 | - // so it ought to be |
|
| 1250 | - if (! $this->is_total()) { |
|
| 1251 | - $this->set_total($total); |
|
| 1252 | - // if not a percent line item, make sure we keep the unit price in sync |
|
| 1253 | - if ($has_children |
|
| 1254 | - && $this->is_line_item() |
|
| 1255 | - && ! $this->is_percent() |
|
| 1256 | - ) { |
|
| 1257 | - if ($this->quantity() === 0) { |
|
| 1258 | - $new_unit_price = 0; |
|
| 1259 | - } else { |
|
| 1260 | - $new_unit_price = $this->total() / $this->quantity(); |
|
| 1261 | - } |
|
| 1262 | - $this->set_unit_price($new_unit_price); |
|
| 1263 | - } |
|
| 1264 | - $this->maybe_save(); |
|
| 1265 | - } |
|
| 1266 | - return $total; |
|
| 1267 | - } |
|
| 1268 | - |
|
| 1269 | - |
|
| 1270 | - /** |
|
| 1271 | - * Calculates the pretax total when this line item is a subtotal or total line item. |
|
| 1272 | - * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
| 1273 | - * will calculate their total based on the un-rounded total we're working with so far, and |
|
| 1274 | - * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
| 1275 | - * |
|
| 1276 | - * @param float $calculated_total_so_far |
|
| 1277 | - * @param EE_Line_Item[] $my_children |
|
| 1278 | - * @return float |
|
| 1279 | - * @throws EE_Error |
|
| 1280 | - * @throws InvalidArgumentException |
|
| 1281 | - * @throws InvalidDataTypeException |
|
| 1282 | - * @throws InvalidInterfaceException |
|
| 1283 | - * @throws ReflectionException |
|
| 1284 | - */ |
|
| 1285 | - protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
| 1286 | - { |
|
| 1287 | - if ($my_children === null) { |
|
| 1288 | - $my_children = $this->children(); |
|
| 1289 | - } |
|
| 1290 | - $subtotal_quantity = 0; |
|
| 1291 | - // get the total of all its children |
|
| 1292 | - foreach ($my_children as $child_line_item) { |
|
| 1293 | - if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
| 1294 | - // percentage line items are based on total so far |
|
| 1295 | - if ($child_line_item->is_percent()) { |
|
| 1296 | - // round as we go so that the line items add up ok |
|
| 1297 | - $percent_total = round( |
|
| 1298 | - $calculated_total_so_far * $child_line_item->percent() / 100, |
|
| 1299 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1300 | - ); |
|
| 1301 | - $child_line_item->set_total($percent_total); |
|
| 1302 | - // so far all percent line items should have a quantity of 1 |
|
| 1303 | - // (ie, no double percent discounts. Although that might be requested someday) |
|
| 1304 | - $child_line_item->set_quantity(1); |
|
| 1305 | - $child_line_item->maybe_save(); |
|
| 1306 | - $calculated_total_so_far += $percent_total; |
|
| 1307 | - } else { |
|
| 1308 | - // verify flat sub-line-item quantities match their parent |
|
| 1309 | - if ($child_line_item->is_sub_line_item()) { |
|
| 1310 | - $child_line_item->set_quantity($this->quantity()); |
|
| 1311 | - } |
|
| 1312 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1313 | - $subtotal_quantity += $child_line_item->quantity(); |
|
| 1314 | - } |
|
| 1315 | - } |
|
| 1316 | - } |
|
| 1317 | - if ($this->is_sub_total()) { |
|
| 1318 | - // no negative totals plz |
|
| 1319 | - $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
| 1320 | - $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
| 1321 | - $this->set_quantity($subtotal_quantity); |
|
| 1322 | - $this->maybe_save(); |
|
| 1323 | - } |
|
| 1324 | - return $calculated_total_so_far; |
|
| 1325 | - } |
|
| 1326 | - |
|
| 1327 | - |
|
| 1328 | - /** |
|
| 1329 | - * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
| 1330 | - * (where each sub-line-item is applied to the base price for the line item |
|
| 1331 | - * and the result is immediately rounded, rather than summing all the sub-line-items |
|
| 1332 | - * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
| 1333 | - * |
|
| 1334 | - * @param float $calculated_total_so_far |
|
| 1335 | - * @param EE_Line_Item[] $my_children |
|
| 1336 | - * @return float |
|
| 1337 | - * @throws EE_Error |
|
| 1338 | - * @throws InvalidArgumentException |
|
| 1339 | - * @throws InvalidDataTypeException |
|
| 1340 | - * @throws InvalidInterfaceException |
|
| 1341 | - * @throws ReflectionException |
|
| 1342 | - */ |
|
| 1343 | - protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
| 1344 | - { |
|
| 1345 | - if ($my_children === null) { |
|
| 1346 | - $my_children = $this->children(); |
|
| 1347 | - } |
|
| 1348 | - // we need to keep track of the running total for a single item, |
|
| 1349 | - // because we need to round as we go |
|
| 1350 | - $unit_price_for_total = 0; |
|
| 1351 | - $quantity_for_total = 1; |
|
| 1352 | - // get the total of all its children |
|
| 1353 | - foreach ($my_children as $child_line_item) { |
|
| 1354 | - if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
| 1355 | - if ($child_line_item->is_percent()) { |
|
| 1356 | - // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
| 1357 | - // not total multiplied by percent, because that ignores rounding along-the-way |
|
| 1358 | - $percent_unit_price = round( |
|
| 1359 | - $unit_price_for_total * $child_line_item->percent() / 100, |
|
| 1360 | - EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1361 | - ); |
|
| 1362 | - $percent_total = $percent_unit_price * $quantity_for_total; |
|
| 1363 | - $child_line_item->set_total($percent_total); |
|
| 1364 | - // so far all percent line items should have a quantity of 1 |
|
| 1365 | - // (ie, no double percent discounts. Although that might be requested someday) |
|
| 1366 | - $child_line_item->set_quantity(1); |
|
| 1367 | - $child_line_item->maybe_save(); |
|
| 1368 | - $calculated_total_so_far += $percent_total; |
|
| 1369 | - $unit_price_for_total += $percent_unit_price; |
|
| 1370 | - } else { |
|
| 1371 | - // verify flat sub-line-item quantities match their parent |
|
| 1372 | - if ($child_line_item->is_sub_line_item()) { |
|
| 1373 | - $child_line_item->set_quantity($this->quantity()); |
|
| 1374 | - } |
|
| 1375 | - $quantity_for_total = $child_line_item->quantity(); |
|
| 1376 | - $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1377 | - $unit_price_for_total += $child_line_item->unit_price(); |
|
| 1378 | - } |
|
| 1379 | - } |
|
| 1380 | - } |
|
| 1381 | - return $calculated_total_so_far; |
|
| 1382 | - } |
|
| 1383 | - |
|
| 1384 | - |
|
| 1385 | - /** |
|
| 1386 | - * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
| 1387 | - * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
| 1388 | - * and tax sub-total if already in the DB |
|
| 1389 | - * |
|
| 1390 | - * @return float |
|
| 1391 | - * @throws EE_Error |
|
| 1392 | - * @throws InvalidArgumentException |
|
| 1393 | - * @throws InvalidDataTypeException |
|
| 1394 | - * @throws InvalidInterfaceException |
|
| 1395 | - * @throws ReflectionException |
|
| 1396 | - */ |
|
| 1397 | - public function recalculate_taxes_and_tax_total() |
|
| 1398 | - { |
|
| 1399 | - // get all taxes |
|
| 1400 | - $taxes = $this->tax_descendants(); |
|
| 1401 | - // calculate the pretax total |
|
| 1402 | - $taxable_total = $this->taxable_total(); |
|
| 1403 | - $tax_total = 0; |
|
| 1404 | - foreach ($taxes as $tax) { |
|
| 1405 | - $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
| 1406 | - // remember the total on this line item |
|
| 1407 | - $tax->set_total($total_on_this_tax); |
|
| 1408 | - $tax->maybe_save(); |
|
| 1409 | - $tax_total += $tax->total(); |
|
| 1410 | - } |
|
| 1411 | - $this->_recalculate_tax_sub_total(); |
|
| 1412 | - return $tax_total; |
|
| 1413 | - } |
|
| 1414 | - |
|
| 1415 | - |
|
| 1416 | - /** |
|
| 1417 | - * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
| 1418 | - * |
|
| 1419 | - * @return void |
|
| 1420 | - * @throws EE_Error |
|
| 1421 | - * @throws InvalidArgumentException |
|
| 1422 | - * @throws InvalidDataTypeException |
|
| 1423 | - * @throws InvalidInterfaceException |
|
| 1424 | - * @throws ReflectionException |
|
| 1425 | - */ |
|
| 1426 | - private function _recalculate_tax_sub_total() |
|
| 1427 | - { |
|
| 1428 | - if ($this->is_tax_sub_total()) { |
|
| 1429 | - $total = 0; |
|
| 1430 | - $total_percent = 0; |
|
| 1431 | - // simply loop through all its children (which should be taxes) and sum their total |
|
| 1432 | - foreach ($this->children() as $child_tax) { |
|
| 1433 | - if ($child_tax instanceof EE_Line_Item) { |
|
| 1434 | - $total += $child_tax->total(); |
|
| 1435 | - $total_percent += $child_tax->percent(); |
|
| 1436 | - } |
|
| 1437 | - } |
|
| 1438 | - $this->set_total($total); |
|
| 1439 | - $this->set_percent($total_percent); |
|
| 1440 | - $this->maybe_save(); |
|
| 1441 | - } elseif ($this->is_total()) { |
|
| 1442 | - foreach ($this->children() as $maybe_tax_subtotal) { |
|
| 1443 | - if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
| 1444 | - $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
| 1445 | - } |
|
| 1446 | - } |
|
| 1447 | - } |
|
| 1448 | - } |
|
| 1449 | - |
|
| 1450 | - |
|
| 1451 | - /** |
|
| 1452 | - * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
| 1453 | - * recalculate_taxes_and_total |
|
| 1454 | - * |
|
| 1455 | - * @return float |
|
| 1456 | - * @throws EE_Error |
|
| 1457 | - * @throws InvalidArgumentException |
|
| 1458 | - * @throws InvalidDataTypeException |
|
| 1459 | - * @throws InvalidInterfaceException |
|
| 1460 | - * @throws ReflectionException |
|
| 1461 | - */ |
|
| 1462 | - public function get_total_tax() |
|
| 1463 | - { |
|
| 1464 | - $this->_recalculate_tax_sub_total(); |
|
| 1465 | - $total = 0; |
|
| 1466 | - foreach ($this->tax_descendants() as $tax_line_item) { |
|
| 1467 | - if ($tax_line_item instanceof EE_Line_Item) { |
|
| 1468 | - $total += $tax_line_item->total(); |
|
| 1469 | - } |
|
| 1470 | - } |
|
| 1471 | - return $total; |
|
| 1472 | - } |
|
| 1473 | - |
|
| 1474 | - |
|
| 1475 | - /** |
|
| 1476 | - * Gets the total for all the items purchased only |
|
| 1477 | - * |
|
| 1478 | - * @return float |
|
| 1479 | - * @throws EE_Error |
|
| 1480 | - * @throws InvalidArgumentException |
|
| 1481 | - * @throws InvalidDataTypeException |
|
| 1482 | - * @throws InvalidInterfaceException |
|
| 1483 | - * @throws ReflectionException |
|
| 1484 | - */ |
|
| 1485 | - public function get_items_total() |
|
| 1486 | - { |
|
| 1487 | - // by default, let's make sure we're consistent with the existing line item |
|
| 1488 | - if ($this->is_total()) { |
|
| 1489 | - $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
| 1490 | - if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
| 1491 | - return $pretax_subtotal_li->total(); |
|
| 1492 | - } |
|
| 1493 | - } |
|
| 1494 | - $total = 0; |
|
| 1495 | - foreach ($this->get_items() as $item) { |
|
| 1496 | - if ($item instanceof EE_Line_Item) { |
|
| 1497 | - $total += $item->total(); |
|
| 1498 | - } |
|
| 1499 | - } |
|
| 1500 | - return $total; |
|
| 1501 | - } |
|
| 1502 | - |
|
| 1503 | - |
|
| 1504 | - /** |
|
| 1505 | - * Gets all the descendants (ie, children or children of children etc) that |
|
| 1506 | - * are of the type 'tax' |
|
| 1507 | - * |
|
| 1508 | - * @return EE_Line_Item[] |
|
| 1509 | - * @throws EE_Error |
|
| 1510 | - */ |
|
| 1511 | - public function tax_descendants() |
|
| 1512 | - { |
|
| 1513 | - return EEH_Line_Item::get_tax_descendants($this); |
|
| 1514 | - } |
|
| 1515 | - |
|
| 1516 | - |
|
| 1517 | - /** |
|
| 1518 | - * Gets all the real items purchased which are children of this item |
|
| 1519 | - * |
|
| 1520 | - * @return EE_Line_Item[] |
|
| 1521 | - * @throws EE_Error |
|
| 1522 | - */ |
|
| 1523 | - public function get_items() |
|
| 1524 | - { |
|
| 1525 | - return EEH_Line_Item::get_line_item_descendants($this); |
|
| 1526 | - } |
|
| 1527 | - |
|
| 1528 | - |
|
| 1529 | - /** |
|
| 1530 | - * Returns the amount taxable among this line item's children (or if it has no children, |
|
| 1531 | - * how much of it is taxable). Does not recalculate totals or subtotals. |
|
| 1532 | - * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
| 1533 | - * but there is a "Taxable" discount), returns 0. |
|
| 1534 | - * |
|
| 1535 | - * @return float |
|
| 1536 | - * @throws EE_Error |
|
| 1537 | - * @throws InvalidArgumentException |
|
| 1538 | - * @throws InvalidDataTypeException |
|
| 1539 | - * @throws InvalidInterfaceException |
|
| 1540 | - * @throws ReflectionException |
|
| 1541 | - */ |
|
| 1542 | - public function taxable_total() |
|
| 1543 | - { |
|
| 1544 | - $total = 0; |
|
| 1545 | - if ($this->children()) { |
|
| 1546 | - foreach ($this->children() as $child_line_item) { |
|
| 1547 | - if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
| 1548 | - // if it's a percent item, only take into account the percent |
|
| 1549 | - // that's taxable too (the taxable total so far) |
|
| 1550 | - if ($child_line_item->is_percent()) { |
|
| 1551 | - $total += ($total * $child_line_item->percent() / 100); |
|
| 1552 | - } else { |
|
| 1553 | - $total += $child_line_item->total(); |
|
| 1554 | - } |
|
| 1555 | - } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
| 1556 | - $total += $child_line_item->taxable_total(); |
|
| 1557 | - } |
|
| 1558 | - } |
|
| 1559 | - } |
|
| 1560 | - return max($total, 0); |
|
| 1561 | - } |
|
| 1562 | - |
|
| 1563 | - |
|
| 1564 | - /** |
|
| 1565 | - * Gets the transaction for this line item |
|
| 1566 | - * |
|
| 1567 | - * @return EE_Base_Class|EE_Transaction |
|
| 1568 | - * @throws EE_Error |
|
| 1569 | - * @throws InvalidArgumentException |
|
| 1570 | - * @throws InvalidDataTypeException |
|
| 1571 | - * @throws InvalidInterfaceException |
|
| 1572 | - * @throws ReflectionException |
|
| 1573 | - */ |
|
| 1574 | - public function transaction() |
|
| 1575 | - { |
|
| 1576 | - return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION); |
|
| 1577 | - } |
|
| 1578 | - |
|
| 1579 | - |
|
| 1580 | - /** |
|
| 1581 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1582 | - * Because there currently is no proper parent-child relation on the model, |
|
| 1583 | - * save_this_and_cached() will NOT save the descendants. |
|
| 1584 | - * Also sets the transaction on this line item and all its descendants before saving |
|
| 1585 | - * |
|
| 1586 | - * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
| 1587 | - * @return int count of items saved |
|
| 1588 | - * @throws EE_Error |
|
| 1589 | - * @throws InvalidArgumentException |
|
| 1590 | - * @throws InvalidDataTypeException |
|
| 1591 | - * @throws InvalidInterfaceException |
|
| 1592 | - * @throws ReflectionException |
|
| 1593 | - */ |
|
| 1594 | - public function save_this_and_descendants_to_txn($txn_id = null) |
|
| 1595 | - { |
|
| 1596 | - $count = 0; |
|
| 1597 | - if (! $txn_id) { |
|
| 1598 | - $txn_id = $this->TXN_ID(); |
|
| 1599 | - } |
|
| 1600 | - $this->set_TXN_ID($txn_id); |
|
| 1601 | - $children = $this->children(); |
|
| 1602 | - $count += $this->save() |
|
| 1603 | - ? 1 |
|
| 1604 | - : 0; |
|
| 1605 | - foreach ($children as $child_line_item) { |
|
| 1606 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1607 | - $child_line_item->set_parent_ID($this->ID()); |
|
| 1608 | - $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
| 1609 | - } |
|
| 1610 | - } |
|
| 1611 | - return $count; |
|
| 1612 | - } |
|
| 1613 | - |
|
| 1614 | - |
|
| 1615 | - /** |
|
| 1616 | - * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1617 | - * |
|
| 1618 | - * @return int count of items saved |
|
| 1619 | - * @throws EE_Error |
|
| 1620 | - * @throws InvalidArgumentException |
|
| 1621 | - * @throws InvalidDataTypeException |
|
| 1622 | - * @throws InvalidInterfaceException |
|
| 1623 | - * @throws ReflectionException |
|
| 1624 | - */ |
|
| 1625 | - public function save_this_and_descendants() |
|
| 1626 | - { |
|
| 1627 | - $count = 0; |
|
| 1628 | - $children = $this->children(); |
|
| 1629 | - $count += $this->save() |
|
| 1630 | - ? 1 |
|
| 1631 | - : 0; |
|
| 1632 | - foreach ($children as $child_line_item) { |
|
| 1633 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1634 | - $child_line_item->set_parent_ID($this->ID()); |
|
| 1635 | - $count += $child_line_item->save_this_and_descendants(); |
|
| 1636 | - } |
|
| 1637 | - } |
|
| 1638 | - return $count; |
|
| 1639 | - } |
|
| 1640 | - |
|
| 1641 | - |
|
| 1642 | - /** |
|
| 1643 | - * returns the cancellation line item if this item was cancelled |
|
| 1644 | - * |
|
| 1645 | - * @return EE_Line_Item[] |
|
| 1646 | - * @throws InvalidArgumentException |
|
| 1647 | - * @throws InvalidInterfaceException |
|
| 1648 | - * @throws InvalidDataTypeException |
|
| 1649 | - * @throws ReflectionException |
|
| 1650 | - * @throws EE_Error |
|
| 1651 | - */ |
|
| 1652 | - public function get_cancellations() |
|
| 1653 | - { |
|
| 1654 | - EE_Registry::instance()->load_helper('Line_Item'); |
|
| 1655 | - return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
| 1656 | - } |
|
| 1657 | - |
|
| 1658 | - |
|
| 1659 | - /** |
|
| 1660 | - * If this item has an ID, then this saves it again to update the db |
|
| 1661 | - * |
|
| 1662 | - * @return int count of items saved |
|
| 1663 | - * @throws EE_Error |
|
| 1664 | - * @throws InvalidArgumentException |
|
| 1665 | - * @throws InvalidDataTypeException |
|
| 1666 | - * @throws InvalidInterfaceException |
|
| 1667 | - * @throws ReflectionException |
|
| 1668 | - */ |
|
| 1669 | - public function maybe_save() |
|
| 1670 | - { |
|
| 1671 | - if ($this->ID()) { |
|
| 1672 | - return $this->save(); |
|
| 1673 | - } |
|
| 1674 | - return false; |
|
| 1675 | - } |
|
| 1676 | - |
|
| 1677 | - |
|
| 1678 | - /** |
|
| 1679 | - * clears the cached children and parent from the line item |
|
| 1680 | - * |
|
| 1681 | - * @return void |
|
| 1682 | - */ |
|
| 1683 | - public function clear_related_line_item_cache() |
|
| 1684 | - { |
|
| 1685 | - $this->_children = array(); |
|
| 1686 | - $this->_parent = null; |
|
| 1687 | - } |
|
| 1688 | - |
|
| 1689 | - |
|
| 1690 | - /** |
|
| 1691 | - * @param bool $raw |
|
| 1692 | - * @return int |
|
| 1693 | - * @throws EE_Error |
|
| 1694 | - * @throws InvalidArgumentException |
|
| 1695 | - * @throws InvalidDataTypeException |
|
| 1696 | - * @throws InvalidInterfaceException |
|
| 1697 | - * @throws ReflectionException |
|
| 1698 | - */ |
|
| 1699 | - public function timestamp($raw = false) |
|
| 1700 | - { |
|
| 1701 | - return $raw |
|
| 1702 | - ? $this->get_raw('LIN_timestamp') |
|
| 1703 | - : $this->get('LIN_timestamp'); |
|
| 1704 | - } |
|
| 1705 | - |
|
| 1706 | - |
|
| 1707 | - |
|
| 1708 | - |
|
| 1709 | - /************************* DEPRECATED *************************/ |
|
| 1710 | - /** |
|
| 1711 | - * @deprecated 4.6.0 |
|
| 1712 | - * @param string $type one of the constants on EEM_Line_Item |
|
| 1713 | - * @return EE_Line_Item[] |
|
| 1714 | - * @throws EE_Error |
|
| 1715 | - */ |
|
| 1716 | - protected function _get_descendants_of_type($type) |
|
| 1717 | - { |
|
| 1718 | - EE_Error::doing_it_wrong( |
|
| 1719 | - 'EE_Line_Item::_get_descendants_of_type()', |
|
| 1720 | - sprintf( |
|
| 1721 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1722 | - 'EEH_Line_Item::get_descendants_of_type()' |
|
| 1723 | - ), |
|
| 1724 | - '4.6.0' |
|
| 1725 | - ); |
|
| 1726 | - return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
| 1727 | - } |
|
| 1728 | - |
|
| 1729 | - |
|
| 1730 | - /** |
|
| 1731 | - * @deprecated 4.6.0 |
|
| 1732 | - * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1733 | - * @return EE_Line_Item |
|
| 1734 | - * @throws EE_Error |
|
| 1735 | - * @throws InvalidArgumentException |
|
| 1736 | - * @throws InvalidDataTypeException |
|
| 1737 | - * @throws InvalidInterfaceException |
|
| 1738 | - * @throws ReflectionException |
|
| 1739 | - */ |
|
| 1740 | - public function get_nearest_descendant_of_type($type) |
|
| 1741 | - { |
|
| 1742 | - EE_Error::doing_it_wrong( |
|
| 1743 | - 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
| 1744 | - sprintf( |
|
| 1745 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1746 | - 'EEH_Line_Item::get_nearest_descendant_of_type()' |
|
| 1747 | - ), |
|
| 1748 | - '4.6.0' |
|
| 1749 | - ); |
|
| 1750 | - return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
| 1751 | - } |
|
| 17 | + /** |
|
| 18 | + * for children line items (currently not a normal relation) |
|
| 19 | + * |
|
| 20 | + * @type EE_Line_Item[] |
|
| 21 | + */ |
|
| 22 | + protected $_children = array(); |
|
| 23 | + |
|
| 24 | + /** |
|
| 25 | + * for the parent line item |
|
| 26 | + * |
|
| 27 | + * @var EE_Line_Item |
|
| 28 | + */ |
|
| 29 | + protected $_parent; |
|
| 30 | + |
|
| 31 | + |
|
| 32 | + /** |
|
| 33 | + * @param array $props_n_values incoming values |
|
| 34 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 35 | + * used.) |
|
| 36 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 37 | + * date_format and the second value is the time format |
|
| 38 | + * @return EE_Line_Item |
|
| 39 | + * @throws EE_Error |
|
| 40 | + * @throws InvalidArgumentException |
|
| 41 | + * @throws InvalidDataTypeException |
|
| 42 | + * @throws InvalidInterfaceException |
|
| 43 | + * @throws ReflectionException |
|
| 44 | + */ |
|
| 45 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
| 46 | + { |
|
| 47 | + $has_object = parent::_check_for_object( |
|
| 48 | + $props_n_values, |
|
| 49 | + __CLASS__, |
|
| 50 | + $timezone, |
|
| 51 | + $date_formats |
|
| 52 | + ); |
|
| 53 | + return $has_object |
|
| 54 | + ? $has_object |
|
| 55 | + : new self($props_n_values, false, $timezone); |
|
| 56 | + } |
|
| 57 | + |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * @param array $props_n_values incoming values from the database |
|
| 61 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 62 | + * the website will be used. |
|
| 63 | + * @return EE_Line_Item |
|
| 64 | + * @throws EE_Error |
|
| 65 | + * @throws InvalidArgumentException |
|
| 66 | + * @throws InvalidDataTypeException |
|
| 67 | + * @throws InvalidInterfaceException |
|
| 68 | + * @throws ReflectionException |
|
| 69 | + */ |
|
| 70 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
| 71 | + { |
|
| 72 | + return new self($props_n_values, true, $timezone); |
|
| 73 | + } |
|
| 74 | + |
|
| 75 | + |
|
| 76 | + /** |
|
| 77 | + * Adds some defaults if they're not specified |
|
| 78 | + * |
|
| 79 | + * @param array $fieldValues |
|
| 80 | + * @param bool $bydb |
|
| 81 | + * @param string $timezone |
|
| 82 | + * @throws EE_Error |
|
| 83 | + * @throws InvalidArgumentException |
|
| 84 | + * @throws InvalidDataTypeException |
|
| 85 | + * @throws InvalidInterfaceException |
|
| 86 | + * @throws ReflectionException |
|
| 87 | + */ |
|
| 88 | + protected function __construct($fieldValues = array(), $bydb = false, $timezone = '') |
|
| 89 | + { |
|
| 90 | + parent::__construct($fieldValues, $bydb, $timezone); |
|
| 91 | + if (! $this->get('LIN_code')) { |
|
| 92 | + $this->set_code($this->generate_code()); |
|
| 93 | + } |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + |
|
| 97 | + /** |
|
| 98 | + * Gets ID |
|
| 99 | + * |
|
| 100 | + * @return int |
|
| 101 | + * @throws EE_Error |
|
| 102 | + * @throws InvalidArgumentException |
|
| 103 | + * @throws InvalidDataTypeException |
|
| 104 | + * @throws InvalidInterfaceException |
|
| 105 | + * @throws ReflectionException |
|
| 106 | + */ |
|
| 107 | + public function ID() |
|
| 108 | + { |
|
| 109 | + return $this->get('LIN_ID'); |
|
| 110 | + } |
|
| 111 | + |
|
| 112 | + |
|
| 113 | + /** |
|
| 114 | + * Gets TXN_ID |
|
| 115 | + * |
|
| 116 | + * @return int |
|
| 117 | + * @throws EE_Error |
|
| 118 | + * @throws InvalidArgumentException |
|
| 119 | + * @throws InvalidDataTypeException |
|
| 120 | + * @throws InvalidInterfaceException |
|
| 121 | + * @throws ReflectionException |
|
| 122 | + */ |
|
| 123 | + public function TXN_ID() |
|
| 124 | + { |
|
| 125 | + return $this->get('TXN_ID'); |
|
| 126 | + } |
|
| 127 | + |
|
| 128 | + |
|
| 129 | + /** |
|
| 130 | + * Sets TXN_ID |
|
| 131 | + * |
|
| 132 | + * @param int $TXN_ID |
|
| 133 | + * @throws EE_Error |
|
| 134 | + * @throws InvalidArgumentException |
|
| 135 | + * @throws InvalidDataTypeException |
|
| 136 | + * @throws InvalidInterfaceException |
|
| 137 | + * @throws ReflectionException |
|
| 138 | + */ |
|
| 139 | + public function set_TXN_ID($TXN_ID) |
|
| 140 | + { |
|
| 141 | + $this->set('TXN_ID', $TXN_ID); |
|
| 142 | + } |
|
| 143 | + |
|
| 144 | + |
|
| 145 | + /** |
|
| 146 | + * Gets name |
|
| 147 | + * |
|
| 148 | + * @return string |
|
| 149 | + * @throws EE_Error |
|
| 150 | + * @throws InvalidArgumentException |
|
| 151 | + * @throws InvalidDataTypeException |
|
| 152 | + * @throws InvalidInterfaceException |
|
| 153 | + * @throws ReflectionException |
|
| 154 | + */ |
|
| 155 | + public function name() |
|
| 156 | + { |
|
| 157 | + $name = $this->get('LIN_name'); |
|
| 158 | + if (! $name) { |
|
| 159 | + $name = ucwords(str_replace('-', ' ', $this->type())); |
|
| 160 | + } |
|
| 161 | + return $name; |
|
| 162 | + } |
|
| 163 | + |
|
| 164 | + |
|
| 165 | + /** |
|
| 166 | + * Sets name |
|
| 167 | + * |
|
| 168 | + * @param string $name |
|
| 169 | + * @throws EE_Error |
|
| 170 | + * @throws InvalidArgumentException |
|
| 171 | + * @throws InvalidDataTypeException |
|
| 172 | + * @throws InvalidInterfaceException |
|
| 173 | + * @throws ReflectionException |
|
| 174 | + */ |
|
| 175 | + public function set_name($name) |
|
| 176 | + { |
|
| 177 | + $this->set('LIN_name', $name); |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + |
|
| 181 | + /** |
|
| 182 | + * Gets desc |
|
| 183 | + * |
|
| 184 | + * @return string |
|
| 185 | + * @throws EE_Error |
|
| 186 | + * @throws InvalidArgumentException |
|
| 187 | + * @throws InvalidDataTypeException |
|
| 188 | + * @throws InvalidInterfaceException |
|
| 189 | + * @throws ReflectionException |
|
| 190 | + */ |
|
| 191 | + public function desc() |
|
| 192 | + { |
|
| 193 | + return $this->get('LIN_desc'); |
|
| 194 | + } |
|
| 195 | + |
|
| 196 | + |
|
| 197 | + /** |
|
| 198 | + * Sets desc |
|
| 199 | + * |
|
| 200 | + * @param string $desc |
|
| 201 | + * @throws EE_Error |
|
| 202 | + * @throws InvalidArgumentException |
|
| 203 | + * @throws InvalidDataTypeException |
|
| 204 | + * @throws InvalidInterfaceException |
|
| 205 | + * @throws ReflectionException |
|
| 206 | + */ |
|
| 207 | + public function set_desc($desc) |
|
| 208 | + { |
|
| 209 | + $this->set('LIN_desc', $desc); |
|
| 210 | + } |
|
| 211 | + |
|
| 212 | + |
|
| 213 | + /** |
|
| 214 | + * Gets quantity |
|
| 215 | + * |
|
| 216 | + * @return int |
|
| 217 | + * @throws EE_Error |
|
| 218 | + * @throws InvalidArgumentException |
|
| 219 | + * @throws InvalidDataTypeException |
|
| 220 | + * @throws InvalidInterfaceException |
|
| 221 | + * @throws ReflectionException |
|
| 222 | + */ |
|
| 223 | + public function quantity() |
|
| 224 | + { |
|
| 225 | + return $this->get('LIN_quantity'); |
|
| 226 | + } |
|
| 227 | + |
|
| 228 | + |
|
| 229 | + /** |
|
| 230 | + * Sets quantity |
|
| 231 | + * |
|
| 232 | + * @param int $quantity |
|
| 233 | + * @throws EE_Error |
|
| 234 | + * @throws InvalidArgumentException |
|
| 235 | + * @throws InvalidDataTypeException |
|
| 236 | + * @throws InvalidInterfaceException |
|
| 237 | + * @throws ReflectionException |
|
| 238 | + */ |
|
| 239 | + public function set_quantity($quantity) |
|
| 240 | + { |
|
| 241 | + $this->set('LIN_quantity', max($quantity, 0)); |
|
| 242 | + } |
|
| 243 | + |
|
| 244 | + |
|
| 245 | + /** |
|
| 246 | + * Gets item_id |
|
| 247 | + * |
|
| 248 | + * @return string |
|
| 249 | + * @throws EE_Error |
|
| 250 | + * @throws InvalidArgumentException |
|
| 251 | + * @throws InvalidDataTypeException |
|
| 252 | + * @throws InvalidInterfaceException |
|
| 253 | + * @throws ReflectionException |
|
| 254 | + */ |
|
| 255 | + public function OBJ_ID() |
|
| 256 | + { |
|
| 257 | + return $this->get('OBJ_ID'); |
|
| 258 | + } |
|
| 259 | + |
|
| 260 | + |
|
| 261 | + /** |
|
| 262 | + * Sets item_id |
|
| 263 | + * |
|
| 264 | + * @param string $item_id |
|
| 265 | + * @throws EE_Error |
|
| 266 | + * @throws InvalidArgumentException |
|
| 267 | + * @throws InvalidDataTypeException |
|
| 268 | + * @throws InvalidInterfaceException |
|
| 269 | + * @throws ReflectionException |
|
| 270 | + */ |
|
| 271 | + public function set_OBJ_ID($item_id) |
|
| 272 | + { |
|
| 273 | + $this->set('OBJ_ID', $item_id); |
|
| 274 | + } |
|
| 275 | + |
|
| 276 | + |
|
| 277 | + /** |
|
| 278 | + * Gets item_type |
|
| 279 | + * |
|
| 280 | + * @return string |
|
| 281 | + * @throws EE_Error |
|
| 282 | + * @throws InvalidArgumentException |
|
| 283 | + * @throws InvalidDataTypeException |
|
| 284 | + * @throws InvalidInterfaceException |
|
| 285 | + * @throws ReflectionException |
|
| 286 | + */ |
|
| 287 | + public function OBJ_type() |
|
| 288 | + { |
|
| 289 | + return $this->get('OBJ_type'); |
|
| 290 | + } |
|
| 291 | + |
|
| 292 | + |
|
| 293 | + /** |
|
| 294 | + * Gets item_type |
|
| 295 | + * |
|
| 296 | + * @return string |
|
| 297 | + * @throws EE_Error |
|
| 298 | + * @throws InvalidArgumentException |
|
| 299 | + * @throws InvalidDataTypeException |
|
| 300 | + * @throws InvalidInterfaceException |
|
| 301 | + * @throws ReflectionException |
|
| 302 | + */ |
|
| 303 | + public function OBJ_type_i18n() |
|
| 304 | + { |
|
| 305 | + $obj_type = $this->OBJ_type(); |
|
| 306 | + switch ($obj_type) { |
|
| 307 | + case EEM_Line_Item::OBJ_TYPE_EVENT: |
|
| 308 | + $obj_type = esc_html__('Event', 'event_espresso'); |
|
| 309 | + break; |
|
| 310 | + case EEM_Line_Item::OBJ_TYPE_PRICE: |
|
| 311 | + $obj_type = esc_html__('Price', 'event_espresso'); |
|
| 312 | + break; |
|
| 313 | + case EEM_Line_Item::OBJ_TYPE_PROMOTION: |
|
| 314 | + $obj_type = esc_html__('Promotion', 'event_espresso'); |
|
| 315 | + break; |
|
| 316 | + case EEM_Line_Item::OBJ_TYPE_TICKET: |
|
| 317 | + $obj_type = esc_html__('Ticket', 'event_espresso'); |
|
| 318 | + break; |
|
| 319 | + case EEM_Line_Item::OBJ_TYPE_TRANSACTION: |
|
| 320 | + $obj_type = esc_html__('Transaction', 'event_espresso'); |
|
| 321 | + break; |
|
| 322 | + } |
|
| 323 | + return apply_filters('FHEE__EE_Line_Item__OBJ_type_i18n', $obj_type, $this); |
|
| 324 | + } |
|
| 325 | + |
|
| 326 | + |
|
| 327 | + /** |
|
| 328 | + * Sets item_type |
|
| 329 | + * |
|
| 330 | + * @param string $OBJ_type |
|
| 331 | + * @throws EE_Error |
|
| 332 | + * @throws InvalidArgumentException |
|
| 333 | + * @throws InvalidDataTypeException |
|
| 334 | + * @throws InvalidInterfaceException |
|
| 335 | + * @throws ReflectionException |
|
| 336 | + */ |
|
| 337 | + public function set_OBJ_type($OBJ_type) |
|
| 338 | + { |
|
| 339 | + $this->set('OBJ_type', $OBJ_type); |
|
| 340 | + } |
|
| 341 | + |
|
| 342 | + |
|
| 343 | + /** |
|
| 344 | + * Gets unit_price |
|
| 345 | + * |
|
| 346 | + * @return float |
|
| 347 | + * @throws EE_Error |
|
| 348 | + * @throws InvalidArgumentException |
|
| 349 | + * @throws InvalidDataTypeException |
|
| 350 | + * @throws InvalidInterfaceException |
|
| 351 | + * @throws ReflectionException |
|
| 352 | + */ |
|
| 353 | + public function unit_price() |
|
| 354 | + { |
|
| 355 | + return $this->get('LIN_unit_price'); |
|
| 356 | + } |
|
| 357 | + |
|
| 358 | + |
|
| 359 | + /** |
|
| 360 | + * Sets unit_price |
|
| 361 | + * |
|
| 362 | + * @param float $unit_price |
|
| 363 | + * @throws EE_Error |
|
| 364 | + * @throws InvalidArgumentException |
|
| 365 | + * @throws InvalidDataTypeException |
|
| 366 | + * @throws InvalidInterfaceException |
|
| 367 | + * @throws ReflectionException |
|
| 368 | + */ |
|
| 369 | + public function set_unit_price($unit_price) |
|
| 370 | + { |
|
| 371 | + $this->set('LIN_unit_price', $unit_price); |
|
| 372 | + } |
|
| 373 | + |
|
| 374 | + |
|
| 375 | + /** |
|
| 376 | + * Checks if this item is a percentage modifier or not |
|
| 377 | + * |
|
| 378 | + * @return boolean |
|
| 379 | + * @throws EE_Error |
|
| 380 | + * @throws InvalidArgumentException |
|
| 381 | + * @throws InvalidDataTypeException |
|
| 382 | + * @throws InvalidInterfaceException |
|
| 383 | + * @throws ReflectionException |
|
| 384 | + */ |
|
| 385 | + public function is_percent() |
|
| 386 | + { |
|
| 387 | + if ($this->is_tax_sub_total()) { |
|
| 388 | + // tax subtotals HAVE a percent on them, that percentage only applies |
|
| 389 | + // to taxable items, so its' an exception. Treat it like a flat line item |
|
| 390 | + return false; |
|
| 391 | + } |
|
| 392 | + $unit_price = abs($this->get('LIN_unit_price')); |
|
| 393 | + $percent = abs($this->get('LIN_percent')); |
|
| 394 | + if ($unit_price < .001 && $percent) { |
|
| 395 | + return true; |
|
| 396 | + } |
|
| 397 | + if ($unit_price >= .001 && ! $percent) { |
|
| 398 | + return false; |
|
| 399 | + } |
|
| 400 | + if ($unit_price >= .001 && $percent) { |
|
| 401 | + throw new EE_Error( |
|
| 402 | + sprintf( |
|
| 403 | + esc_html__( |
|
| 404 | + 'A Line Item can not have a unit price of (%s) AND a percent (%s)!', |
|
| 405 | + 'event_espresso' |
|
| 406 | + ), |
|
| 407 | + $unit_price, |
|
| 408 | + $percent |
|
| 409 | + ) |
|
| 410 | + ); |
|
| 411 | + } |
|
| 412 | + // if they're both 0, assume its not a percent item |
|
| 413 | + return false; |
|
| 414 | + } |
|
| 415 | + |
|
| 416 | + |
|
| 417 | + /** |
|
| 418 | + * Gets percent (between 100-.001) |
|
| 419 | + * |
|
| 420 | + * @return float |
|
| 421 | + * @throws EE_Error |
|
| 422 | + * @throws InvalidArgumentException |
|
| 423 | + * @throws InvalidDataTypeException |
|
| 424 | + * @throws InvalidInterfaceException |
|
| 425 | + * @throws ReflectionException |
|
| 426 | + */ |
|
| 427 | + public function percent() |
|
| 428 | + { |
|
| 429 | + return $this->get('LIN_percent'); |
|
| 430 | + } |
|
| 431 | + |
|
| 432 | + |
|
| 433 | + /** |
|
| 434 | + * Sets percent (between 100-0.01) |
|
| 435 | + * |
|
| 436 | + * @param float $percent |
|
| 437 | + * @throws EE_Error |
|
| 438 | + * @throws InvalidArgumentException |
|
| 439 | + * @throws InvalidDataTypeException |
|
| 440 | + * @throws InvalidInterfaceException |
|
| 441 | + * @throws ReflectionException |
|
| 442 | + */ |
|
| 443 | + public function set_percent($percent) |
|
| 444 | + { |
|
| 445 | + $this->set('LIN_percent', $percent); |
|
| 446 | + } |
|
| 447 | + |
|
| 448 | + |
|
| 449 | + /** |
|
| 450 | + * Gets total |
|
| 451 | + * |
|
| 452 | + * @return float |
|
| 453 | + * @throws EE_Error |
|
| 454 | + * @throws InvalidArgumentException |
|
| 455 | + * @throws InvalidDataTypeException |
|
| 456 | + * @throws InvalidInterfaceException |
|
| 457 | + * @throws ReflectionException |
|
| 458 | + */ |
|
| 459 | + public function total() |
|
| 460 | + { |
|
| 461 | + return $this->get('LIN_total'); |
|
| 462 | + } |
|
| 463 | + |
|
| 464 | + |
|
| 465 | + /** |
|
| 466 | + * Sets total |
|
| 467 | + * |
|
| 468 | + * @param float $total |
|
| 469 | + * @throws EE_Error |
|
| 470 | + * @throws InvalidArgumentException |
|
| 471 | + * @throws InvalidDataTypeException |
|
| 472 | + * @throws InvalidInterfaceException |
|
| 473 | + * @throws ReflectionException |
|
| 474 | + */ |
|
| 475 | + public function set_total($total) |
|
| 476 | + { |
|
| 477 | + $this->set('LIN_total', $total); |
|
| 478 | + } |
|
| 479 | + |
|
| 480 | + |
|
| 481 | + /** |
|
| 482 | + * Gets order |
|
| 483 | + * |
|
| 484 | + * @return int |
|
| 485 | + * @throws EE_Error |
|
| 486 | + * @throws InvalidArgumentException |
|
| 487 | + * @throws InvalidDataTypeException |
|
| 488 | + * @throws InvalidInterfaceException |
|
| 489 | + * @throws ReflectionException |
|
| 490 | + */ |
|
| 491 | + public function order() |
|
| 492 | + { |
|
| 493 | + return $this->get('LIN_order'); |
|
| 494 | + } |
|
| 495 | + |
|
| 496 | + |
|
| 497 | + /** |
|
| 498 | + * Sets order |
|
| 499 | + * |
|
| 500 | + * @param int $order |
|
| 501 | + * @throws EE_Error |
|
| 502 | + * @throws InvalidArgumentException |
|
| 503 | + * @throws InvalidDataTypeException |
|
| 504 | + * @throws InvalidInterfaceException |
|
| 505 | + * @throws ReflectionException |
|
| 506 | + */ |
|
| 507 | + public function set_order($order) |
|
| 508 | + { |
|
| 509 | + $this->set('LIN_order', $order); |
|
| 510 | + } |
|
| 511 | + |
|
| 512 | + |
|
| 513 | + /** |
|
| 514 | + * Gets parent |
|
| 515 | + * |
|
| 516 | + * @return int |
|
| 517 | + * @throws EE_Error |
|
| 518 | + * @throws InvalidArgumentException |
|
| 519 | + * @throws InvalidDataTypeException |
|
| 520 | + * @throws InvalidInterfaceException |
|
| 521 | + * @throws ReflectionException |
|
| 522 | + */ |
|
| 523 | + public function parent_ID() |
|
| 524 | + { |
|
| 525 | + return $this->get('LIN_parent'); |
|
| 526 | + } |
|
| 527 | + |
|
| 528 | + |
|
| 529 | + /** |
|
| 530 | + * Sets parent |
|
| 531 | + * |
|
| 532 | + * @param int $parent |
|
| 533 | + * @throws EE_Error |
|
| 534 | + * @throws InvalidArgumentException |
|
| 535 | + * @throws InvalidDataTypeException |
|
| 536 | + * @throws InvalidInterfaceException |
|
| 537 | + * @throws ReflectionException |
|
| 538 | + */ |
|
| 539 | + public function set_parent_ID($parent) |
|
| 540 | + { |
|
| 541 | + $this->set('LIN_parent', $parent); |
|
| 542 | + } |
|
| 543 | + |
|
| 544 | + |
|
| 545 | + /** |
|
| 546 | + * Gets type |
|
| 547 | + * |
|
| 548 | + * @return string |
|
| 549 | + * @throws EE_Error |
|
| 550 | + * @throws InvalidArgumentException |
|
| 551 | + * @throws InvalidDataTypeException |
|
| 552 | + * @throws InvalidInterfaceException |
|
| 553 | + * @throws ReflectionException |
|
| 554 | + */ |
|
| 555 | + public function type() |
|
| 556 | + { |
|
| 557 | + return $this->get('LIN_type'); |
|
| 558 | + } |
|
| 559 | + |
|
| 560 | + |
|
| 561 | + /** |
|
| 562 | + * Sets type |
|
| 563 | + * |
|
| 564 | + * @param string $type |
|
| 565 | + * @throws EE_Error |
|
| 566 | + * @throws InvalidArgumentException |
|
| 567 | + * @throws InvalidDataTypeException |
|
| 568 | + * @throws InvalidInterfaceException |
|
| 569 | + * @throws ReflectionException |
|
| 570 | + */ |
|
| 571 | + public function set_type($type) |
|
| 572 | + { |
|
| 573 | + $this->set('LIN_type', $type); |
|
| 574 | + } |
|
| 575 | + |
|
| 576 | + |
|
| 577 | + /** |
|
| 578 | + * Gets the line item of which this item is a composite. Eg, if this is a subtotal, the parent might be a total\ |
|
| 579 | + * 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 |
|
| 580 | + * it uses its cached reference to its parent line item (which would have been set by `EE_Line_Item::set_parent()` |
|
| 581 | + * or indirectly by `EE_Line_item::add_child_line_item()`) |
|
| 582 | + * |
|
| 583 | + * @return EE_Base_Class|EE_Line_Item |
|
| 584 | + * @throws EE_Error |
|
| 585 | + * @throws InvalidArgumentException |
|
| 586 | + * @throws InvalidDataTypeException |
|
| 587 | + * @throws InvalidInterfaceException |
|
| 588 | + * @throws ReflectionException |
|
| 589 | + */ |
|
| 590 | + public function parent() |
|
| 591 | + { |
|
| 592 | + return $this->ID() |
|
| 593 | + ? $this->get_model()->get_one_by_ID($this->parent_ID()) |
|
| 594 | + : $this->_parent; |
|
| 595 | + } |
|
| 596 | + |
|
| 597 | + |
|
| 598 | + /** |
|
| 599 | + * Gets ALL the children of this line item (ie, all the parts that contribute towards this total). |
|
| 600 | + * |
|
| 601 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 602 | + * @throws EE_Error |
|
| 603 | + * @throws InvalidArgumentException |
|
| 604 | + * @throws InvalidDataTypeException |
|
| 605 | + * @throws InvalidInterfaceException |
|
| 606 | + * @throws ReflectionException |
|
| 607 | + */ |
|
| 608 | + public function children() |
|
| 609 | + { |
|
| 610 | + if ($this->ID()) { |
|
| 611 | + return $this->get_model()->get_all( |
|
| 612 | + array( |
|
| 613 | + array('LIN_parent' => $this->ID()), |
|
| 614 | + 'order_by' => array('LIN_order' => 'ASC'), |
|
| 615 | + ) |
|
| 616 | + ); |
|
| 617 | + } |
|
| 618 | + if (! is_array($this->_children)) { |
|
| 619 | + $this->_children = array(); |
|
| 620 | + } |
|
| 621 | + return $this->_children; |
|
| 622 | + } |
|
| 623 | + |
|
| 624 | + |
|
| 625 | + /** |
|
| 626 | + * Gets code |
|
| 627 | + * |
|
| 628 | + * @return string |
|
| 629 | + * @throws EE_Error |
|
| 630 | + * @throws InvalidArgumentException |
|
| 631 | + * @throws InvalidDataTypeException |
|
| 632 | + * @throws InvalidInterfaceException |
|
| 633 | + * @throws ReflectionException |
|
| 634 | + */ |
|
| 635 | + public function code() |
|
| 636 | + { |
|
| 637 | + return $this->get('LIN_code'); |
|
| 638 | + } |
|
| 639 | + |
|
| 640 | + |
|
| 641 | + /** |
|
| 642 | + * Sets code |
|
| 643 | + * |
|
| 644 | + * @param string $code |
|
| 645 | + * @throws EE_Error |
|
| 646 | + * @throws InvalidArgumentException |
|
| 647 | + * @throws InvalidDataTypeException |
|
| 648 | + * @throws InvalidInterfaceException |
|
| 649 | + * @throws ReflectionException |
|
| 650 | + */ |
|
| 651 | + public function set_code($code) |
|
| 652 | + { |
|
| 653 | + $this->set('LIN_code', $code); |
|
| 654 | + } |
|
| 655 | + |
|
| 656 | + |
|
| 657 | + /** |
|
| 658 | + * Gets is_taxable |
|
| 659 | + * |
|
| 660 | + * @return boolean |
|
| 661 | + * @throws EE_Error |
|
| 662 | + * @throws InvalidArgumentException |
|
| 663 | + * @throws InvalidDataTypeException |
|
| 664 | + * @throws InvalidInterfaceException |
|
| 665 | + * @throws ReflectionException |
|
| 666 | + */ |
|
| 667 | + public function is_taxable() |
|
| 668 | + { |
|
| 669 | + return $this->get('LIN_is_taxable'); |
|
| 670 | + } |
|
| 671 | + |
|
| 672 | + |
|
| 673 | + /** |
|
| 674 | + * Sets is_taxable |
|
| 675 | + * |
|
| 676 | + * @param boolean $is_taxable |
|
| 677 | + * @throws EE_Error |
|
| 678 | + * @throws InvalidArgumentException |
|
| 679 | + * @throws InvalidDataTypeException |
|
| 680 | + * @throws InvalidInterfaceException |
|
| 681 | + * @throws ReflectionException |
|
| 682 | + */ |
|
| 683 | + public function set_is_taxable($is_taxable) |
|
| 684 | + { |
|
| 685 | + $this->set('LIN_is_taxable', $is_taxable); |
|
| 686 | + } |
|
| 687 | + |
|
| 688 | + |
|
| 689 | + /** |
|
| 690 | + * Gets the object that this model-joins-to. |
|
| 691 | + * returns one of the model objects that the field OBJ_ID can point to... see the 'OBJ_ID' field on |
|
| 692 | + * EEM_Promotion_Object |
|
| 693 | + * Eg, if this line item join model object is for a ticket, this will return the EE_Ticket object |
|
| 694 | + * |
|
| 695 | + * @return EE_Base_Class | NULL |
|
| 696 | + * @throws EE_Error |
|
| 697 | + * @throws InvalidArgumentException |
|
| 698 | + * @throws InvalidDataTypeException |
|
| 699 | + * @throws InvalidInterfaceException |
|
| 700 | + * @throws ReflectionException |
|
| 701 | + */ |
|
| 702 | + public function get_object() |
|
| 703 | + { |
|
| 704 | + $model_name_of_related_obj = $this->OBJ_type(); |
|
| 705 | + return $this->get_model()->has_relation($model_name_of_related_obj) |
|
| 706 | + ? $this->get_first_related($model_name_of_related_obj) |
|
| 707 | + : null; |
|
| 708 | + } |
|
| 709 | + |
|
| 710 | + |
|
| 711 | + /** |
|
| 712 | + * Like EE_Line_Item::get_object(), but can only ever actually return an EE_Ticket. |
|
| 713 | + * (IE, if this line item is for a price or something else, will return NULL) |
|
| 714 | + * |
|
| 715 | + * @param array $query_params |
|
| 716 | + * @return EE_Base_Class|EE_Ticket |
|
| 717 | + * @throws EE_Error |
|
| 718 | + * @throws InvalidArgumentException |
|
| 719 | + * @throws InvalidDataTypeException |
|
| 720 | + * @throws InvalidInterfaceException |
|
| 721 | + * @throws ReflectionException |
|
| 722 | + */ |
|
| 723 | + public function ticket($query_params = array()) |
|
| 724 | + { |
|
| 725 | + // we're going to assume that when this method is called |
|
| 726 | + // we always want to receive the attached ticket EVEN if that ticket is archived. |
|
| 727 | + // This can be overridden via the incoming $query_params argument |
|
| 728 | + $remove_defaults = array('default_where_conditions' => 'none'); |
|
| 729 | + $query_params = array_merge($remove_defaults, $query_params); |
|
| 730 | + return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TICKET, $query_params); |
|
| 731 | + } |
|
| 732 | + |
|
| 733 | + |
|
| 734 | + /** |
|
| 735 | + * Gets the EE_Datetime that's related to the ticket, IF this is for a ticket |
|
| 736 | + * |
|
| 737 | + * @return EE_Datetime | NULL |
|
| 738 | + * @throws EE_Error |
|
| 739 | + * @throws InvalidArgumentException |
|
| 740 | + * @throws InvalidDataTypeException |
|
| 741 | + * @throws InvalidInterfaceException |
|
| 742 | + * @throws ReflectionException |
|
| 743 | + */ |
|
| 744 | + public function get_ticket_datetime() |
|
| 745 | + { |
|
| 746 | + if ($this->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 747 | + $ticket = $this->ticket(); |
|
| 748 | + if ($ticket instanceof EE_Ticket) { |
|
| 749 | + $datetime = $ticket->first_datetime(); |
|
| 750 | + if ($datetime instanceof EE_Datetime) { |
|
| 751 | + return $datetime; |
|
| 752 | + } |
|
| 753 | + } |
|
| 754 | + } |
|
| 755 | + return null; |
|
| 756 | + } |
|
| 757 | + |
|
| 758 | + |
|
| 759 | + /** |
|
| 760 | + * Gets the event's name that's related to the ticket, if this is for |
|
| 761 | + * a ticket |
|
| 762 | + * |
|
| 763 | + * @return string |
|
| 764 | + * @throws EE_Error |
|
| 765 | + * @throws InvalidArgumentException |
|
| 766 | + * @throws InvalidDataTypeException |
|
| 767 | + * @throws InvalidInterfaceException |
|
| 768 | + * @throws ReflectionException |
|
| 769 | + */ |
|
| 770 | + public function ticket_event_name() |
|
| 771 | + { |
|
| 772 | + $event_name = esc_html__('Unknown', 'event_espresso'); |
|
| 773 | + $event = $this->ticket_event(); |
|
| 774 | + if ($event instanceof EE_Event) { |
|
| 775 | + $event_name = $event->name(); |
|
| 776 | + } |
|
| 777 | + return $event_name; |
|
| 778 | + } |
|
| 779 | + |
|
| 780 | + |
|
| 781 | + /** |
|
| 782 | + * Gets the event that's related to the ticket, if this line item represents a ticket. |
|
| 783 | + * |
|
| 784 | + * @return EE_Event|null |
|
| 785 | + * @throws EE_Error |
|
| 786 | + * @throws InvalidArgumentException |
|
| 787 | + * @throws InvalidDataTypeException |
|
| 788 | + * @throws InvalidInterfaceException |
|
| 789 | + * @throws ReflectionException |
|
| 790 | + */ |
|
| 791 | + public function ticket_event() |
|
| 792 | + { |
|
| 793 | + $event = null; |
|
| 794 | + $ticket = $this->ticket(); |
|
| 795 | + if ($ticket instanceof EE_Ticket) { |
|
| 796 | + $datetime = $ticket->first_datetime(); |
|
| 797 | + if ($datetime instanceof EE_Datetime) { |
|
| 798 | + $event = $datetime->event(); |
|
| 799 | + } |
|
| 800 | + } |
|
| 801 | + return $event; |
|
| 802 | + } |
|
| 803 | + |
|
| 804 | + |
|
| 805 | + /** |
|
| 806 | + * Gets the first datetime for this lien item, assuming it's for a ticket |
|
| 807 | + * |
|
| 808 | + * @param string $date_format |
|
| 809 | + * @param string $time_format |
|
| 810 | + * @return string |
|
| 811 | + * @throws EE_Error |
|
| 812 | + * @throws InvalidArgumentException |
|
| 813 | + * @throws InvalidDataTypeException |
|
| 814 | + * @throws InvalidInterfaceException |
|
| 815 | + * @throws ReflectionException |
|
| 816 | + */ |
|
| 817 | + public function ticket_datetime_start($date_format = '', $time_format = '') |
|
| 818 | + { |
|
| 819 | + $first_datetime_string = esc_html__('Unknown', 'event_espresso'); |
|
| 820 | + $datetime = $this->get_ticket_datetime(); |
|
| 821 | + if ($datetime) { |
|
| 822 | + $first_datetime_string = $datetime->start_date_and_time($date_format, $time_format); |
|
| 823 | + } |
|
| 824 | + return $first_datetime_string; |
|
| 825 | + } |
|
| 826 | + |
|
| 827 | + |
|
| 828 | + /** |
|
| 829 | + * Adds the line item as a child to this line item. If there is another child line |
|
| 830 | + * item with the same LIN_code, it is overwritten by this new one |
|
| 831 | + * |
|
| 832 | + * @param EEI_Line_Item $line_item |
|
| 833 | + * @param bool $set_order |
|
| 834 | + * @return bool success |
|
| 835 | + * @throws EE_Error |
|
| 836 | + * @throws InvalidArgumentException |
|
| 837 | + * @throws InvalidDataTypeException |
|
| 838 | + * @throws InvalidInterfaceException |
|
| 839 | + * @throws ReflectionException |
|
| 840 | + */ |
|
| 841 | + public function add_child_line_item(EEI_Line_Item $line_item, $set_order = true) |
|
| 842 | + { |
|
| 843 | + // should we calculate the LIN_order for this line item ? |
|
| 844 | + if ($set_order || $line_item->order() === null) { |
|
| 845 | + $line_item->set_order(count($this->children())); |
|
| 846 | + } |
|
| 847 | + if ($this->ID()) { |
|
| 848 | + // check for any duplicate line items (with the same code), if so, this replaces it |
|
| 849 | + $line_item_with_same_code = $this->get_child_line_item($line_item->code()); |
|
| 850 | + if ($line_item_with_same_code instanceof EE_Line_Item && $line_item_with_same_code !== $line_item) { |
|
| 851 | + $this->delete_child_line_item($line_item_with_same_code->code()); |
|
| 852 | + } |
|
| 853 | + $line_item->set_parent_ID($this->ID()); |
|
| 854 | + if ($this->TXN_ID()) { |
|
| 855 | + $line_item->set_TXN_ID($this->TXN_ID()); |
|
| 856 | + } |
|
| 857 | + return $line_item->save(); |
|
| 858 | + } |
|
| 859 | + $this->_children[ $line_item->code() ] = $line_item; |
|
| 860 | + if ($line_item->parent() !== $this) { |
|
| 861 | + $line_item->set_parent($this); |
|
| 862 | + } |
|
| 863 | + return true; |
|
| 864 | + } |
|
| 865 | + |
|
| 866 | + |
|
| 867 | + /** |
|
| 868 | + * Similar to EE_Base_Class::_add_relation_to, except this isn't a normal relation. |
|
| 869 | + * If this line item is saved to the DB, this is just a wrapper for set_parent_ID() and save() |
|
| 870 | + * However, if this line item is NOT saved to the DB, this just caches the parent on |
|
| 871 | + * the EE_Line_Item::_parent property. |
|
| 872 | + * |
|
| 873 | + * @param EE_Line_Item $line_item |
|
| 874 | + * @throws EE_Error |
|
| 875 | + * @throws InvalidArgumentException |
|
| 876 | + * @throws InvalidDataTypeException |
|
| 877 | + * @throws InvalidInterfaceException |
|
| 878 | + * @throws ReflectionException |
|
| 879 | + */ |
|
| 880 | + public function set_parent($line_item) |
|
| 881 | + { |
|
| 882 | + if ($this->ID()) { |
|
| 883 | + if (! $line_item->ID()) { |
|
| 884 | + $line_item->save(); |
|
| 885 | + } |
|
| 886 | + $this->set_parent_ID($line_item->ID()); |
|
| 887 | + $this->save(); |
|
| 888 | + } else { |
|
| 889 | + $this->_parent = $line_item; |
|
| 890 | + $this->set_parent_ID($line_item->ID()); |
|
| 891 | + } |
|
| 892 | + } |
|
| 893 | + |
|
| 894 | + |
|
| 895 | + /** |
|
| 896 | + * Gets the child line item as specified by its code. Because this returns an object (by reference) |
|
| 897 | + * you can modify this child line item and the parent (this object) can know about them |
|
| 898 | + * because it also has a reference to that line item |
|
| 899 | + * |
|
| 900 | + * @param string $code |
|
| 901 | + * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 902 | + * @throws EE_Error |
|
| 903 | + * @throws InvalidArgumentException |
|
| 904 | + * @throws InvalidDataTypeException |
|
| 905 | + * @throws InvalidInterfaceException |
|
| 906 | + * @throws ReflectionException |
|
| 907 | + */ |
|
| 908 | + public function get_child_line_item($code) |
|
| 909 | + { |
|
| 910 | + if ($this->ID()) { |
|
| 911 | + return $this->get_model()->get_one( |
|
| 912 | + array(array('LIN_parent' => $this->ID(), 'LIN_code' => $code)) |
|
| 913 | + ); |
|
| 914 | + } |
|
| 915 | + return isset($this->_children[ $code ]) |
|
| 916 | + ? $this->_children[ $code ] |
|
| 917 | + : null; |
|
| 918 | + } |
|
| 919 | + |
|
| 920 | + |
|
| 921 | + /** |
|
| 922 | + * Returns how many items are deleted (or, if this item has not been saved ot the DB yet, just how many it HAD |
|
| 923 | + * cached on it) |
|
| 924 | + * |
|
| 925 | + * @return int |
|
| 926 | + * @throws EE_Error |
|
| 927 | + * @throws InvalidArgumentException |
|
| 928 | + * @throws InvalidDataTypeException |
|
| 929 | + * @throws InvalidInterfaceException |
|
| 930 | + * @throws ReflectionException |
|
| 931 | + */ |
|
| 932 | + public function delete_children_line_items() |
|
| 933 | + { |
|
| 934 | + if ($this->ID()) { |
|
| 935 | + return $this->get_model()->delete(array(array('LIN_parent' => $this->ID()))); |
|
| 936 | + } |
|
| 937 | + $count = count($this->_children); |
|
| 938 | + $this->_children = array(); |
|
| 939 | + return $count; |
|
| 940 | + } |
|
| 941 | + |
|
| 942 | + |
|
| 943 | + /** |
|
| 944 | + * If this line item has been saved to the DB, deletes its child with LIN_code == $code. If this line |
|
| 945 | + * HAS NOT been saved to the DB, removes the child line item with index $code. |
|
| 946 | + * Also searches through the child's children for a matching line item. However, once a line item has been found |
|
| 947 | + * and deleted, stops searching (so if there are line items with duplicate codes, only the first one found will be |
|
| 948 | + * deleted) |
|
| 949 | + * |
|
| 950 | + * @param string $code |
|
| 951 | + * @param bool $stop_search_once_found |
|
| 952 | + * @return int count of items deleted (or simply removed from the line item's cache, if not has not been saved to |
|
| 953 | + * the DB yet) |
|
| 954 | + * @throws EE_Error |
|
| 955 | + * @throws InvalidArgumentException |
|
| 956 | + * @throws InvalidDataTypeException |
|
| 957 | + * @throws InvalidInterfaceException |
|
| 958 | + * @throws ReflectionException |
|
| 959 | + */ |
|
| 960 | + public function delete_child_line_item($code, $stop_search_once_found = true) |
|
| 961 | + { |
|
| 962 | + if ($this->ID()) { |
|
| 963 | + $items_deleted = 0; |
|
| 964 | + if ($this->code() === $code) { |
|
| 965 | + $items_deleted += EEH_Line_Item::delete_all_child_items($this); |
|
| 966 | + $items_deleted += (int) $this->delete(); |
|
| 967 | + if ($stop_search_once_found) { |
|
| 968 | + return $items_deleted; |
|
| 969 | + } |
|
| 970 | + } |
|
| 971 | + foreach ($this->children() as $child_line_item) { |
|
| 972 | + $items_deleted += $child_line_item->delete_child_line_item($code, $stop_search_once_found); |
|
| 973 | + } |
|
| 974 | + return $items_deleted; |
|
| 975 | + } |
|
| 976 | + if (isset($this->_children[ $code ])) { |
|
| 977 | + unset($this->_children[ $code ]); |
|
| 978 | + return 1; |
|
| 979 | + } |
|
| 980 | + return 0; |
|
| 981 | + } |
|
| 982 | + |
|
| 983 | + |
|
| 984 | + /** |
|
| 985 | + * If this line item is in the database, is of the type subtotal, and |
|
| 986 | + * has no children, why do we have it? It should be deleted so this function |
|
| 987 | + * does that |
|
| 988 | + * |
|
| 989 | + * @return boolean |
|
| 990 | + * @throws EE_Error |
|
| 991 | + * @throws InvalidArgumentException |
|
| 992 | + * @throws InvalidDataTypeException |
|
| 993 | + * @throws InvalidInterfaceException |
|
| 994 | + * @throws ReflectionException |
|
| 995 | + */ |
|
| 996 | + public function delete_if_childless_subtotal() |
|
| 997 | + { |
|
| 998 | + if ($this->ID() && $this->type() === EEM_Line_Item::type_sub_total && ! $this->children()) { |
|
| 999 | + return $this->delete(); |
|
| 1000 | + } |
|
| 1001 | + return false; |
|
| 1002 | + } |
|
| 1003 | + |
|
| 1004 | + |
|
| 1005 | + /** |
|
| 1006 | + * Creates a code and returns a string. doesn't assign the code to this model object |
|
| 1007 | + * |
|
| 1008 | + * @return string |
|
| 1009 | + * @throws EE_Error |
|
| 1010 | + * @throws InvalidArgumentException |
|
| 1011 | + * @throws InvalidDataTypeException |
|
| 1012 | + * @throws InvalidInterfaceException |
|
| 1013 | + * @throws ReflectionException |
|
| 1014 | + */ |
|
| 1015 | + public function generate_code() |
|
| 1016 | + { |
|
| 1017 | + // each line item in the cart requires a unique identifier |
|
| 1018 | + return md5($this->get('OBJ_type') . $this->get('OBJ_ID') . microtime()); |
|
| 1019 | + } |
|
| 1020 | + |
|
| 1021 | + |
|
| 1022 | + /** |
|
| 1023 | + * @return bool |
|
| 1024 | + * @throws EE_Error |
|
| 1025 | + * @throws InvalidArgumentException |
|
| 1026 | + * @throws InvalidDataTypeException |
|
| 1027 | + * @throws InvalidInterfaceException |
|
| 1028 | + * @throws ReflectionException |
|
| 1029 | + */ |
|
| 1030 | + public function is_tax() |
|
| 1031 | + { |
|
| 1032 | + return $this->type() === EEM_Line_Item::type_tax; |
|
| 1033 | + } |
|
| 1034 | + |
|
| 1035 | + |
|
| 1036 | + /** |
|
| 1037 | + * @return bool |
|
| 1038 | + * @throws EE_Error |
|
| 1039 | + * @throws InvalidArgumentException |
|
| 1040 | + * @throws InvalidDataTypeException |
|
| 1041 | + * @throws InvalidInterfaceException |
|
| 1042 | + * @throws ReflectionException |
|
| 1043 | + */ |
|
| 1044 | + public function is_tax_sub_total() |
|
| 1045 | + { |
|
| 1046 | + return $this->type() === EEM_Line_Item::type_tax_sub_total; |
|
| 1047 | + } |
|
| 1048 | + |
|
| 1049 | + |
|
| 1050 | + /** |
|
| 1051 | + * @return bool |
|
| 1052 | + * @throws EE_Error |
|
| 1053 | + * @throws InvalidArgumentException |
|
| 1054 | + * @throws InvalidDataTypeException |
|
| 1055 | + * @throws InvalidInterfaceException |
|
| 1056 | + * @throws ReflectionException |
|
| 1057 | + */ |
|
| 1058 | + public function is_line_item() |
|
| 1059 | + { |
|
| 1060 | + return $this->type() === EEM_Line_Item::type_line_item; |
|
| 1061 | + } |
|
| 1062 | + |
|
| 1063 | + |
|
| 1064 | + /** |
|
| 1065 | + * @return bool |
|
| 1066 | + * @throws EE_Error |
|
| 1067 | + * @throws InvalidArgumentException |
|
| 1068 | + * @throws InvalidDataTypeException |
|
| 1069 | + * @throws InvalidInterfaceException |
|
| 1070 | + * @throws ReflectionException |
|
| 1071 | + */ |
|
| 1072 | + public function is_sub_line_item() |
|
| 1073 | + { |
|
| 1074 | + return $this->type() === EEM_Line_Item::type_sub_line_item; |
|
| 1075 | + } |
|
| 1076 | + |
|
| 1077 | + |
|
| 1078 | + /** |
|
| 1079 | + * @return bool |
|
| 1080 | + * @throws EE_Error |
|
| 1081 | + * @throws InvalidArgumentException |
|
| 1082 | + * @throws InvalidDataTypeException |
|
| 1083 | + * @throws InvalidInterfaceException |
|
| 1084 | + * @throws ReflectionException |
|
| 1085 | + */ |
|
| 1086 | + public function is_sub_total() |
|
| 1087 | + { |
|
| 1088 | + return $this->type() === EEM_Line_Item::type_sub_total; |
|
| 1089 | + } |
|
| 1090 | + |
|
| 1091 | + |
|
| 1092 | + /** |
|
| 1093 | + * Whether or not this line item is a cancellation line item |
|
| 1094 | + * |
|
| 1095 | + * @return boolean |
|
| 1096 | + * @throws EE_Error |
|
| 1097 | + * @throws InvalidArgumentException |
|
| 1098 | + * @throws InvalidDataTypeException |
|
| 1099 | + * @throws InvalidInterfaceException |
|
| 1100 | + * @throws ReflectionException |
|
| 1101 | + */ |
|
| 1102 | + public function is_cancellation() |
|
| 1103 | + { |
|
| 1104 | + return EEM_Line_Item::type_cancellation === $this->type(); |
|
| 1105 | + } |
|
| 1106 | + |
|
| 1107 | + |
|
| 1108 | + /** |
|
| 1109 | + * @return bool |
|
| 1110 | + * @throws EE_Error |
|
| 1111 | + * @throws InvalidArgumentException |
|
| 1112 | + * @throws InvalidDataTypeException |
|
| 1113 | + * @throws InvalidInterfaceException |
|
| 1114 | + * @throws ReflectionException |
|
| 1115 | + */ |
|
| 1116 | + public function is_total() |
|
| 1117 | + { |
|
| 1118 | + return $this->type() === EEM_Line_Item::type_total; |
|
| 1119 | + } |
|
| 1120 | + |
|
| 1121 | + |
|
| 1122 | + /** |
|
| 1123 | + * @return bool |
|
| 1124 | + * @throws EE_Error |
|
| 1125 | + * @throws InvalidArgumentException |
|
| 1126 | + * @throws InvalidDataTypeException |
|
| 1127 | + * @throws InvalidInterfaceException |
|
| 1128 | + * @throws ReflectionException |
|
| 1129 | + */ |
|
| 1130 | + public function is_cancelled() |
|
| 1131 | + { |
|
| 1132 | + return $this->type() === EEM_Line_Item::type_cancellation; |
|
| 1133 | + } |
|
| 1134 | + |
|
| 1135 | + |
|
| 1136 | + /** |
|
| 1137 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
| 1138 | + * @throws EE_Error |
|
| 1139 | + * @throws InvalidArgumentException |
|
| 1140 | + * @throws InvalidDataTypeException |
|
| 1141 | + * @throws InvalidInterfaceException |
|
| 1142 | + * @throws ReflectionException |
|
| 1143 | + */ |
|
| 1144 | + public function unit_price_no_code() |
|
| 1145 | + { |
|
| 1146 | + return $this->get_pretty('LIN_unit_price', 'no_currency_code'); |
|
| 1147 | + } |
|
| 1148 | + |
|
| 1149 | + |
|
| 1150 | + /** |
|
| 1151 | + * @return string like '2, 004.00', formatted according to the localized currency |
|
| 1152 | + * @throws EE_Error |
|
| 1153 | + * @throws InvalidArgumentException |
|
| 1154 | + * @throws InvalidDataTypeException |
|
| 1155 | + * @throws InvalidInterfaceException |
|
| 1156 | + * @throws ReflectionException |
|
| 1157 | + */ |
|
| 1158 | + public function total_no_code() |
|
| 1159 | + { |
|
| 1160 | + return $this->get_pretty('LIN_total', 'no_currency_code'); |
|
| 1161 | + } |
|
| 1162 | + |
|
| 1163 | + |
|
| 1164 | + /** |
|
| 1165 | + * Gets the final total on this item, taking taxes into account. |
|
| 1166 | + * Has the side-effect of setting the sub-total as it was just calculated. |
|
| 1167 | + * If this is used on a grand-total line item, also updates the transaction's |
|
| 1168 | + * TXN_total (provided this line item is allowed to persist, otherwise we don't |
|
| 1169 | + * want to change a persistable transaction with info from a non-persistent line item) |
|
| 1170 | + * |
|
| 1171 | + * @param bool $update_txn_status |
|
| 1172 | + * @return float |
|
| 1173 | + * @throws EE_Error |
|
| 1174 | + * @throws InvalidArgumentException |
|
| 1175 | + * @throws InvalidDataTypeException |
|
| 1176 | + * @throws InvalidInterfaceException |
|
| 1177 | + * @throws ReflectionException |
|
| 1178 | + * @throws RuntimeException |
|
| 1179 | + */ |
|
| 1180 | + public function recalculate_total_including_taxes($update_txn_status = false) |
|
| 1181 | + { |
|
| 1182 | + $pre_tax_total = $this->recalculate_pre_tax_total(); |
|
| 1183 | + $tax_total = $this->recalculate_taxes_and_tax_total(); |
|
| 1184 | + $total = $pre_tax_total + $tax_total; |
|
| 1185 | + // no negative totals plz |
|
| 1186 | + $total = max($total, 0); |
|
| 1187 | + $this->set_total($total); |
|
| 1188 | + // only update the related transaction's total |
|
| 1189 | + // if we intend to save this line item and its a grand total |
|
| 1190 | + if ($this->allow_persist() && $this->type() === EEM_Line_Item::type_total |
|
| 1191 | + && $this->transaction() |
|
| 1192 | + instanceof |
|
| 1193 | + EE_Transaction |
|
| 1194 | + ) { |
|
| 1195 | + $this->transaction()->set_total($total); |
|
| 1196 | + if ($update_txn_status) { |
|
| 1197 | + // don't save the TXN because that will be done below |
|
| 1198 | + // and the following method only saves if the status changes |
|
| 1199 | + $this->transaction()->update_status_based_on_total_paid(false); |
|
| 1200 | + } |
|
| 1201 | + if ($this->transaction()->ID()) { |
|
| 1202 | + $this->transaction()->save(); |
|
| 1203 | + } |
|
| 1204 | + } |
|
| 1205 | + $this->maybe_save(); |
|
| 1206 | + return $total; |
|
| 1207 | + } |
|
| 1208 | + |
|
| 1209 | + |
|
| 1210 | + /** |
|
| 1211 | + * Recursively goes through all the children and recalculates sub-totals EXCEPT for |
|
| 1212 | + * tax-sub-totals (they're a an odd beast). Updates the 'total' on each line item according to either its |
|
| 1213 | + * unit price * quantity or the total of all its children EXCEPT when we're only calculating the taxable total and |
|
| 1214 | + * when this is called on the grand total |
|
| 1215 | + * |
|
| 1216 | + * @return float |
|
| 1217 | + * @throws EE_Error |
|
| 1218 | + * @throws InvalidArgumentException |
|
| 1219 | + * @throws InvalidDataTypeException |
|
| 1220 | + * @throws InvalidInterfaceException |
|
| 1221 | + * @throws ReflectionException |
|
| 1222 | + */ |
|
| 1223 | + public function recalculate_pre_tax_total() |
|
| 1224 | + { |
|
| 1225 | + $total = 0; |
|
| 1226 | + $my_children = $this->children(); |
|
| 1227 | + $has_children = ! empty($my_children); |
|
| 1228 | + if ($has_children && $this->is_line_item()) { |
|
| 1229 | + $total = $this->_recalculate_pretax_total_for_line_item($total, $my_children); |
|
| 1230 | + } elseif (! $has_children && ($this->is_sub_line_item() || $this->is_line_item())) { |
|
| 1231 | + $total = $this->unit_price() * $this->quantity(); |
|
| 1232 | + } elseif ($this->is_sub_total() || $this->is_total()) { |
|
| 1233 | + $total = $this->_recalculate_pretax_total_for_subtotal($total, $my_children); |
|
| 1234 | + } elseif ($this->is_tax_sub_total() || $this->is_tax() || $this->is_cancelled()) { |
|
| 1235 | + // completely ignore tax totals, tax sub-totals, and cancelled line items, when calculating the pre-tax-total |
|
| 1236 | + return 0; |
|
| 1237 | + } |
|
| 1238 | + // ensure all non-line items and non-sub-line-items have a quantity of 1 (except for Events) |
|
| 1239 | + if (! $this->is_line_item() && ! $this->is_sub_line_item() && ! $this->is_cancellation() |
|
| 1240 | + ) { |
|
| 1241 | + if ($this->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_EVENT) { |
|
| 1242 | + $this->set_quantity(1); |
|
| 1243 | + } |
|
| 1244 | + if (! $this->is_percent()) { |
|
| 1245 | + $this->set_unit_price($total); |
|
| 1246 | + } |
|
| 1247 | + } |
|
| 1248 | + // we don't want to bother saving grand totals, because that needs to factor in taxes anyways |
|
| 1249 | + // so it ought to be |
|
| 1250 | + if (! $this->is_total()) { |
|
| 1251 | + $this->set_total($total); |
|
| 1252 | + // if not a percent line item, make sure we keep the unit price in sync |
|
| 1253 | + if ($has_children |
|
| 1254 | + && $this->is_line_item() |
|
| 1255 | + && ! $this->is_percent() |
|
| 1256 | + ) { |
|
| 1257 | + if ($this->quantity() === 0) { |
|
| 1258 | + $new_unit_price = 0; |
|
| 1259 | + } else { |
|
| 1260 | + $new_unit_price = $this->total() / $this->quantity(); |
|
| 1261 | + } |
|
| 1262 | + $this->set_unit_price($new_unit_price); |
|
| 1263 | + } |
|
| 1264 | + $this->maybe_save(); |
|
| 1265 | + } |
|
| 1266 | + return $total; |
|
| 1267 | + } |
|
| 1268 | + |
|
| 1269 | + |
|
| 1270 | + /** |
|
| 1271 | + * Calculates the pretax total when this line item is a subtotal or total line item. |
|
| 1272 | + * Basically does a sum-then-round approach (ie, any percent line item that are children |
|
| 1273 | + * will calculate their total based on the un-rounded total we're working with so far, and |
|
| 1274 | + * THEN round the result; instead of rounding as we go like with sub-line-items) |
|
| 1275 | + * |
|
| 1276 | + * @param float $calculated_total_so_far |
|
| 1277 | + * @param EE_Line_Item[] $my_children |
|
| 1278 | + * @return float |
|
| 1279 | + * @throws EE_Error |
|
| 1280 | + * @throws InvalidArgumentException |
|
| 1281 | + * @throws InvalidDataTypeException |
|
| 1282 | + * @throws InvalidInterfaceException |
|
| 1283 | + * @throws ReflectionException |
|
| 1284 | + */ |
|
| 1285 | + protected function _recalculate_pretax_total_for_subtotal($calculated_total_so_far, $my_children = null) |
|
| 1286 | + { |
|
| 1287 | + if ($my_children === null) { |
|
| 1288 | + $my_children = $this->children(); |
|
| 1289 | + } |
|
| 1290 | + $subtotal_quantity = 0; |
|
| 1291 | + // get the total of all its children |
|
| 1292 | + foreach ($my_children as $child_line_item) { |
|
| 1293 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
| 1294 | + // percentage line items are based on total so far |
|
| 1295 | + if ($child_line_item->is_percent()) { |
|
| 1296 | + // round as we go so that the line items add up ok |
|
| 1297 | + $percent_total = round( |
|
| 1298 | + $calculated_total_so_far * $child_line_item->percent() / 100, |
|
| 1299 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1300 | + ); |
|
| 1301 | + $child_line_item->set_total($percent_total); |
|
| 1302 | + // so far all percent line items should have a quantity of 1 |
|
| 1303 | + // (ie, no double percent discounts. Although that might be requested someday) |
|
| 1304 | + $child_line_item->set_quantity(1); |
|
| 1305 | + $child_line_item->maybe_save(); |
|
| 1306 | + $calculated_total_so_far += $percent_total; |
|
| 1307 | + } else { |
|
| 1308 | + // verify flat sub-line-item quantities match their parent |
|
| 1309 | + if ($child_line_item->is_sub_line_item()) { |
|
| 1310 | + $child_line_item->set_quantity($this->quantity()); |
|
| 1311 | + } |
|
| 1312 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1313 | + $subtotal_quantity += $child_line_item->quantity(); |
|
| 1314 | + } |
|
| 1315 | + } |
|
| 1316 | + } |
|
| 1317 | + if ($this->is_sub_total()) { |
|
| 1318 | + // no negative totals plz |
|
| 1319 | + $calculated_total_so_far = max($calculated_total_so_far, 0); |
|
| 1320 | + $subtotal_quantity = $subtotal_quantity > 0 ? 1 : 0; |
|
| 1321 | + $this->set_quantity($subtotal_quantity); |
|
| 1322 | + $this->maybe_save(); |
|
| 1323 | + } |
|
| 1324 | + return $calculated_total_so_far; |
|
| 1325 | + } |
|
| 1326 | + |
|
| 1327 | + |
|
| 1328 | + /** |
|
| 1329 | + * Calculates the pretax total for a normal line item, in a round-then-sum approach |
|
| 1330 | + * (where each sub-line-item is applied to the base price for the line item |
|
| 1331 | + * and the result is immediately rounded, rather than summing all the sub-line-items |
|
| 1332 | + * then rounding, like we do when recalculating pretax totals on totals and subtotals). |
|
| 1333 | + * |
|
| 1334 | + * @param float $calculated_total_so_far |
|
| 1335 | + * @param EE_Line_Item[] $my_children |
|
| 1336 | + * @return float |
|
| 1337 | + * @throws EE_Error |
|
| 1338 | + * @throws InvalidArgumentException |
|
| 1339 | + * @throws InvalidDataTypeException |
|
| 1340 | + * @throws InvalidInterfaceException |
|
| 1341 | + * @throws ReflectionException |
|
| 1342 | + */ |
|
| 1343 | + protected function _recalculate_pretax_total_for_line_item($calculated_total_so_far, $my_children = null) |
|
| 1344 | + { |
|
| 1345 | + if ($my_children === null) { |
|
| 1346 | + $my_children = $this->children(); |
|
| 1347 | + } |
|
| 1348 | + // we need to keep track of the running total for a single item, |
|
| 1349 | + // because we need to round as we go |
|
| 1350 | + $unit_price_for_total = 0; |
|
| 1351 | + $quantity_for_total = 1; |
|
| 1352 | + // get the total of all its children |
|
| 1353 | + foreach ($my_children as $child_line_item) { |
|
| 1354 | + if ($child_line_item instanceof EE_Line_Item && ! $child_line_item->is_cancellation()) { |
|
| 1355 | + if ($child_line_item->is_percent()) { |
|
| 1356 | + // it should be the unit-price-so-far multiplied by teh percent multiplied by the quantity |
|
| 1357 | + // not total multiplied by percent, because that ignores rounding along-the-way |
|
| 1358 | + $percent_unit_price = round( |
|
| 1359 | + $unit_price_for_total * $child_line_item->percent() / 100, |
|
| 1360 | + EE_Registry::instance()->CFG->currency->dec_plc |
|
| 1361 | + ); |
|
| 1362 | + $percent_total = $percent_unit_price * $quantity_for_total; |
|
| 1363 | + $child_line_item->set_total($percent_total); |
|
| 1364 | + // so far all percent line items should have a quantity of 1 |
|
| 1365 | + // (ie, no double percent discounts. Although that might be requested someday) |
|
| 1366 | + $child_line_item->set_quantity(1); |
|
| 1367 | + $child_line_item->maybe_save(); |
|
| 1368 | + $calculated_total_so_far += $percent_total; |
|
| 1369 | + $unit_price_for_total += $percent_unit_price; |
|
| 1370 | + } else { |
|
| 1371 | + // verify flat sub-line-item quantities match their parent |
|
| 1372 | + if ($child_line_item->is_sub_line_item()) { |
|
| 1373 | + $child_line_item->set_quantity($this->quantity()); |
|
| 1374 | + } |
|
| 1375 | + $quantity_for_total = $child_line_item->quantity(); |
|
| 1376 | + $calculated_total_so_far += $child_line_item->recalculate_pre_tax_total(); |
|
| 1377 | + $unit_price_for_total += $child_line_item->unit_price(); |
|
| 1378 | + } |
|
| 1379 | + } |
|
| 1380 | + } |
|
| 1381 | + return $calculated_total_so_far; |
|
| 1382 | + } |
|
| 1383 | + |
|
| 1384 | + |
|
| 1385 | + /** |
|
| 1386 | + * Recalculates the total on each individual tax (based on a recalculation of the pre-tax total), sets |
|
| 1387 | + * the totals on each tax calculated, and returns the final tax total. Re-saves tax line items |
|
| 1388 | + * and tax sub-total if already in the DB |
|
| 1389 | + * |
|
| 1390 | + * @return float |
|
| 1391 | + * @throws EE_Error |
|
| 1392 | + * @throws InvalidArgumentException |
|
| 1393 | + * @throws InvalidDataTypeException |
|
| 1394 | + * @throws InvalidInterfaceException |
|
| 1395 | + * @throws ReflectionException |
|
| 1396 | + */ |
|
| 1397 | + public function recalculate_taxes_and_tax_total() |
|
| 1398 | + { |
|
| 1399 | + // get all taxes |
|
| 1400 | + $taxes = $this->tax_descendants(); |
|
| 1401 | + // calculate the pretax total |
|
| 1402 | + $taxable_total = $this->taxable_total(); |
|
| 1403 | + $tax_total = 0; |
|
| 1404 | + foreach ($taxes as $tax) { |
|
| 1405 | + $total_on_this_tax = $taxable_total * $tax->percent() / 100; |
|
| 1406 | + // remember the total on this line item |
|
| 1407 | + $tax->set_total($total_on_this_tax); |
|
| 1408 | + $tax->maybe_save(); |
|
| 1409 | + $tax_total += $tax->total(); |
|
| 1410 | + } |
|
| 1411 | + $this->_recalculate_tax_sub_total(); |
|
| 1412 | + return $tax_total; |
|
| 1413 | + } |
|
| 1414 | + |
|
| 1415 | + |
|
| 1416 | + /** |
|
| 1417 | + * Simply forces all the tax-sub-totals to recalculate. Assumes the taxes have been calculated |
|
| 1418 | + * |
|
| 1419 | + * @return void |
|
| 1420 | + * @throws EE_Error |
|
| 1421 | + * @throws InvalidArgumentException |
|
| 1422 | + * @throws InvalidDataTypeException |
|
| 1423 | + * @throws InvalidInterfaceException |
|
| 1424 | + * @throws ReflectionException |
|
| 1425 | + */ |
|
| 1426 | + private function _recalculate_tax_sub_total() |
|
| 1427 | + { |
|
| 1428 | + if ($this->is_tax_sub_total()) { |
|
| 1429 | + $total = 0; |
|
| 1430 | + $total_percent = 0; |
|
| 1431 | + // simply loop through all its children (which should be taxes) and sum their total |
|
| 1432 | + foreach ($this->children() as $child_tax) { |
|
| 1433 | + if ($child_tax instanceof EE_Line_Item) { |
|
| 1434 | + $total += $child_tax->total(); |
|
| 1435 | + $total_percent += $child_tax->percent(); |
|
| 1436 | + } |
|
| 1437 | + } |
|
| 1438 | + $this->set_total($total); |
|
| 1439 | + $this->set_percent($total_percent); |
|
| 1440 | + $this->maybe_save(); |
|
| 1441 | + } elseif ($this->is_total()) { |
|
| 1442 | + foreach ($this->children() as $maybe_tax_subtotal) { |
|
| 1443 | + if ($maybe_tax_subtotal instanceof EE_Line_Item) { |
|
| 1444 | + $maybe_tax_subtotal->_recalculate_tax_sub_total(); |
|
| 1445 | + } |
|
| 1446 | + } |
|
| 1447 | + } |
|
| 1448 | + } |
|
| 1449 | + |
|
| 1450 | + |
|
| 1451 | + /** |
|
| 1452 | + * Gets the total tax on this line item. Assumes taxes have already been calculated using |
|
| 1453 | + * recalculate_taxes_and_total |
|
| 1454 | + * |
|
| 1455 | + * @return float |
|
| 1456 | + * @throws EE_Error |
|
| 1457 | + * @throws InvalidArgumentException |
|
| 1458 | + * @throws InvalidDataTypeException |
|
| 1459 | + * @throws InvalidInterfaceException |
|
| 1460 | + * @throws ReflectionException |
|
| 1461 | + */ |
|
| 1462 | + public function get_total_tax() |
|
| 1463 | + { |
|
| 1464 | + $this->_recalculate_tax_sub_total(); |
|
| 1465 | + $total = 0; |
|
| 1466 | + foreach ($this->tax_descendants() as $tax_line_item) { |
|
| 1467 | + if ($tax_line_item instanceof EE_Line_Item) { |
|
| 1468 | + $total += $tax_line_item->total(); |
|
| 1469 | + } |
|
| 1470 | + } |
|
| 1471 | + return $total; |
|
| 1472 | + } |
|
| 1473 | + |
|
| 1474 | + |
|
| 1475 | + /** |
|
| 1476 | + * Gets the total for all the items purchased only |
|
| 1477 | + * |
|
| 1478 | + * @return float |
|
| 1479 | + * @throws EE_Error |
|
| 1480 | + * @throws InvalidArgumentException |
|
| 1481 | + * @throws InvalidDataTypeException |
|
| 1482 | + * @throws InvalidInterfaceException |
|
| 1483 | + * @throws ReflectionException |
|
| 1484 | + */ |
|
| 1485 | + public function get_items_total() |
|
| 1486 | + { |
|
| 1487 | + // by default, let's make sure we're consistent with the existing line item |
|
| 1488 | + if ($this->is_total()) { |
|
| 1489 | + $pretax_subtotal_li = EEH_Line_Item::get_pre_tax_subtotal($this); |
|
| 1490 | + if ($pretax_subtotal_li instanceof EE_Line_Item) { |
|
| 1491 | + return $pretax_subtotal_li->total(); |
|
| 1492 | + } |
|
| 1493 | + } |
|
| 1494 | + $total = 0; |
|
| 1495 | + foreach ($this->get_items() as $item) { |
|
| 1496 | + if ($item instanceof EE_Line_Item) { |
|
| 1497 | + $total += $item->total(); |
|
| 1498 | + } |
|
| 1499 | + } |
|
| 1500 | + return $total; |
|
| 1501 | + } |
|
| 1502 | + |
|
| 1503 | + |
|
| 1504 | + /** |
|
| 1505 | + * Gets all the descendants (ie, children or children of children etc) that |
|
| 1506 | + * are of the type 'tax' |
|
| 1507 | + * |
|
| 1508 | + * @return EE_Line_Item[] |
|
| 1509 | + * @throws EE_Error |
|
| 1510 | + */ |
|
| 1511 | + public function tax_descendants() |
|
| 1512 | + { |
|
| 1513 | + return EEH_Line_Item::get_tax_descendants($this); |
|
| 1514 | + } |
|
| 1515 | + |
|
| 1516 | + |
|
| 1517 | + /** |
|
| 1518 | + * Gets all the real items purchased which are children of this item |
|
| 1519 | + * |
|
| 1520 | + * @return EE_Line_Item[] |
|
| 1521 | + * @throws EE_Error |
|
| 1522 | + */ |
|
| 1523 | + public function get_items() |
|
| 1524 | + { |
|
| 1525 | + return EEH_Line_Item::get_line_item_descendants($this); |
|
| 1526 | + } |
|
| 1527 | + |
|
| 1528 | + |
|
| 1529 | + /** |
|
| 1530 | + * Returns the amount taxable among this line item's children (or if it has no children, |
|
| 1531 | + * how much of it is taxable). Does not recalculate totals or subtotals. |
|
| 1532 | + * If the taxable total is negative, (eg, if none of the tickets were taxable, |
|
| 1533 | + * but there is a "Taxable" discount), returns 0. |
|
| 1534 | + * |
|
| 1535 | + * @return float |
|
| 1536 | + * @throws EE_Error |
|
| 1537 | + * @throws InvalidArgumentException |
|
| 1538 | + * @throws InvalidDataTypeException |
|
| 1539 | + * @throws InvalidInterfaceException |
|
| 1540 | + * @throws ReflectionException |
|
| 1541 | + */ |
|
| 1542 | + public function taxable_total() |
|
| 1543 | + { |
|
| 1544 | + $total = 0; |
|
| 1545 | + if ($this->children()) { |
|
| 1546 | + foreach ($this->children() as $child_line_item) { |
|
| 1547 | + if ($child_line_item->type() === EEM_Line_Item::type_line_item && $child_line_item->is_taxable()) { |
|
| 1548 | + // if it's a percent item, only take into account the percent |
|
| 1549 | + // that's taxable too (the taxable total so far) |
|
| 1550 | + if ($child_line_item->is_percent()) { |
|
| 1551 | + $total += ($total * $child_line_item->percent() / 100); |
|
| 1552 | + } else { |
|
| 1553 | + $total += $child_line_item->total(); |
|
| 1554 | + } |
|
| 1555 | + } elseif ($child_line_item->type() === EEM_Line_Item::type_sub_total) { |
|
| 1556 | + $total += $child_line_item->taxable_total(); |
|
| 1557 | + } |
|
| 1558 | + } |
|
| 1559 | + } |
|
| 1560 | + return max($total, 0); |
|
| 1561 | + } |
|
| 1562 | + |
|
| 1563 | + |
|
| 1564 | + /** |
|
| 1565 | + * Gets the transaction for this line item |
|
| 1566 | + * |
|
| 1567 | + * @return EE_Base_Class|EE_Transaction |
|
| 1568 | + * @throws EE_Error |
|
| 1569 | + * @throws InvalidArgumentException |
|
| 1570 | + * @throws InvalidDataTypeException |
|
| 1571 | + * @throws InvalidInterfaceException |
|
| 1572 | + * @throws ReflectionException |
|
| 1573 | + */ |
|
| 1574 | + public function transaction() |
|
| 1575 | + { |
|
| 1576 | + return $this->get_first_related(EEM_Line_Item::OBJ_TYPE_TRANSACTION); |
|
| 1577 | + } |
|
| 1578 | + |
|
| 1579 | + |
|
| 1580 | + /** |
|
| 1581 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1582 | + * Because there currently is no proper parent-child relation on the model, |
|
| 1583 | + * save_this_and_cached() will NOT save the descendants. |
|
| 1584 | + * Also sets the transaction on this line item and all its descendants before saving |
|
| 1585 | + * |
|
| 1586 | + * @param int $txn_id if none is provided, assumes $this->TXN_ID() |
|
| 1587 | + * @return int count of items saved |
|
| 1588 | + * @throws EE_Error |
|
| 1589 | + * @throws InvalidArgumentException |
|
| 1590 | + * @throws InvalidDataTypeException |
|
| 1591 | + * @throws InvalidInterfaceException |
|
| 1592 | + * @throws ReflectionException |
|
| 1593 | + */ |
|
| 1594 | + public function save_this_and_descendants_to_txn($txn_id = null) |
|
| 1595 | + { |
|
| 1596 | + $count = 0; |
|
| 1597 | + if (! $txn_id) { |
|
| 1598 | + $txn_id = $this->TXN_ID(); |
|
| 1599 | + } |
|
| 1600 | + $this->set_TXN_ID($txn_id); |
|
| 1601 | + $children = $this->children(); |
|
| 1602 | + $count += $this->save() |
|
| 1603 | + ? 1 |
|
| 1604 | + : 0; |
|
| 1605 | + foreach ($children as $child_line_item) { |
|
| 1606 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1607 | + $child_line_item->set_parent_ID($this->ID()); |
|
| 1608 | + $count += $child_line_item->save_this_and_descendants_to_txn($txn_id); |
|
| 1609 | + } |
|
| 1610 | + } |
|
| 1611 | + return $count; |
|
| 1612 | + } |
|
| 1613 | + |
|
| 1614 | + |
|
| 1615 | + /** |
|
| 1616 | + * Saves this line item to the DB, and recursively saves its descendants. |
|
| 1617 | + * |
|
| 1618 | + * @return int count of items saved |
|
| 1619 | + * @throws EE_Error |
|
| 1620 | + * @throws InvalidArgumentException |
|
| 1621 | + * @throws InvalidDataTypeException |
|
| 1622 | + * @throws InvalidInterfaceException |
|
| 1623 | + * @throws ReflectionException |
|
| 1624 | + */ |
|
| 1625 | + public function save_this_and_descendants() |
|
| 1626 | + { |
|
| 1627 | + $count = 0; |
|
| 1628 | + $children = $this->children(); |
|
| 1629 | + $count += $this->save() |
|
| 1630 | + ? 1 |
|
| 1631 | + : 0; |
|
| 1632 | + foreach ($children as $child_line_item) { |
|
| 1633 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1634 | + $child_line_item->set_parent_ID($this->ID()); |
|
| 1635 | + $count += $child_line_item->save_this_and_descendants(); |
|
| 1636 | + } |
|
| 1637 | + } |
|
| 1638 | + return $count; |
|
| 1639 | + } |
|
| 1640 | + |
|
| 1641 | + |
|
| 1642 | + /** |
|
| 1643 | + * returns the cancellation line item if this item was cancelled |
|
| 1644 | + * |
|
| 1645 | + * @return EE_Line_Item[] |
|
| 1646 | + * @throws InvalidArgumentException |
|
| 1647 | + * @throws InvalidInterfaceException |
|
| 1648 | + * @throws InvalidDataTypeException |
|
| 1649 | + * @throws ReflectionException |
|
| 1650 | + * @throws EE_Error |
|
| 1651 | + */ |
|
| 1652 | + public function get_cancellations() |
|
| 1653 | + { |
|
| 1654 | + EE_Registry::instance()->load_helper('Line_Item'); |
|
| 1655 | + return EEH_Line_Item::get_descendants_of_type($this, EEM_Line_Item::type_cancellation); |
|
| 1656 | + } |
|
| 1657 | + |
|
| 1658 | + |
|
| 1659 | + /** |
|
| 1660 | + * If this item has an ID, then this saves it again to update the db |
|
| 1661 | + * |
|
| 1662 | + * @return int count of items saved |
|
| 1663 | + * @throws EE_Error |
|
| 1664 | + * @throws InvalidArgumentException |
|
| 1665 | + * @throws InvalidDataTypeException |
|
| 1666 | + * @throws InvalidInterfaceException |
|
| 1667 | + * @throws ReflectionException |
|
| 1668 | + */ |
|
| 1669 | + public function maybe_save() |
|
| 1670 | + { |
|
| 1671 | + if ($this->ID()) { |
|
| 1672 | + return $this->save(); |
|
| 1673 | + } |
|
| 1674 | + return false; |
|
| 1675 | + } |
|
| 1676 | + |
|
| 1677 | + |
|
| 1678 | + /** |
|
| 1679 | + * clears the cached children and parent from the line item |
|
| 1680 | + * |
|
| 1681 | + * @return void |
|
| 1682 | + */ |
|
| 1683 | + public function clear_related_line_item_cache() |
|
| 1684 | + { |
|
| 1685 | + $this->_children = array(); |
|
| 1686 | + $this->_parent = null; |
|
| 1687 | + } |
|
| 1688 | + |
|
| 1689 | + |
|
| 1690 | + /** |
|
| 1691 | + * @param bool $raw |
|
| 1692 | + * @return int |
|
| 1693 | + * @throws EE_Error |
|
| 1694 | + * @throws InvalidArgumentException |
|
| 1695 | + * @throws InvalidDataTypeException |
|
| 1696 | + * @throws InvalidInterfaceException |
|
| 1697 | + * @throws ReflectionException |
|
| 1698 | + */ |
|
| 1699 | + public function timestamp($raw = false) |
|
| 1700 | + { |
|
| 1701 | + return $raw |
|
| 1702 | + ? $this->get_raw('LIN_timestamp') |
|
| 1703 | + : $this->get('LIN_timestamp'); |
|
| 1704 | + } |
|
| 1705 | + |
|
| 1706 | + |
|
| 1707 | + |
|
| 1708 | + |
|
| 1709 | + /************************* DEPRECATED *************************/ |
|
| 1710 | + /** |
|
| 1711 | + * @deprecated 4.6.0 |
|
| 1712 | + * @param string $type one of the constants on EEM_Line_Item |
|
| 1713 | + * @return EE_Line_Item[] |
|
| 1714 | + * @throws EE_Error |
|
| 1715 | + */ |
|
| 1716 | + protected function _get_descendants_of_type($type) |
|
| 1717 | + { |
|
| 1718 | + EE_Error::doing_it_wrong( |
|
| 1719 | + 'EE_Line_Item::_get_descendants_of_type()', |
|
| 1720 | + sprintf( |
|
| 1721 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1722 | + 'EEH_Line_Item::get_descendants_of_type()' |
|
| 1723 | + ), |
|
| 1724 | + '4.6.0' |
|
| 1725 | + ); |
|
| 1726 | + return EEH_Line_Item::get_descendants_of_type($this, $type); |
|
| 1727 | + } |
|
| 1728 | + |
|
| 1729 | + |
|
| 1730 | + /** |
|
| 1731 | + * @deprecated 4.6.0 |
|
| 1732 | + * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1733 | + * @return EE_Line_Item |
|
| 1734 | + * @throws EE_Error |
|
| 1735 | + * @throws InvalidArgumentException |
|
| 1736 | + * @throws InvalidDataTypeException |
|
| 1737 | + * @throws InvalidInterfaceException |
|
| 1738 | + * @throws ReflectionException |
|
| 1739 | + */ |
|
| 1740 | + public function get_nearest_descendant_of_type($type) |
|
| 1741 | + { |
|
| 1742 | + EE_Error::doing_it_wrong( |
|
| 1743 | + 'EE_Line_Item::get_nearest_descendant_of_type()', |
|
| 1744 | + sprintf( |
|
| 1745 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1746 | + 'EEH_Line_Item::get_nearest_descendant_of_type()' |
|
| 1747 | + ), |
|
| 1748 | + '4.6.0' |
|
| 1749 | + ); |
|
| 1750 | + return EEH_Line_Item::get_nearest_descendant_of_type($this, $type); |
|
| 1751 | + } |
|
| 1752 | 1752 | } |
@@ -1027,7 +1027,7 @@ discard block |
||
| 1027 | 1027 | * Deletes ALL children of the passed line item |
| 1028 | 1028 | * |
| 1029 | 1029 | * @param EE_Line_Item $parent_line_item |
| 1030 | - * @return bool |
|
| 1030 | + * @return integer |
|
| 1031 | 1031 | * @throws EE_Error |
| 1032 | 1032 | * @throws InvalidArgumentException |
| 1033 | 1033 | * @throws InvalidDataTypeException |
@@ -1333,6 +1333,7 @@ discard block |
||
| 1333 | 1333 | * @param string $line_item_type one of the EEM_Line_Item constants |
| 1334 | 1334 | * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when |
| 1335 | 1335 | * searching |
| 1336 | + * @param string $obj_type |
|
| 1336 | 1337 | * @return EE_Line_Item[] |
| 1337 | 1338 | * @throws EE_Error |
| 1338 | 1339 | */ |
@@ -138,7 +138,7 @@ discard block |
||
| 138 | 138 | */ |
| 139 | 139 | public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
| 140 | 140 | { |
| 141 | - if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) { |
|
| 141 | + if ( ! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) { |
|
| 142 | 142 | throw new EE_Error( |
| 143 | 143 | sprintf( |
| 144 | 144 | esc_html__( |
@@ -153,7 +153,7 @@ discard block |
||
| 153 | 153 | // either increment the qty for an existing ticket |
| 154 | 154 | $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty); |
| 155 | 155 | // or add a new one |
| 156 | - if (! $line_item instanceof EE_Line_Item) { |
|
| 156 | + if ( ! $line_item instanceof EE_Line_Item) { |
|
| 157 | 157 | $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty); |
| 158 | 158 | } |
| 159 | 159 | $total_line_item->recalculate_total_including_taxes(); |
@@ -214,7 +214,7 @@ discard block |
||
| 214 | 214 | */ |
| 215 | 215 | public static function increment_quantity(EE_Line_Item $line_item, $qty = 1) |
| 216 | 216 | { |
| 217 | - if (! $line_item->is_percent()) { |
|
| 217 | + if ( ! $line_item->is_percent()) { |
|
| 218 | 218 | $qty += $line_item->quantity(); |
| 219 | 219 | $line_item->set_quantity($qty); |
| 220 | 220 | $line_item->set_total($line_item->unit_price() * $qty); |
@@ -243,7 +243,7 @@ discard block |
||
| 243 | 243 | */ |
| 244 | 244 | public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1) |
| 245 | 245 | { |
| 246 | - if (! $line_item->is_percent()) { |
|
| 246 | + if ( ! $line_item->is_percent()) { |
|
| 247 | 247 | $qty = $line_item->quantity() - $qty; |
| 248 | 248 | $qty = max($qty, 0); |
| 249 | 249 | $line_item->set_quantity($qty); |
@@ -272,7 +272,7 @@ discard block |
||
| 272 | 272 | */ |
| 273 | 273 | public static function update_quantity(EE_Line_Item $line_item, $new_quantity) |
| 274 | 274 | { |
| 275 | - if (! $line_item->is_percent()) { |
|
| 275 | + if ( ! $line_item->is_percent()) { |
|
| 276 | 276 | $line_item->set_quantity($new_quantity); |
| 277 | 277 | $line_item->set_total($line_item->unit_price() * $new_quantity); |
| 278 | 278 | $line_item->save(); |
@@ -312,7 +312,7 @@ discard block |
||
| 312 | 312 | // add $ticket to cart |
| 313 | 313 | $line_item = EE_Line_Item::new_instance(array( |
| 314 | 314 | 'LIN_name' => $ticket->name(), |
| 315 | - 'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event, |
|
| 315 | + 'LIN_desc' => $ticket->description() !== '' ? $ticket->description().' '.$event : $event, |
|
| 316 | 316 | 'LIN_unit_price' => $ticket->price(), |
| 317 | 317 | 'LIN_quantity' => $qty, |
| 318 | 318 | 'LIN_is_taxable' => $ticket->taxable(), |
@@ -462,7 +462,7 @@ discard block |
||
| 462 | 462 | 'event_espresso' |
| 463 | 463 | ), |
| 464 | 464 | $ticket_line_item->name(), |
| 465 | - current_time(get_option('date_format') . ' ' . get_option('time_format')) |
|
| 465 | + current_time(get_option('date_format').' '.get_option('time_format')) |
|
| 466 | 466 | ), |
| 467 | 467 | 'LIN_unit_price' => 0, // $ticket_line_item->unit_price() |
| 468 | 468 | 'LIN_quantity' => $qty, |
@@ -524,7 +524,7 @@ discard block |
||
| 524 | 524 | ); |
| 525 | 525 | $cancellation_line_item = reset($cancellation_line_item); |
| 526 | 526 | // verify that this ticket was indeed previously cancelled |
| 527 | - if (! $cancellation_line_item instanceof EE_Line_Item) { |
|
| 527 | + if ( ! $cancellation_line_item instanceof EE_Line_Item) { |
|
| 528 | 528 | return false; |
| 529 | 529 | } |
| 530 | 530 | if ($cancellation_line_item->quantity() > $qty) { |
@@ -729,7 +729,7 @@ discard block |
||
| 729 | 729 | 'LIN_code' => 'taxes', |
| 730 | 730 | 'LIN_name' => esc_html__('Taxes', 'event_espresso'), |
| 731 | 731 | 'LIN_type' => EEM_Line_Item::type_tax_sub_total, |
| 732 | - 'LIN_order' => 1000,// this should always come last |
|
| 732 | + 'LIN_order' => 1000, // this should always come last |
|
| 733 | 733 | )); |
| 734 | 734 | $tax_line_item = apply_filters( |
| 735 | 735 | 'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item', |
@@ -785,7 +785,7 @@ discard block |
||
| 785 | 785 | */ |
| 786 | 786 | public static function get_event_code($event) |
| 787 | 787 | { |
| 788 | - return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 788 | + return 'event-'.($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 789 | 789 | } |
| 790 | 790 | |
| 791 | 791 | |
@@ -834,7 +834,7 @@ discard block |
||
| 834 | 834 | public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket) |
| 835 | 835 | { |
| 836 | 836 | $first_datetime = $ticket->first_datetime(); |
| 837 | - if (! $first_datetime instanceof EE_Datetime) { |
|
| 837 | + if ( ! $first_datetime instanceof EE_Datetime) { |
|
| 838 | 838 | throw new EE_Error( |
| 839 | 839 | sprintf( |
| 840 | 840 | __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), |
@@ -843,7 +843,7 @@ discard block |
||
| 843 | 843 | ); |
| 844 | 844 | } |
| 845 | 845 | $event = $first_datetime->event(); |
| 846 | - if (! $event instanceof EE_Event) { |
|
| 846 | + if ( ! $event instanceof EE_Event) { |
|
| 847 | 847 | throw new EE_Error( |
| 848 | 848 | sprintf( |
| 849 | 849 | esc_html__( |
@@ -855,7 +855,7 @@ discard block |
||
| 855 | 855 | ); |
| 856 | 856 | } |
| 857 | 857 | $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event); |
| 858 | - if (! $events_sub_total instanceof EE_Line_Item) { |
|
| 858 | + if ( ! $events_sub_total instanceof EE_Line_Item) { |
|
| 859 | 859 | throw new EE_Error( |
| 860 | 860 | sprintf( |
| 861 | 861 | esc_html__( |
@@ -891,7 +891,7 @@ discard block |
||
| 891 | 891 | $found = false; |
| 892 | 892 | foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) { |
| 893 | 893 | // default event subtotal, we should only ever find this the first time this method is called |
| 894 | - if (! $event_line_item->OBJ_ID()) { |
|
| 894 | + if ( ! $event_line_item->OBJ_ID()) { |
|
| 895 | 895 | // let's use this! but first... set the event details |
| 896 | 896 | EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
| 897 | 897 | $found = true; |
@@ -903,7 +903,7 @@ discard block |
||
| 903 | 903 | break; |
| 904 | 904 | } |
| 905 | 905 | } |
| 906 | - if (! $found) { |
|
| 906 | + if ( ! $found) { |
|
| 907 | 907 | // there is no event sub-total yet, so add it |
| 908 | 908 | $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total); |
| 909 | 909 | // create a new "event" subtotal below that |
@@ -1018,7 +1018,7 @@ discard block |
||
| 1018 | 1018 | public static function ensure_taxes_applied($total_line_item) |
| 1019 | 1019 | { |
| 1020 | 1020 | $taxes_subtotal = self::get_taxes_subtotal($total_line_item); |
| 1021 | - if (! $taxes_subtotal->children()) { |
|
| 1021 | + if ( ! $taxes_subtotal->children()) { |
|
| 1022 | 1022 | self::apply_taxes($total_line_item); |
| 1023 | 1023 | } |
| 1024 | 1024 | return $taxes_subtotal->total(); |
@@ -1085,7 +1085,7 @@ discard block |
||
| 1085 | 1085 | do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
| 1086 | 1086 | |
| 1087 | 1087 | // check if only a single line_item_id was passed |
| 1088 | - if (! empty($line_item_codes) && ! is_array($line_item_codes)) { |
|
| 1088 | + if ( ! empty($line_item_codes) && ! is_array($line_item_codes)) { |
|
| 1089 | 1089 | // place single line_item_id in an array to appear as multiple line_item_ids |
| 1090 | 1090 | $line_item_codes = array($line_item_codes); |
| 1091 | 1091 | } |
@@ -1192,7 +1192,7 @@ discard block |
||
| 1192 | 1192 | if ($code_substring_for_whitelist !== null) { |
| 1193 | 1193 | $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false; |
| 1194 | 1194 | } |
| 1195 | - if (! $whitelisted && $line_item->is_line_item()) { |
|
| 1195 | + if ( ! $whitelisted && $line_item->is_line_item()) { |
|
| 1196 | 1196 | $line_item->set_is_taxable($taxable); |
| 1197 | 1197 | } |
| 1198 | 1198 | foreach ($line_item->children() as $child_line_item) { |
@@ -1554,7 +1554,7 @@ discard block |
||
| 1554 | 1554 | public static function visualize(EE_Line_Item $line_item, $indentation = 0) |
| 1555 | 1555 | { |
| 1556 | 1556 | echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
| 1557 | - if (! $indentation) { |
|
| 1557 | + if ( ! $indentation) { |
|
| 1558 | 1558 | echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
| 1559 | 1559 | } |
| 1560 | 1560 | for ($i = 0; $i < $indentation; $i++) { |
@@ -1565,12 +1565,12 @@ discard block |
||
| 1565 | 1565 | if ($line_item->is_percent()) { |
| 1566 | 1566 | $breakdown = "{$line_item->percent()}%"; |
| 1567 | 1567 | } else { |
| 1568 | - $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1568 | + $breakdown = '$'."{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1569 | 1569 | } |
| 1570 | 1570 | } |
| 1571 | 1571 | echo $line_item->name(); |
| 1572 | 1572 | echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : "; |
| 1573 | - echo '$' . (string) $line_item->total(); |
|
| 1573 | + echo '$'.(string) $line_item->total(); |
|
| 1574 | 1574 | if ($breakdown) { |
| 1575 | 1575 | echo " ( {$breakdown} )"; |
| 1576 | 1576 | } |
@@ -1658,8 +1658,8 @@ discard block |
||
| 1658 | 1658 | if ($line_item_id === 'taxable') { |
| 1659 | 1659 | continue; |
| 1660 | 1660 | } |
| 1661 | - $taxable_total = $running_totals['taxable'][ $line_item_id ]; |
|
| 1662 | - $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal); |
|
| 1661 | + $taxable_total = $running_totals['taxable'][$line_item_id]; |
|
| 1662 | + $running_totals[$line_item_id] += ($taxable_total * $tax_percent_decimal); |
|
| 1663 | 1663 | } |
| 1664 | 1664 | break; |
| 1665 | 1665 | |
@@ -1667,7 +1667,7 @@ discard block |
||
| 1667 | 1667 | // ticket line items or ???? |
| 1668 | 1668 | if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
| 1669 | 1669 | // kk it's a ticket |
| 1670 | - if (isset($running_totals[ $child_line_item->ID() ])) { |
|
| 1670 | + if (isset($running_totals[$child_line_item->ID()])) { |
|
| 1671 | 1671 | // huh? that shouldn't happen. |
| 1672 | 1672 | $running_totals['total'] += $child_line_item->total(); |
| 1673 | 1673 | } else { |
@@ -1678,18 +1678,18 @@ discard block |
||
| 1678 | 1678 | $taxable_amount = 0; |
| 1679 | 1679 | } |
| 1680 | 1680 | // are we only calculating totals for some tickets? |
| 1681 | - if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) { |
|
| 1682 | - $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ]; |
|
| 1683 | - $running_totals[ $child_line_item->ID() ] = $quantity |
|
| 1681 | + if (isset($billable_ticket_quantities[$child_line_item->OBJ_ID()])) { |
|
| 1682 | + $quantity = $billable_ticket_quantities[$child_line_item->OBJ_ID()]; |
|
| 1683 | + $running_totals[$child_line_item->ID()] = $quantity |
|
| 1684 | 1684 | ? $child_line_item->unit_price() |
| 1685 | 1685 | : 0; |
| 1686 | - $running_totals['taxable'][ $child_line_item->ID() ] = $quantity |
|
| 1686 | + $running_totals['taxable'][$child_line_item->ID()] = $quantity |
|
| 1687 | 1687 | ? $taxable_amount |
| 1688 | 1688 | : 0; |
| 1689 | 1689 | } else { |
| 1690 | 1690 | $quantity = $child_line_item->quantity(); |
| 1691 | - $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price(); |
|
| 1692 | - $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount; |
|
| 1691 | + $running_totals[$child_line_item->ID()] = $child_line_item->unit_price(); |
|
| 1692 | + $running_totals['taxable'][$child_line_item->ID()] = $taxable_amount; |
|
| 1693 | 1693 | } |
| 1694 | 1694 | $running_totals['taxable']['total'] += $taxable_amount * $quantity; |
| 1695 | 1695 | $running_totals['total'] += $child_line_item->unit_price() * $quantity; |
@@ -1709,12 +1709,12 @@ discard block |
||
| 1709 | 1709 | } |
| 1710 | 1710 | // update the running totals |
| 1711 | 1711 | // yes this actually even works for the running grand total! |
| 1712 | - $running_totals[ $line_item_id ] = |
|
| 1712 | + $running_totals[$line_item_id] = |
|
| 1713 | 1713 | $line_items_percent_of_running_total * $this_running_total; |
| 1714 | 1714 | |
| 1715 | 1715 | if ($child_line_item->is_taxable()) { |
| 1716 | - $running_totals['taxable'][ $line_item_id ] = |
|
| 1717 | - $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ]; |
|
| 1716 | + $running_totals['taxable'][$line_item_id] = |
|
| 1717 | + $line_items_percent_of_running_total * $running_totals['taxable'][$line_item_id]; |
|
| 1718 | 1718 | } |
| 1719 | 1719 | } |
| 1720 | 1720 | } |
@@ -1747,8 +1747,8 @@ discard block |
||
| 1747 | 1747 | ); |
| 1748 | 1748 | } |
| 1749 | 1749 | // ok now find this new registration's final price |
| 1750 | - if (isset($final_prices_per_ticket_line_item[ $ticket_line_item->ID() ])) { |
|
| 1751 | - return $final_prices_per_ticket_line_item[ $ticket_line_item->ID() ]; |
|
| 1750 | + if (isset($final_prices_per_ticket_line_item[$ticket_line_item->ID()])) { |
|
| 1751 | + return $final_prices_per_ticket_line_item[$ticket_line_item->ID()]; |
|
| 1752 | 1752 | } |
| 1753 | 1753 | $message = sprintf( |
| 1754 | 1754 | esc_html__( |
@@ -1758,7 +1758,7 @@ discard block |
||
| 1758 | 1758 | $ticket_line_item->ID() |
| 1759 | 1759 | ); |
| 1760 | 1760 | if (WP_DEBUG) { |
| 1761 | - $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true); |
|
| 1761 | + $message .= '<br>'.print_r($final_prices_per_ticket_line_item, true); |
|
| 1762 | 1762 | throw new OutOfRangeException($message); |
| 1763 | 1763 | } |
| 1764 | 1764 | EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message); |
@@ -21,2045 +21,2045 @@ |
||
| 21 | 21 | class EEH_Line_Item |
| 22 | 22 | { |
| 23 | 23 | |
| 24 | - /** |
|
| 25 | - * Adds a simple item (unrelated to any other model object) to the provided PARENT line item. |
|
| 26 | - * Does NOT automatically re-calculate the line item totals or update the related transaction. |
|
| 27 | - * You should call recalculate_total_including_taxes() on the grant total line item after this |
|
| 28 | - * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 29 | - * to keep the registration final prices in-sync with the transaction's total. |
|
| 30 | - * |
|
| 31 | - * @param EE_Line_Item $parent_line_item |
|
| 32 | - * @param string $name |
|
| 33 | - * @param float $unit_price |
|
| 34 | - * @param string $description |
|
| 35 | - * @param int $quantity |
|
| 36 | - * @param boolean $taxable |
|
| 37 | - * @param boolean $code if set to a value, ensures there is only one line item with that code |
|
| 38 | - * @return boolean success |
|
| 39 | - * @throws EE_Error |
|
| 40 | - * @throws InvalidArgumentException |
|
| 41 | - * @throws InvalidDataTypeException |
|
| 42 | - * @throws InvalidInterfaceException |
|
| 43 | - * @throws ReflectionException |
|
| 44 | - */ |
|
| 45 | - public static function add_unrelated_item( |
|
| 46 | - EE_Line_Item $parent_line_item, |
|
| 47 | - $name, |
|
| 48 | - $unit_price, |
|
| 49 | - $description = '', |
|
| 50 | - $quantity = 1, |
|
| 51 | - $taxable = false, |
|
| 52 | - $code = null |
|
| 53 | - ) { |
|
| 54 | - $items_subtotal = self::get_pre_tax_subtotal($parent_line_item); |
|
| 55 | - $line_item = EE_Line_Item::new_instance(array( |
|
| 56 | - 'LIN_name' => $name, |
|
| 57 | - 'LIN_desc' => $description, |
|
| 58 | - 'LIN_unit_price' => $unit_price, |
|
| 59 | - 'LIN_quantity' => $quantity, |
|
| 60 | - 'LIN_percent' => null, |
|
| 61 | - 'LIN_is_taxable' => $taxable, |
|
| 62 | - 'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0, |
|
| 63 | - 'LIN_total' => (float) $unit_price * (int) $quantity, |
|
| 64 | - 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 65 | - 'LIN_code' => $code, |
|
| 66 | - )); |
|
| 67 | - $line_item = apply_filters( |
|
| 68 | - 'FHEE__EEH_Line_Item__add_unrelated_item__line_item', |
|
| 69 | - $line_item, |
|
| 70 | - $parent_line_item |
|
| 71 | - ); |
|
| 72 | - return self::add_item($parent_line_item, $line_item); |
|
| 73 | - } |
|
| 74 | - |
|
| 75 | - |
|
| 76 | - /** |
|
| 77 | - * Adds a simple item ( unrelated to any other model object) to the total line item, |
|
| 78 | - * in the correct spot in the line item tree. Automatically |
|
| 79 | - * re-calculates the line item totals and updates the related transaction. But |
|
| 80 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 81 | - * should probably change because of this). |
|
| 82 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 83 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 84 | - * |
|
| 85 | - * @param EE_Line_Item $parent_line_item |
|
| 86 | - * @param string $name |
|
| 87 | - * @param float $percentage_amount |
|
| 88 | - * @param string $description |
|
| 89 | - * @param boolean $taxable |
|
| 90 | - * @return boolean success |
|
| 91 | - * @throws EE_Error |
|
| 92 | - */ |
|
| 93 | - public static function add_percentage_based_item( |
|
| 94 | - EE_Line_Item $parent_line_item, |
|
| 95 | - $name, |
|
| 96 | - $percentage_amount, |
|
| 97 | - $description = '', |
|
| 98 | - $taxable = false |
|
| 99 | - ) { |
|
| 100 | - $line_item = EE_Line_Item::new_instance(array( |
|
| 101 | - 'LIN_name' => $name, |
|
| 102 | - 'LIN_desc' => $description, |
|
| 103 | - 'LIN_unit_price' => 0, |
|
| 104 | - 'LIN_percent' => $percentage_amount, |
|
| 105 | - 'LIN_quantity' => 1, |
|
| 106 | - 'LIN_is_taxable' => $taxable, |
|
| 107 | - 'LIN_total' => (float) ($percentage_amount * ($parent_line_item->total() / 100)), |
|
| 108 | - 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 109 | - 'LIN_parent' => $parent_line_item->ID(), |
|
| 110 | - )); |
|
| 111 | - $line_item = apply_filters( |
|
| 112 | - 'FHEE__EEH_Line_Item__add_percentage_based_item__line_item', |
|
| 113 | - $line_item |
|
| 114 | - ); |
|
| 115 | - return $parent_line_item->add_child_line_item($line_item, false); |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - |
|
| 119 | - /** |
|
| 120 | - * Returns the new line item created by adding a purchase of the ticket |
|
| 121 | - * ensures that ticket line item is saved, and that cart total has been recalculated. |
|
| 122 | - * If this ticket has already been purchased, just increments its count. |
|
| 123 | - * Automatically re-calculates the line item totals and updates the related transaction. But |
|
| 124 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 125 | - * should probably change because of this). |
|
| 126 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 127 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 128 | - * |
|
| 129 | - * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total |
|
| 130 | - * @param EE_Ticket $ticket |
|
| 131 | - * @param int $qty |
|
| 132 | - * @return EE_Line_Item |
|
| 133 | - * @throws EE_Error |
|
| 134 | - * @throws InvalidArgumentException |
|
| 135 | - * @throws InvalidDataTypeException |
|
| 136 | - * @throws InvalidInterfaceException |
|
| 137 | - * @throws ReflectionException |
|
| 138 | - */ |
|
| 139 | - public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 140 | - { |
|
| 141 | - if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) { |
|
| 142 | - throw new EE_Error( |
|
| 143 | - sprintf( |
|
| 144 | - esc_html__( |
|
| 145 | - 'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', |
|
| 146 | - 'event_espresso' |
|
| 147 | - ), |
|
| 148 | - $ticket->ID(), |
|
| 149 | - $total_line_item->ID() |
|
| 150 | - ) |
|
| 151 | - ); |
|
| 152 | - } |
|
| 153 | - // either increment the qty for an existing ticket |
|
| 154 | - $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty); |
|
| 155 | - // or add a new one |
|
| 156 | - if (! $line_item instanceof EE_Line_Item) { |
|
| 157 | - $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty); |
|
| 158 | - } |
|
| 159 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 160 | - return $line_item; |
|
| 161 | - } |
|
| 162 | - |
|
| 163 | - |
|
| 164 | - /** |
|
| 165 | - * Returns the new line item created by adding a purchase of the ticket |
|
| 166 | - * |
|
| 167 | - * @param EE_Line_Item $total_line_item |
|
| 168 | - * @param EE_Ticket $ticket |
|
| 169 | - * @param int $qty |
|
| 170 | - * @return EE_Line_Item |
|
| 171 | - * @throws EE_Error |
|
| 172 | - * @throws InvalidArgumentException |
|
| 173 | - * @throws InvalidDataTypeException |
|
| 174 | - * @throws InvalidInterfaceException |
|
| 175 | - * @throws ReflectionException |
|
| 176 | - */ |
|
| 177 | - public static function increment_ticket_qty_if_already_in_cart( |
|
| 178 | - EE_Line_Item $total_line_item, |
|
| 179 | - EE_Ticket $ticket, |
|
| 180 | - $qty = 1 |
|
| 181 | - ) { |
|
| 182 | - $line_item = null; |
|
| 183 | - if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) { |
|
| 184 | - $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item); |
|
| 185 | - foreach ((array) $ticket_line_items as $ticket_line_item) { |
|
| 186 | - if ($ticket_line_item instanceof EE_Line_Item |
|
| 187 | - && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID() |
|
| 188 | - ) { |
|
| 189 | - $line_item = $ticket_line_item; |
|
| 190 | - break; |
|
| 191 | - } |
|
| 192 | - } |
|
| 193 | - } |
|
| 194 | - if ($line_item instanceof EE_Line_Item) { |
|
| 195 | - EEH_Line_Item::increment_quantity($line_item, $qty); |
|
| 196 | - return $line_item; |
|
| 197 | - } |
|
| 198 | - return null; |
|
| 199 | - } |
|
| 200 | - |
|
| 201 | - |
|
| 202 | - /** |
|
| 203 | - * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 204 | - * Does NOT save or recalculate other line items totals |
|
| 205 | - * |
|
| 206 | - * @param EE_Line_Item $line_item |
|
| 207 | - * @param int $qty |
|
| 208 | - * @return void |
|
| 209 | - * @throws EE_Error |
|
| 210 | - * @throws InvalidArgumentException |
|
| 211 | - * @throws InvalidDataTypeException |
|
| 212 | - * @throws InvalidInterfaceException |
|
| 213 | - * @throws ReflectionException |
|
| 214 | - */ |
|
| 215 | - public static function increment_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 216 | - { |
|
| 217 | - if (! $line_item->is_percent()) { |
|
| 218 | - $qty += $line_item->quantity(); |
|
| 219 | - $line_item->set_quantity($qty); |
|
| 220 | - $line_item->set_total($line_item->unit_price() * $qty); |
|
| 221 | - $line_item->save(); |
|
| 222 | - } |
|
| 223 | - foreach ($line_item->children() as $child) { |
|
| 224 | - if ($child->is_sub_line_item()) { |
|
| 225 | - EEH_Line_Item::update_quantity($child, $qty); |
|
| 226 | - } |
|
| 227 | - } |
|
| 228 | - } |
|
| 229 | - |
|
| 230 | - |
|
| 231 | - /** |
|
| 232 | - * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 233 | - * Does NOT save or recalculate other line items totals |
|
| 234 | - * |
|
| 235 | - * @param EE_Line_Item $line_item |
|
| 236 | - * @param int $qty |
|
| 237 | - * @return void |
|
| 238 | - * @throws EE_Error |
|
| 239 | - * @throws InvalidArgumentException |
|
| 240 | - * @throws InvalidDataTypeException |
|
| 241 | - * @throws InvalidInterfaceException |
|
| 242 | - * @throws ReflectionException |
|
| 243 | - */ |
|
| 244 | - public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 245 | - { |
|
| 246 | - if (! $line_item->is_percent()) { |
|
| 247 | - $qty = $line_item->quantity() - $qty; |
|
| 248 | - $qty = max($qty, 0); |
|
| 249 | - $line_item->set_quantity($qty); |
|
| 250 | - $line_item->set_total($line_item->unit_price() * $qty); |
|
| 251 | - $line_item->save(); |
|
| 252 | - } |
|
| 253 | - foreach ($line_item->children() as $child) { |
|
| 254 | - if ($child->is_sub_line_item()) { |
|
| 255 | - EEH_Line_Item::update_quantity($child, $qty); |
|
| 256 | - } |
|
| 257 | - } |
|
| 258 | - } |
|
| 259 | - |
|
| 260 | - |
|
| 261 | - /** |
|
| 262 | - * Updates the line item and its children's quantities to the specified number. |
|
| 263 | - * Does NOT save them or recalculate totals. |
|
| 264 | - * |
|
| 265 | - * @param EE_Line_Item $line_item |
|
| 266 | - * @param int $new_quantity |
|
| 267 | - * @throws EE_Error |
|
| 268 | - * @throws InvalidArgumentException |
|
| 269 | - * @throws InvalidDataTypeException |
|
| 270 | - * @throws InvalidInterfaceException |
|
| 271 | - * @throws ReflectionException |
|
| 272 | - */ |
|
| 273 | - public static function update_quantity(EE_Line_Item $line_item, $new_quantity) |
|
| 274 | - { |
|
| 275 | - if (! $line_item->is_percent()) { |
|
| 276 | - $line_item->set_quantity($new_quantity); |
|
| 277 | - $line_item->set_total($line_item->unit_price() * $new_quantity); |
|
| 278 | - $line_item->save(); |
|
| 279 | - } |
|
| 280 | - foreach ($line_item->children() as $child) { |
|
| 281 | - if ($child->is_sub_line_item()) { |
|
| 282 | - EEH_Line_Item::update_quantity($child, $new_quantity); |
|
| 283 | - } |
|
| 284 | - } |
|
| 285 | - } |
|
| 286 | - |
|
| 287 | - |
|
| 288 | - /** |
|
| 289 | - * Returns the new line item created by adding a purchase of the ticket |
|
| 290 | - * |
|
| 291 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 292 | - * @param EE_Ticket $ticket |
|
| 293 | - * @param int $qty |
|
| 294 | - * @return EE_Line_Item |
|
| 295 | - * @throws EE_Error |
|
| 296 | - * @throws InvalidArgumentException |
|
| 297 | - * @throws InvalidDataTypeException |
|
| 298 | - * @throws InvalidInterfaceException |
|
| 299 | - * @throws ReflectionException |
|
| 300 | - */ |
|
| 301 | - public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 302 | - { |
|
| 303 | - $datetimes = $ticket->datetimes(); |
|
| 304 | - $first_datetime = reset($datetimes); |
|
| 305 | - $first_datetime_name = esc_html__('Event', 'event_espresso'); |
|
| 306 | - if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) { |
|
| 307 | - $first_datetime_name = $first_datetime->event()->name(); |
|
| 308 | - } |
|
| 309 | - $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name); |
|
| 310 | - // get event subtotal line |
|
| 311 | - $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket); |
|
| 312 | - // add $ticket to cart |
|
| 313 | - $line_item = EE_Line_Item::new_instance(array( |
|
| 314 | - 'LIN_name' => $ticket->name(), |
|
| 315 | - 'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event, |
|
| 316 | - 'LIN_unit_price' => $ticket->price(), |
|
| 317 | - 'LIN_quantity' => $qty, |
|
| 318 | - 'LIN_is_taxable' => $ticket->taxable(), |
|
| 319 | - 'LIN_order' => count($events_sub_total->children()), |
|
| 320 | - 'LIN_total' => $ticket->price() * $qty, |
|
| 321 | - 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 322 | - 'OBJ_ID' => $ticket->ID(), |
|
| 323 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 324 | - )); |
|
| 325 | - $line_item = apply_filters( |
|
| 326 | - 'FHEE__EEH_Line_Item__create_ticket_line_item__line_item', |
|
| 327 | - $line_item |
|
| 328 | - ); |
|
| 329 | - $events_sub_total->add_child_line_item($line_item); |
|
| 330 | - // now add the sub-line items |
|
| 331 | - $running_total_for_ticket = 0; |
|
| 332 | - foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) { |
|
| 333 | - $sign = $price->is_discount() ? -1 : 1; |
|
| 334 | - $price_total = $price->is_percent() |
|
| 335 | - ? $running_total_for_ticket * $price->amount() / 100 |
|
| 336 | - : $price->amount() * $qty; |
|
| 337 | - $sub_line_item = EE_Line_Item::new_instance(array( |
|
| 338 | - 'LIN_name' => $price->name(), |
|
| 339 | - 'LIN_desc' => $price->desc(), |
|
| 340 | - 'LIN_quantity' => $price->is_percent() ? null : $qty, |
|
| 341 | - 'LIN_is_taxable' => false, |
|
| 342 | - 'LIN_order' => $price->order(), |
|
| 343 | - 'LIN_total' => $sign * $price_total, |
|
| 344 | - 'LIN_type' => EEM_Line_Item::type_sub_line_item, |
|
| 345 | - 'OBJ_ID' => $price->ID(), |
|
| 346 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PRICE, |
|
| 347 | - )); |
|
| 348 | - $sub_line_item = apply_filters( |
|
| 349 | - 'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item', |
|
| 350 | - $sub_line_item |
|
| 351 | - ); |
|
| 352 | - if ($price->is_percent()) { |
|
| 353 | - $sub_line_item->set_percent($sign * $price->amount()); |
|
| 354 | - } else { |
|
| 355 | - $sub_line_item->set_unit_price($sign * $price->amount()); |
|
| 356 | - } |
|
| 357 | - $running_total_for_ticket += $price_total; |
|
| 358 | - $line_item->add_child_line_item($sub_line_item); |
|
| 359 | - } |
|
| 360 | - return $line_item; |
|
| 361 | - } |
|
| 362 | - |
|
| 363 | - |
|
| 364 | - /** |
|
| 365 | - * Adds the specified item under the pre-tax-sub-total line item. Automatically |
|
| 366 | - * re-calculates the line item totals and updates the related transaction. But |
|
| 367 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 368 | - * should probably change because of this). |
|
| 369 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 370 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 371 | - * |
|
| 372 | - * @param EE_Line_Item $total_line_item |
|
| 373 | - * @param EE_Line_Item $item to be added |
|
| 374 | - * @return boolean |
|
| 375 | - * @throws EE_Error |
|
| 376 | - * @throws InvalidArgumentException |
|
| 377 | - * @throws InvalidDataTypeException |
|
| 378 | - * @throws InvalidInterfaceException |
|
| 379 | - * @throws ReflectionException |
|
| 380 | - */ |
|
| 381 | - public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item) |
|
| 382 | - { |
|
| 383 | - $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item); |
|
| 384 | - if ($pre_tax_subtotal instanceof EE_Line_Item) { |
|
| 385 | - $success = $pre_tax_subtotal->add_child_line_item($item); |
|
| 386 | - } else { |
|
| 387 | - return false; |
|
| 388 | - } |
|
| 389 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 390 | - return $success; |
|
| 391 | - } |
|
| 392 | - |
|
| 393 | - |
|
| 394 | - /** |
|
| 395 | - * cancels an existing ticket line item, |
|
| 396 | - * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item. |
|
| 397 | - * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 398 | - * |
|
| 399 | - * @param EE_Line_Item $ticket_line_item |
|
| 400 | - * @param int $qty |
|
| 401 | - * @return bool success |
|
| 402 | - * @throws EE_Error |
|
| 403 | - * @throws InvalidArgumentException |
|
| 404 | - * @throws InvalidDataTypeException |
|
| 405 | - * @throws InvalidInterfaceException |
|
| 406 | - * @throws ReflectionException |
|
| 407 | - */ |
|
| 408 | - public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 409 | - { |
|
| 410 | - // validate incoming line_item |
|
| 411 | - if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 412 | - throw new EE_Error( |
|
| 413 | - sprintf( |
|
| 414 | - esc_html__( |
|
| 415 | - 'The supplied line item must have an Object Type of "Ticket", not %1$s.', |
|
| 416 | - 'event_espresso' |
|
| 417 | - ), |
|
| 418 | - $ticket_line_item->type() |
|
| 419 | - ) |
|
| 420 | - ); |
|
| 421 | - } |
|
| 422 | - if ($ticket_line_item->quantity() < $qty) { |
|
| 423 | - throw new EE_Error( |
|
| 424 | - sprintf( |
|
| 425 | - esc_html__( |
|
| 426 | - 'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', |
|
| 427 | - 'event_espresso' |
|
| 428 | - ), |
|
| 429 | - $qty, |
|
| 430 | - $ticket_line_item->quantity() |
|
| 431 | - ) |
|
| 432 | - ); |
|
| 433 | - } |
|
| 434 | - // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this |
|
| 435 | - $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty); |
|
| 436 | - foreach ($ticket_line_item->children() as $child_line_item) { |
|
| 437 | - if ($child_line_item->is_sub_line_item() |
|
| 438 | - && ! $child_line_item->is_percent() |
|
| 439 | - && ! $child_line_item->is_cancellation() |
|
| 440 | - ) { |
|
| 441 | - $child_line_item->set_quantity($child_line_item->quantity() - $qty); |
|
| 442 | - } |
|
| 443 | - } |
|
| 444 | - // get cancellation sub line item |
|
| 445 | - $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 446 | - $ticket_line_item, |
|
| 447 | - EEM_Line_Item::type_cancellation |
|
| 448 | - ); |
|
| 449 | - $cancellation_line_item = reset($cancellation_line_item); |
|
| 450 | - // verify that this ticket was indeed previously cancelled |
|
| 451 | - if ($cancellation_line_item instanceof EE_Line_Item) { |
|
| 452 | - // increment cancelled quantity |
|
| 453 | - $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty); |
|
| 454 | - } else { |
|
| 455 | - // create cancellation sub line item |
|
| 456 | - $cancellation_line_item = EE_Line_Item::new_instance(array( |
|
| 457 | - 'LIN_name' => esc_html__('Cancellation', 'event_espresso'), |
|
| 458 | - 'LIN_desc' => sprintf( |
|
| 459 | - esc_html_x( |
|
| 460 | - 'Cancelled %1$s : %2$s', |
|
| 461 | - 'Cancelled Ticket Name : 2015-01-01 11:11', |
|
| 462 | - 'event_espresso' |
|
| 463 | - ), |
|
| 464 | - $ticket_line_item->name(), |
|
| 465 | - current_time(get_option('date_format') . ' ' . get_option('time_format')) |
|
| 466 | - ), |
|
| 467 | - 'LIN_unit_price' => 0, // $ticket_line_item->unit_price() |
|
| 468 | - 'LIN_quantity' => $qty, |
|
| 469 | - 'LIN_is_taxable' => $ticket_line_item->is_taxable(), |
|
| 470 | - 'LIN_order' => count($ticket_line_item->children()), |
|
| 471 | - 'LIN_total' => 0, // $ticket_line_item->unit_price() |
|
| 472 | - 'LIN_type' => EEM_Line_Item::type_cancellation, |
|
| 473 | - )); |
|
| 474 | - $ticket_line_item->add_child_line_item($cancellation_line_item); |
|
| 475 | - } |
|
| 476 | - if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 477 | - // decrement parent line item quantity |
|
| 478 | - $event_line_item = $ticket_line_item->parent(); |
|
| 479 | - if ($event_line_item instanceof EE_Line_Item |
|
| 480 | - && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT |
|
| 481 | - ) { |
|
| 482 | - $event_line_item->set_quantity($event_line_item->quantity() - $qty); |
|
| 483 | - $event_line_item->save(); |
|
| 484 | - } |
|
| 485 | - EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 486 | - return true; |
|
| 487 | - } |
|
| 488 | - return false; |
|
| 489 | - } |
|
| 490 | - |
|
| 491 | - |
|
| 492 | - /** |
|
| 493 | - * reinstates (un-cancels?) a previously canceled ticket line item, |
|
| 494 | - * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item. |
|
| 495 | - * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 496 | - * |
|
| 497 | - * @param EE_Line_Item $ticket_line_item |
|
| 498 | - * @param int $qty |
|
| 499 | - * @return bool success |
|
| 500 | - * @throws EE_Error |
|
| 501 | - * @throws InvalidArgumentException |
|
| 502 | - * @throws InvalidDataTypeException |
|
| 503 | - * @throws InvalidInterfaceException |
|
| 504 | - * @throws ReflectionException |
|
| 505 | - */ |
|
| 506 | - public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 507 | - { |
|
| 508 | - // validate incoming line_item |
|
| 509 | - if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 510 | - throw new EE_Error( |
|
| 511 | - sprintf( |
|
| 512 | - esc_html__( |
|
| 513 | - 'The supplied line item must have an Object Type of "Ticket", not %1$s.', |
|
| 514 | - 'event_espresso' |
|
| 515 | - ), |
|
| 516 | - $ticket_line_item->type() |
|
| 517 | - ) |
|
| 518 | - ); |
|
| 519 | - } |
|
| 520 | - // get cancellation sub line item |
|
| 521 | - $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 522 | - $ticket_line_item, |
|
| 523 | - EEM_Line_Item::type_cancellation |
|
| 524 | - ); |
|
| 525 | - $cancellation_line_item = reset($cancellation_line_item); |
|
| 526 | - // verify that this ticket was indeed previously cancelled |
|
| 527 | - if (! $cancellation_line_item instanceof EE_Line_Item) { |
|
| 528 | - return false; |
|
| 529 | - } |
|
| 530 | - if ($cancellation_line_item->quantity() > $qty) { |
|
| 531 | - // decrement cancelled quantity |
|
| 532 | - $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 533 | - } elseif ($cancellation_line_item->quantity() === $qty) { |
|
| 534 | - // decrement cancelled quantity in case anyone still has the object kicking around |
|
| 535 | - $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 536 | - // delete because quantity will end up as 0 |
|
| 537 | - $cancellation_line_item->delete(); |
|
| 538 | - // and attempt to destroy the object, |
|
| 539 | - // even though PHP won't actually destroy it until it needs the memory |
|
| 540 | - unset($cancellation_line_item); |
|
| 541 | - } else { |
|
| 542 | - // what ?!?! negative quantity ?!?! |
|
| 543 | - throw new EE_Error( |
|
| 544 | - sprintf( |
|
| 545 | - esc_html__( |
|
| 546 | - 'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.', |
|
| 547 | - 'event_espresso' |
|
| 548 | - ), |
|
| 549 | - $qty, |
|
| 550 | - $cancellation_line_item->quantity() |
|
| 551 | - ) |
|
| 552 | - ); |
|
| 553 | - } |
|
| 554 | - // increment ticket quantity |
|
| 555 | - $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty); |
|
| 556 | - if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 557 | - // increment parent line item quantity |
|
| 558 | - $event_line_item = $ticket_line_item->parent(); |
|
| 559 | - if ($event_line_item instanceof EE_Line_Item |
|
| 560 | - && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT |
|
| 561 | - ) { |
|
| 562 | - $event_line_item->set_quantity($event_line_item->quantity() + $qty); |
|
| 563 | - } |
|
| 564 | - EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 565 | - return true; |
|
| 566 | - } |
|
| 567 | - return false; |
|
| 568 | - } |
|
| 569 | - |
|
| 570 | - |
|
| 571 | - /** |
|
| 572 | - * calls EEH_Line_Item::find_transaction_grand_total_for_line_item() |
|
| 573 | - * then EE_Line_Item::recalculate_total_including_taxes() on the result |
|
| 574 | - * |
|
| 575 | - * @param EE_Line_Item $line_item |
|
| 576 | - * @return float |
|
| 577 | - * @throws EE_Error |
|
| 578 | - * @throws InvalidArgumentException |
|
| 579 | - * @throws InvalidDataTypeException |
|
| 580 | - * @throws InvalidInterfaceException |
|
| 581 | - * @throws ReflectionException |
|
| 582 | - */ |
|
| 583 | - public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item) |
|
| 584 | - { |
|
| 585 | - $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item); |
|
| 586 | - return $grand_total_line_item->recalculate_total_including_taxes(); |
|
| 587 | - } |
|
| 588 | - |
|
| 589 | - |
|
| 590 | - /** |
|
| 591 | - * Gets the line item which contains the subtotal of all the items |
|
| 592 | - * |
|
| 593 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 594 | - * @return EE_Line_Item |
|
| 595 | - * @throws EE_Error |
|
| 596 | - * @throws InvalidArgumentException |
|
| 597 | - * @throws InvalidDataTypeException |
|
| 598 | - * @throws InvalidInterfaceException |
|
| 599 | - * @throws ReflectionException |
|
| 600 | - */ |
|
| 601 | - public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item) |
|
| 602 | - { |
|
| 603 | - $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal'); |
|
| 604 | - return $pre_tax_subtotal instanceof EE_Line_Item |
|
| 605 | - ? $pre_tax_subtotal |
|
| 606 | - : self::create_pre_tax_subtotal($total_line_item); |
|
| 607 | - } |
|
| 608 | - |
|
| 609 | - |
|
| 610 | - /** |
|
| 611 | - * Gets the line item for the taxes subtotal |
|
| 612 | - * |
|
| 613 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 614 | - * @return EE_Line_Item |
|
| 615 | - * @throws EE_Error |
|
| 616 | - * @throws InvalidArgumentException |
|
| 617 | - * @throws InvalidDataTypeException |
|
| 618 | - * @throws InvalidInterfaceException |
|
| 619 | - * @throws ReflectionException |
|
| 620 | - */ |
|
| 621 | - public static function get_taxes_subtotal(EE_Line_Item $total_line_item) |
|
| 622 | - { |
|
| 623 | - $taxes = $total_line_item->get_child_line_item('taxes'); |
|
| 624 | - return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item); |
|
| 625 | - } |
|
| 626 | - |
|
| 627 | - |
|
| 628 | - /** |
|
| 629 | - * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object |
|
| 630 | - * |
|
| 631 | - * @param EE_Line_Item $line_item |
|
| 632 | - * @param EE_Transaction $transaction |
|
| 633 | - * @return void |
|
| 634 | - * @throws EE_Error |
|
| 635 | - * @throws InvalidArgumentException |
|
| 636 | - * @throws InvalidDataTypeException |
|
| 637 | - * @throws InvalidInterfaceException |
|
| 638 | - * @throws ReflectionException |
|
| 639 | - */ |
|
| 640 | - public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null) |
|
| 641 | - { |
|
| 642 | - if ($transaction) { |
|
| 643 | - /** @type EEM_Transaction $EEM_Transaction */ |
|
| 644 | - $EEM_Transaction = EE_Registry::instance()->load_model('Transaction'); |
|
| 645 | - $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction); |
|
| 646 | - $line_item->set_TXN_ID($TXN_ID); |
|
| 647 | - } |
|
| 648 | - } |
|
| 649 | - |
|
| 650 | - |
|
| 651 | - /** |
|
| 652 | - * Creates a new default total line item for the transaction, |
|
| 653 | - * and its tickets subtotal and taxes subtotal line items (and adds the |
|
| 654 | - * existing taxes as children of the taxes subtotal line item) |
|
| 655 | - * |
|
| 656 | - * @param EE_Transaction $transaction |
|
| 657 | - * @return EE_Line_Item of type total |
|
| 658 | - * @throws EE_Error |
|
| 659 | - * @throws InvalidArgumentException |
|
| 660 | - * @throws InvalidDataTypeException |
|
| 661 | - * @throws InvalidInterfaceException |
|
| 662 | - * @throws ReflectionException |
|
| 663 | - */ |
|
| 664 | - public static function create_total_line_item($transaction = null) |
|
| 665 | - { |
|
| 666 | - $total_line_item = EE_Line_Item::new_instance(array( |
|
| 667 | - 'LIN_code' => 'total', |
|
| 668 | - 'LIN_name' => esc_html__('Grand Total', 'event_espresso'), |
|
| 669 | - 'LIN_type' => EEM_Line_Item::type_total, |
|
| 670 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION, |
|
| 671 | - )); |
|
| 672 | - $total_line_item = apply_filters( |
|
| 673 | - 'FHEE__EEH_Line_Item__create_total_line_item__total_line_item', |
|
| 674 | - $total_line_item |
|
| 675 | - ); |
|
| 676 | - self::set_TXN_ID($total_line_item, $transaction); |
|
| 677 | - self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 678 | - self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 679 | - return $total_line_item; |
|
| 680 | - } |
|
| 681 | - |
|
| 682 | - |
|
| 683 | - /** |
|
| 684 | - * Creates a default items subtotal line item |
|
| 685 | - * |
|
| 686 | - * @param EE_Line_Item $total_line_item |
|
| 687 | - * @param EE_Transaction $transaction |
|
| 688 | - * @return EE_Line_Item |
|
| 689 | - * @throws EE_Error |
|
| 690 | - * @throws InvalidArgumentException |
|
| 691 | - * @throws InvalidDataTypeException |
|
| 692 | - * @throws InvalidInterfaceException |
|
| 693 | - * @throws ReflectionException |
|
| 694 | - */ |
|
| 695 | - protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 696 | - { |
|
| 697 | - $pre_tax_line_item = EE_Line_Item::new_instance(array( |
|
| 698 | - 'LIN_code' => 'pre-tax-subtotal', |
|
| 699 | - 'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'), |
|
| 700 | - 'LIN_type' => EEM_Line_Item::type_sub_total, |
|
| 701 | - )); |
|
| 702 | - $pre_tax_line_item = apply_filters( |
|
| 703 | - 'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item', |
|
| 704 | - $pre_tax_line_item |
|
| 705 | - ); |
|
| 706 | - self::set_TXN_ID($pre_tax_line_item, $transaction); |
|
| 707 | - $total_line_item->add_child_line_item($pre_tax_line_item); |
|
| 708 | - self::create_event_subtotal($pre_tax_line_item, $transaction); |
|
| 709 | - return $pre_tax_line_item; |
|
| 710 | - } |
|
| 711 | - |
|
| 712 | - |
|
| 713 | - /** |
|
| 714 | - * Creates a line item for the taxes subtotal and finds all the tax prices |
|
| 715 | - * and applies taxes to it |
|
| 716 | - * |
|
| 717 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 718 | - * @param EE_Transaction $transaction |
|
| 719 | - * @return EE_Line_Item |
|
| 720 | - * @throws EE_Error |
|
| 721 | - * @throws InvalidArgumentException |
|
| 722 | - * @throws InvalidDataTypeException |
|
| 723 | - * @throws InvalidInterfaceException |
|
| 724 | - * @throws ReflectionException |
|
| 725 | - */ |
|
| 726 | - protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 727 | - { |
|
| 728 | - $tax_line_item = EE_Line_Item::new_instance(array( |
|
| 729 | - 'LIN_code' => 'taxes', |
|
| 730 | - 'LIN_name' => esc_html__('Taxes', 'event_espresso'), |
|
| 731 | - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, |
|
| 732 | - 'LIN_order' => 1000,// this should always come last |
|
| 733 | - )); |
|
| 734 | - $tax_line_item = apply_filters( |
|
| 735 | - 'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item', |
|
| 736 | - $tax_line_item |
|
| 737 | - ); |
|
| 738 | - self::set_TXN_ID($tax_line_item, $transaction); |
|
| 739 | - $total_line_item->add_child_line_item($tax_line_item); |
|
| 740 | - // and lastly, add the actual taxes |
|
| 741 | - self::apply_taxes($total_line_item); |
|
| 742 | - return $tax_line_item; |
|
| 743 | - } |
|
| 744 | - |
|
| 745 | - |
|
| 746 | - /** |
|
| 747 | - * Creates a default items subtotal line item |
|
| 748 | - * |
|
| 749 | - * @param EE_Line_Item $pre_tax_line_item |
|
| 750 | - * @param EE_Transaction $transaction |
|
| 751 | - * @param EE_Event $event |
|
| 752 | - * @return EE_Line_Item |
|
| 753 | - * @throws EE_Error |
|
| 754 | - * @throws InvalidArgumentException |
|
| 755 | - * @throws InvalidDataTypeException |
|
| 756 | - * @throws InvalidInterfaceException |
|
| 757 | - * @throws ReflectionException |
|
| 758 | - */ |
|
| 759 | - public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null) |
|
| 760 | - { |
|
| 761 | - $event_line_item = EE_Line_Item::new_instance(array( |
|
| 762 | - 'LIN_code' => self::get_event_code($event), |
|
| 763 | - 'LIN_name' => self::get_event_name($event), |
|
| 764 | - 'LIN_desc' => self::get_event_desc($event), |
|
| 765 | - 'LIN_type' => EEM_Line_Item::type_sub_total, |
|
| 766 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT, |
|
| 767 | - 'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0, |
|
| 768 | - )); |
|
| 769 | - $event_line_item = apply_filters( |
|
| 770 | - 'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item', |
|
| 771 | - $event_line_item |
|
| 772 | - ); |
|
| 773 | - self::set_TXN_ID($event_line_item, $transaction); |
|
| 774 | - $pre_tax_line_item->add_child_line_item($event_line_item); |
|
| 775 | - return $event_line_item; |
|
| 776 | - } |
|
| 777 | - |
|
| 778 | - |
|
| 779 | - /** |
|
| 780 | - * Gets what the event ticket's code SHOULD be |
|
| 781 | - * |
|
| 782 | - * @param EE_Event $event |
|
| 783 | - * @return string |
|
| 784 | - * @throws EE_Error |
|
| 785 | - */ |
|
| 786 | - public static function get_event_code($event) |
|
| 787 | - { |
|
| 788 | - return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 789 | - } |
|
| 790 | - |
|
| 791 | - |
|
| 792 | - /** |
|
| 793 | - * Gets the event name |
|
| 794 | - * |
|
| 795 | - * @param EE_Event $event |
|
| 796 | - * @return string |
|
| 797 | - * @throws EE_Error |
|
| 798 | - */ |
|
| 799 | - public static function get_event_name($event) |
|
| 800 | - { |
|
| 801 | - return $event instanceof EE_Event |
|
| 802 | - ? mb_substr($event->name(), 0, 245) |
|
| 803 | - : esc_html__('Event', 'event_espresso'); |
|
| 804 | - } |
|
| 805 | - |
|
| 806 | - |
|
| 807 | - /** |
|
| 808 | - * Gets the event excerpt |
|
| 809 | - * |
|
| 810 | - * @param EE_Event $event |
|
| 811 | - * @return string |
|
| 812 | - * @throws EE_Error |
|
| 813 | - */ |
|
| 814 | - public static function get_event_desc($event) |
|
| 815 | - { |
|
| 816 | - return $event instanceof EE_Event ? $event->short_description() : ''; |
|
| 817 | - } |
|
| 818 | - |
|
| 819 | - |
|
| 820 | - /** |
|
| 821 | - * Given the grand total line item and a ticket, finds the event sub-total |
|
| 822 | - * line item the ticket's purchase should be added onto |
|
| 823 | - * |
|
| 824 | - * @access public |
|
| 825 | - * @param EE_Line_Item $grand_total the grand total line item |
|
| 826 | - * @param EE_Ticket $ticket |
|
| 827 | - * @return EE_Line_Item |
|
| 828 | - * @throws EE_Error |
|
| 829 | - * @throws InvalidArgumentException |
|
| 830 | - * @throws InvalidDataTypeException |
|
| 831 | - * @throws InvalidInterfaceException |
|
| 832 | - * @throws ReflectionException |
|
| 833 | - */ |
|
| 834 | - public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket) |
|
| 835 | - { |
|
| 836 | - $first_datetime = $ticket->first_datetime(); |
|
| 837 | - if (! $first_datetime instanceof EE_Datetime) { |
|
| 838 | - throw new EE_Error( |
|
| 839 | - sprintf( |
|
| 840 | - __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), |
|
| 841 | - $ticket->ID() |
|
| 842 | - ) |
|
| 843 | - ); |
|
| 844 | - } |
|
| 845 | - $event = $first_datetime->event(); |
|
| 846 | - if (! $event instanceof EE_Event) { |
|
| 847 | - throw new EE_Error( |
|
| 848 | - sprintf( |
|
| 849 | - esc_html__( |
|
| 850 | - 'The supplied ticket (ID %d) has no event data associated with it.', |
|
| 851 | - 'event_espresso' |
|
| 852 | - ), |
|
| 853 | - $ticket->ID() |
|
| 854 | - ) |
|
| 855 | - ); |
|
| 856 | - } |
|
| 857 | - $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event); |
|
| 858 | - if (! $events_sub_total instanceof EE_Line_Item) { |
|
| 859 | - throw new EE_Error( |
|
| 860 | - sprintf( |
|
| 861 | - esc_html__( |
|
| 862 | - 'There is no events sub-total for ticket %s on total line item %d', |
|
| 863 | - 'event_espresso' |
|
| 864 | - ), |
|
| 865 | - $ticket->ID(), |
|
| 866 | - $grand_total->ID() |
|
| 867 | - ) |
|
| 868 | - ); |
|
| 869 | - } |
|
| 870 | - return $events_sub_total; |
|
| 871 | - } |
|
| 872 | - |
|
| 873 | - |
|
| 874 | - /** |
|
| 875 | - * Gets the event line item |
|
| 876 | - * |
|
| 877 | - * @param EE_Line_Item $grand_total |
|
| 878 | - * @param EE_Event $event |
|
| 879 | - * @return EE_Line_Item for the event subtotal which is a child of $grand_total |
|
| 880 | - * @throws EE_Error |
|
| 881 | - * @throws InvalidArgumentException |
|
| 882 | - * @throws InvalidDataTypeException |
|
| 883 | - * @throws InvalidInterfaceException |
|
| 884 | - * @throws ReflectionException |
|
| 885 | - */ |
|
| 886 | - public static function get_event_line_item(EE_Line_Item $grand_total, $event) |
|
| 887 | - { |
|
| 888 | - /** @type EE_Event $event */ |
|
| 889 | - $event = EEM_Event::instance()->ensure_is_obj($event, true); |
|
| 890 | - $event_line_item = null; |
|
| 891 | - $found = false; |
|
| 892 | - foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) { |
|
| 893 | - // default event subtotal, we should only ever find this the first time this method is called |
|
| 894 | - if (! $event_line_item->OBJ_ID()) { |
|
| 895 | - // let's use this! but first... set the event details |
|
| 896 | - EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 897 | - $found = true; |
|
| 898 | - break; |
|
| 899 | - } |
|
| 900 | - if ($event_line_item->OBJ_ID() === $event->ID()) { |
|
| 901 | - // found existing line item for this event in the cart, so break out of loop and use this one |
|
| 902 | - $found = true; |
|
| 903 | - break; |
|
| 904 | - } |
|
| 905 | - } |
|
| 906 | - if (! $found) { |
|
| 907 | - // there is no event sub-total yet, so add it |
|
| 908 | - $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total); |
|
| 909 | - // create a new "event" subtotal below that |
|
| 910 | - $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event); |
|
| 911 | - // and set the event details |
|
| 912 | - EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 913 | - } |
|
| 914 | - return $event_line_item; |
|
| 915 | - } |
|
| 916 | - |
|
| 917 | - |
|
| 918 | - /** |
|
| 919 | - * Creates a default items subtotal line item |
|
| 920 | - * |
|
| 921 | - * @param EE_Line_Item $event_line_item |
|
| 922 | - * @param EE_Event $event |
|
| 923 | - * @param EE_Transaction $transaction |
|
| 924 | - * @return void |
|
| 925 | - * @throws EE_Error |
|
| 926 | - * @throws InvalidArgumentException |
|
| 927 | - * @throws InvalidDataTypeException |
|
| 928 | - * @throws InvalidInterfaceException |
|
| 929 | - * @throws ReflectionException |
|
| 930 | - */ |
|
| 931 | - public static function set_event_subtotal_details( |
|
| 932 | - EE_Line_Item $event_line_item, |
|
| 933 | - EE_Event $event, |
|
| 934 | - $transaction = null |
|
| 935 | - ) { |
|
| 936 | - if ($event instanceof EE_Event) { |
|
| 937 | - $event_line_item->set_code(self::get_event_code($event)); |
|
| 938 | - $event_line_item->set_name(self::get_event_name($event)); |
|
| 939 | - $event_line_item->set_desc(self::get_event_desc($event)); |
|
| 940 | - $event_line_item->set_OBJ_ID($event->ID()); |
|
| 941 | - } |
|
| 942 | - self::set_TXN_ID($event_line_item, $transaction); |
|
| 943 | - } |
|
| 944 | - |
|
| 945 | - |
|
| 946 | - /** |
|
| 947 | - * Finds what taxes should apply, adds them as tax line items under the taxes sub-total, |
|
| 948 | - * and recalculates the taxes sub-total and the grand total. Resets the taxes, so |
|
| 949 | - * any old taxes are removed |
|
| 950 | - * |
|
| 951 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 952 | - * @param bool $update_txn_status |
|
| 953 | - * @return bool |
|
| 954 | - * @throws EE_Error |
|
| 955 | - * @throws InvalidArgumentException |
|
| 956 | - * @throws InvalidDataTypeException |
|
| 957 | - * @throws InvalidInterfaceException |
|
| 958 | - * @throws ReflectionException |
|
| 959 | - * @throws RuntimeException |
|
| 960 | - */ |
|
| 961 | - public static function apply_taxes(EE_Line_Item $total_line_item, $update_txn_status = false) |
|
| 962 | - { |
|
| 963 | - /** @type EEM_Price $EEM_Price */ |
|
| 964 | - $EEM_Price = EE_Registry::instance()->load_model('Price'); |
|
| 965 | - // get array of taxes via Price Model |
|
| 966 | - $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes(); |
|
| 967 | - ksort($ordered_taxes); |
|
| 968 | - $taxes_line_item = self::get_taxes_subtotal($total_line_item); |
|
| 969 | - // just to be safe, remove its old tax line items |
|
| 970 | - $deleted = $taxes_line_item->delete_children_line_items(); |
|
| 971 | - $updates = false; |
|
| 972 | - // loop thru taxes |
|
| 973 | - foreach ($ordered_taxes as $order => $taxes) { |
|
| 974 | - foreach ($taxes as $tax) { |
|
| 975 | - if ($tax instanceof EE_Price) { |
|
| 976 | - $tax_line_item = EE_Line_Item::new_instance( |
|
| 977 | - array( |
|
| 978 | - 'LIN_name' => $tax->name(), |
|
| 979 | - 'LIN_desc' => $tax->desc(), |
|
| 980 | - 'LIN_percent' => $tax->amount(), |
|
| 981 | - 'LIN_is_taxable' => false, |
|
| 982 | - 'LIN_order' => $order, |
|
| 983 | - 'LIN_total' => 0, |
|
| 984 | - 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 985 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PRICE, |
|
| 986 | - 'OBJ_ID' => $tax->ID(), |
|
| 987 | - ) |
|
| 988 | - ); |
|
| 989 | - $tax_line_item = apply_filters( |
|
| 990 | - 'FHEE__EEH_Line_Item__apply_taxes__tax_line_item', |
|
| 991 | - $tax_line_item |
|
| 992 | - ); |
|
| 993 | - $updates = $taxes_line_item->add_child_line_item($tax_line_item) ? |
|
| 994 | - true : |
|
| 995 | - $updates; |
|
| 996 | - } |
|
| 997 | - } |
|
| 998 | - } |
|
| 999 | - // only recalculate totals if something changed |
|
| 1000 | - if ($deleted || $updates) { |
|
| 1001 | - $total_line_item->recalculate_total_including_taxes($update_txn_status); |
|
| 1002 | - return true; |
|
| 1003 | - } |
|
| 1004 | - return false; |
|
| 1005 | - } |
|
| 1006 | - |
|
| 1007 | - |
|
| 1008 | - /** |
|
| 1009 | - * Ensures that taxes have been applied to the order, if not applies them. |
|
| 1010 | - * Returns the total amount of tax |
|
| 1011 | - * |
|
| 1012 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 1013 | - * @return float |
|
| 1014 | - * @throws EE_Error |
|
| 1015 | - * @throws InvalidArgumentException |
|
| 1016 | - * @throws InvalidDataTypeException |
|
| 1017 | - * @throws InvalidInterfaceException |
|
| 1018 | - * @throws ReflectionException |
|
| 1019 | - */ |
|
| 1020 | - public static function ensure_taxes_applied($total_line_item) |
|
| 1021 | - { |
|
| 1022 | - $taxes_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 1023 | - if (! $taxes_subtotal->children()) { |
|
| 1024 | - self::apply_taxes($total_line_item); |
|
| 1025 | - } |
|
| 1026 | - return $taxes_subtotal->total(); |
|
| 1027 | - } |
|
| 1028 | - |
|
| 1029 | - |
|
| 1030 | - /** |
|
| 1031 | - * Deletes ALL children of the passed line item |
|
| 1032 | - * |
|
| 1033 | - * @param EE_Line_Item $parent_line_item |
|
| 1034 | - * @return bool |
|
| 1035 | - * @throws EE_Error |
|
| 1036 | - * @throws InvalidArgumentException |
|
| 1037 | - * @throws InvalidDataTypeException |
|
| 1038 | - * @throws InvalidInterfaceException |
|
| 1039 | - * @throws ReflectionException |
|
| 1040 | - */ |
|
| 1041 | - public static function delete_all_child_items(EE_Line_Item $parent_line_item) |
|
| 1042 | - { |
|
| 1043 | - $deleted = 0; |
|
| 1044 | - foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1045 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1046 | - $deleted += EEH_Line_Item::delete_all_child_items($child_line_item); |
|
| 1047 | - if ($child_line_item->ID()) { |
|
| 1048 | - $child_line_item->delete(); |
|
| 1049 | - unset($child_line_item); |
|
| 1050 | - } else { |
|
| 1051 | - $parent_line_item->delete_child_line_item($child_line_item->code()); |
|
| 1052 | - } |
|
| 1053 | - $deleted++; |
|
| 1054 | - } |
|
| 1055 | - } |
|
| 1056 | - return $deleted; |
|
| 1057 | - } |
|
| 1058 | - |
|
| 1059 | - |
|
| 1060 | - /** |
|
| 1061 | - * Deletes the line items as indicated by the line item code(s) provided, |
|
| 1062 | - * regardless of where they're found in the line item tree. Automatically |
|
| 1063 | - * re-calculates the line item totals and updates the related transaction. But |
|
| 1064 | - * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 1065 | - * should probably change because of this). |
|
| 1066 | - * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 1067 | - * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 1068 | - * |
|
| 1069 | - * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 1070 | - * @param array|bool|string $line_item_codes |
|
| 1071 | - * @return int number of items successfully removed |
|
| 1072 | - * @throws EE_Error |
|
| 1073 | - */ |
|
| 1074 | - public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false) |
|
| 1075 | - { |
|
| 1076 | - |
|
| 1077 | - if ($total_line_item->type() !== EEM_Line_Item::type_total) { |
|
| 1078 | - EE_Error::doing_it_wrong( |
|
| 1079 | - 'EEH_Line_Item::delete_items', |
|
| 1080 | - esc_html__( |
|
| 1081 | - 'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly', |
|
| 1082 | - 'event_espresso' |
|
| 1083 | - ), |
|
| 1084 | - '4.6.18' |
|
| 1085 | - ); |
|
| 1086 | - } |
|
| 1087 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 1088 | - |
|
| 1089 | - // check if only a single line_item_id was passed |
|
| 1090 | - if (! empty($line_item_codes) && ! is_array($line_item_codes)) { |
|
| 1091 | - // place single line_item_id in an array to appear as multiple line_item_ids |
|
| 1092 | - $line_item_codes = array($line_item_codes); |
|
| 1093 | - } |
|
| 1094 | - $removals = 0; |
|
| 1095 | - // cycle thru line_item_ids |
|
| 1096 | - foreach ($line_item_codes as $line_item_id) { |
|
| 1097 | - $removals += $total_line_item->delete_child_line_item($line_item_id); |
|
| 1098 | - } |
|
| 1099 | - |
|
| 1100 | - if ($removals > 0) { |
|
| 1101 | - $total_line_item->recalculate_taxes_and_tax_total(); |
|
| 1102 | - return $removals; |
|
| 1103 | - } else { |
|
| 1104 | - return false; |
|
| 1105 | - } |
|
| 1106 | - } |
|
| 1107 | - |
|
| 1108 | - |
|
| 1109 | - /** |
|
| 1110 | - * Overwrites the previous tax by clearing out the old taxes, and creates a new |
|
| 1111 | - * tax and updates the total line item accordingly |
|
| 1112 | - * |
|
| 1113 | - * @param EE_Line_Item $total_line_item |
|
| 1114 | - * @param float $amount |
|
| 1115 | - * @param string $name |
|
| 1116 | - * @param string $description |
|
| 1117 | - * @param string $code |
|
| 1118 | - * @param boolean $add_to_existing_line_item |
|
| 1119 | - * if true, and a duplicate line item with the same code is found, |
|
| 1120 | - * $amount will be added onto it; otherwise will simply set the taxes to match $amount |
|
| 1121 | - * @return EE_Line_Item the new tax line item created |
|
| 1122 | - * @throws EE_Error |
|
| 1123 | - * @throws InvalidArgumentException |
|
| 1124 | - * @throws InvalidDataTypeException |
|
| 1125 | - * @throws InvalidInterfaceException |
|
| 1126 | - * @throws ReflectionException |
|
| 1127 | - */ |
|
| 1128 | - public static function set_total_tax_to( |
|
| 1129 | - EE_Line_Item $total_line_item, |
|
| 1130 | - $amount, |
|
| 1131 | - $name = null, |
|
| 1132 | - $description = null, |
|
| 1133 | - $code = null, |
|
| 1134 | - $add_to_existing_line_item = false |
|
| 1135 | - ) { |
|
| 1136 | - $tax_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 1137 | - $taxable_total = $total_line_item->taxable_total(); |
|
| 1138 | - |
|
| 1139 | - if ($add_to_existing_line_item) { |
|
| 1140 | - $new_tax = $tax_subtotal->get_child_line_item($code); |
|
| 1141 | - EEM_Line_Item::instance()->delete( |
|
| 1142 | - array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID())) |
|
| 1143 | - ); |
|
| 1144 | - } else { |
|
| 1145 | - $new_tax = null; |
|
| 1146 | - $tax_subtotal->delete_children_line_items(); |
|
| 1147 | - } |
|
| 1148 | - if ($new_tax) { |
|
| 1149 | - $new_tax->set_total($new_tax->total() + $amount); |
|
| 1150 | - $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0); |
|
| 1151 | - } else { |
|
| 1152 | - // no existing tax item. Create it |
|
| 1153 | - $new_tax = EE_Line_Item::new_instance(array( |
|
| 1154 | - 'TXN_ID' => $total_line_item->TXN_ID(), |
|
| 1155 | - 'LIN_name' => $name ? $name : esc_html__('Tax', 'event_espresso'), |
|
| 1156 | - 'LIN_desc' => $description ? $description : '', |
|
| 1157 | - 'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0, |
|
| 1158 | - 'LIN_total' => $amount, |
|
| 1159 | - 'LIN_parent' => $tax_subtotal->ID(), |
|
| 1160 | - 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 1161 | - 'LIN_code' => $code, |
|
| 1162 | - )); |
|
| 1163 | - } |
|
| 1164 | - |
|
| 1165 | - $new_tax = apply_filters( |
|
| 1166 | - 'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal', |
|
| 1167 | - $new_tax, |
|
| 1168 | - $total_line_item |
|
| 1169 | - ); |
|
| 1170 | - $new_tax->save(); |
|
| 1171 | - $tax_subtotal->set_total($new_tax->total()); |
|
| 1172 | - $tax_subtotal->save(); |
|
| 1173 | - $total_line_item->recalculate_total_including_taxes(); |
|
| 1174 | - return $new_tax; |
|
| 1175 | - } |
|
| 1176 | - |
|
| 1177 | - |
|
| 1178 | - /** |
|
| 1179 | - * Makes all the line items which are children of $line_item taxable (or not). |
|
| 1180 | - * Does NOT save the line items |
|
| 1181 | - * |
|
| 1182 | - * @param EE_Line_Item $line_item |
|
| 1183 | - * @param boolean $taxable |
|
| 1184 | - * @param string $code_substring_for_whitelist if this string is part of the line item's code |
|
| 1185 | - * it will be whitelisted (ie, except from becoming taxable) |
|
| 1186 | - * @throws EE_Error |
|
| 1187 | - */ |
|
| 1188 | - public static function set_line_items_taxable( |
|
| 1189 | - EE_Line_Item $line_item, |
|
| 1190 | - $taxable = true, |
|
| 1191 | - $code_substring_for_whitelist = null |
|
| 1192 | - ) { |
|
| 1193 | - $whitelisted = false; |
|
| 1194 | - if ($code_substring_for_whitelist !== null) { |
|
| 1195 | - $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false; |
|
| 1196 | - } |
|
| 1197 | - if (! $whitelisted && $line_item->is_line_item()) { |
|
| 1198 | - $line_item->set_is_taxable($taxable); |
|
| 1199 | - } |
|
| 1200 | - foreach ($line_item->children() as $child_line_item) { |
|
| 1201 | - EEH_Line_Item::set_line_items_taxable( |
|
| 1202 | - $child_line_item, |
|
| 1203 | - $taxable, |
|
| 1204 | - $code_substring_for_whitelist |
|
| 1205 | - ); |
|
| 1206 | - } |
|
| 1207 | - } |
|
| 1208 | - |
|
| 1209 | - |
|
| 1210 | - /** |
|
| 1211 | - * Gets all descendants that are event subtotals |
|
| 1212 | - * |
|
| 1213 | - * @uses EEH_Line_Item::get_subtotals_of_object_type() |
|
| 1214 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1215 | - * @return EE_Line_Item[] |
|
| 1216 | - * @throws EE_Error |
|
| 1217 | - */ |
|
| 1218 | - public static function get_event_subtotals(EE_Line_Item $parent_line_item) |
|
| 1219 | - { |
|
| 1220 | - return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT); |
|
| 1221 | - } |
|
| 1222 | - |
|
| 1223 | - |
|
| 1224 | - /** |
|
| 1225 | - * Gets all descendants subtotals that match the supplied object type |
|
| 1226 | - * |
|
| 1227 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1228 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1229 | - * @param string $obj_type |
|
| 1230 | - * @return EE_Line_Item[] |
|
| 1231 | - * @throws EE_Error |
|
| 1232 | - */ |
|
| 1233 | - public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1234 | - { |
|
| 1235 | - return self::_get_descendants_by_type_and_object_type( |
|
| 1236 | - $parent_line_item, |
|
| 1237 | - EEM_Line_Item::type_sub_total, |
|
| 1238 | - $obj_type |
|
| 1239 | - ); |
|
| 1240 | - } |
|
| 1241 | - |
|
| 1242 | - |
|
| 1243 | - /** |
|
| 1244 | - * Gets all descendants that are tickets |
|
| 1245 | - * |
|
| 1246 | - * @uses EEH_Line_Item::get_line_items_of_object_type() |
|
| 1247 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1248 | - * @return EE_Line_Item[] |
|
| 1249 | - * @throws EE_Error |
|
| 1250 | - */ |
|
| 1251 | - public static function get_ticket_line_items(EE_Line_Item $parent_line_item) |
|
| 1252 | - { |
|
| 1253 | - return self::get_line_items_of_object_type( |
|
| 1254 | - $parent_line_item, |
|
| 1255 | - EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1256 | - ); |
|
| 1257 | - } |
|
| 1258 | - |
|
| 1259 | - |
|
| 1260 | - /** |
|
| 1261 | - * Gets all descendants subtotals that match the supplied object type |
|
| 1262 | - * |
|
| 1263 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1264 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1265 | - * @param string $obj_type |
|
| 1266 | - * @return EE_Line_Item[] |
|
| 1267 | - * @throws EE_Error |
|
| 1268 | - */ |
|
| 1269 | - public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1270 | - { |
|
| 1271 | - return self::_get_descendants_by_type_and_object_type( |
|
| 1272 | - $parent_line_item, |
|
| 1273 | - EEM_Line_Item::type_line_item, |
|
| 1274 | - $obj_type |
|
| 1275 | - ); |
|
| 1276 | - } |
|
| 1277 | - |
|
| 1278 | - |
|
| 1279 | - /** |
|
| 1280 | - * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax' |
|
| 1281 | - * |
|
| 1282 | - * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1283 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1284 | - * @return EE_Line_Item[] |
|
| 1285 | - * @throws EE_Error |
|
| 1286 | - */ |
|
| 1287 | - public static function get_tax_descendants(EE_Line_Item $parent_line_item) |
|
| 1288 | - { |
|
| 1289 | - return EEH_Line_Item::get_descendants_of_type( |
|
| 1290 | - $parent_line_item, |
|
| 1291 | - EEM_Line_Item::type_tax |
|
| 1292 | - ); |
|
| 1293 | - } |
|
| 1294 | - |
|
| 1295 | - |
|
| 1296 | - /** |
|
| 1297 | - * Gets all the real items purchased which are children of this item |
|
| 1298 | - * |
|
| 1299 | - * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1300 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1301 | - * @return EE_Line_Item[] |
|
| 1302 | - * @throws EE_Error |
|
| 1303 | - */ |
|
| 1304 | - public static function get_line_item_descendants(EE_Line_Item $parent_line_item) |
|
| 1305 | - { |
|
| 1306 | - return EEH_Line_Item::get_descendants_of_type( |
|
| 1307 | - $parent_line_item, |
|
| 1308 | - EEM_Line_Item::type_line_item |
|
| 1309 | - ); |
|
| 1310 | - } |
|
| 1311 | - |
|
| 1312 | - |
|
| 1313 | - /** |
|
| 1314 | - * Gets all descendants of supplied line item that match the supplied line item type |
|
| 1315 | - * |
|
| 1316 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1317 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1318 | - * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1319 | - * @return EE_Line_Item[] |
|
| 1320 | - * @throws EE_Error |
|
| 1321 | - */ |
|
| 1322 | - public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type) |
|
| 1323 | - { |
|
| 1324 | - return self::_get_descendants_by_type_and_object_type( |
|
| 1325 | - $parent_line_item, |
|
| 1326 | - $line_item_type, |
|
| 1327 | - null |
|
| 1328 | - ); |
|
| 1329 | - } |
|
| 1330 | - |
|
| 1331 | - |
|
| 1332 | - /** |
|
| 1333 | - * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type |
|
| 1334 | - * as well |
|
| 1335 | - * |
|
| 1336 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1337 | - * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1338 | - * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when |
|
| 1339 | - * searching |
|
| 1340 | - * @return EE_Line_Item[] |
|
| 1341 | - * @throws EE_Error |
|
| 1342 | - */ |
|
| 1343 | - protected static function _get_descendants_by_type_and_object_type( |
|
| 1344 | - EE_Line_Item $parent_line_item, |
|
| 1345 | - $line_item_type, |
|
| 1346 | - $obj_type = null |
|
| 1347 | - ) { |
|
| 1348 | - $objects = array(); |
|
| 1349 | - foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1350 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1351 | - if ($child_line_item->type() === $line_item_type |
|
| 1352 | - && ( |
|
| 1353 | - $child_line_item->OBJ_type() === $obj_type || $obj_type === null |
|
| 1354 | - ) |
|
| 1355 | - ) { |
|
| 1356 | - $objects[] = $child_line_item; |
|
| 1357 | - } else { |
|
| 1358 | - // go-through-all-its children looking for more matches |
|
| 1359 | - $objects = array_merge( |
|
| 1360 | - $objects, |
|
| 1361 | - self::_get_descendants_by_type_and_object_type( |
|
| 1362 | - $child_line_item, |
|
| 1363 | - $line_item_type, |
|
| 1364 | - $obj_type |
|
| 1365 | - ) |
|
| 1366 | - ); |
|
| 1367 | - } |
|
| 1368 | - } |
|
| 1369 | - } |
|
| 1370 | - return $objects; |
|
| 1371 | - } |
|
| 1372 | - |
|
| 1373 | - |
|
| 1374 | - /** |
|
| 1375 | - * Gets all descendants subtotals that match the supplied object type |
|
| 1376 | - * |
|
| 1377 | - * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1378 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1379 | - * @param string $OBJ_type object type (like Event) |
|
| 1380 | - * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1381 | - * @return EE_Line_Item[] |
|
| 1382 | - * @throws EE_Error |
|
| 1383 | - */ |
|
| 1384 | - public static function get_line_items_by_object_type_and_IDs( |
|
| 1385 | - EE_Line_Item $parent_line_item, |
|
| 1386 | - $OBJ_type = '', |
|
| 1387 | - $OBJ_IDs = array() |
|
| 1388 | - ) { |
|
| 1389 | - return self::_get_descendants_by_object_type_and_object_ID( |
|
| 1390 | - $parent_line_item, |
|
| 1391 | - $OBJ_type, |
|
| 1392 | - $OBJ_IDs |
|
| 1393 | - ); |
|
| 1394 | - } |
|
| 1395 | - |
|
| 1396 | - |
|
| 1397 | - /** |
|
| 1398 | - * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type |
|
| 1399 | - * as well |
|
| 1400 | - * |
|
| 1401 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1402 | - * @param string $OBJ_type object type (like Event) |
|
| 1403 | - * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1404 | - * @return EE_Line_Item[] |
|
| 1405 | - * @throws EE_Error |
|
| 1406 | - */ |
|
| 1407 | - protected static function _get_descendants_by_object_type_and_object_ID( |
|
| 1408 | - EE_Line_Item $parent_line_item, |
|
| 1409 | - $OBJ_type, |
|
| 1410 | - $OBJ_IDs |
|
| 1411 | - ) { |
|
| 1412 | - $objects = array(); |
|
| 1413 | - foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1414 | - if ($child_line_item instanceof EE_Line_Item) { |
|
| 1415 | - if ($child_line_item->OBJ_type() === $OBJ_type |
|
| 1416 | - && is_array($OBJ_IDs) |
|
| 1417 | - && in_array($child_line_item->OBJ_ID(), $OBJ_IDs) |
|
| 1418 | - ) { |
|
| 1419 | - $objects[] = $child_line_item; |
|
| 1420 | - } else { |
|
| 1421 | - // go-through-all-its children looking for more matches |
|
| 1422 | - $objects = array_merge( |
|
| 1423 | - $objects, |
|
| 1424 | - self::_get_descendants_by_object_type_and_object_ID( |
|
| 1425 | - $child_line_item, |
|
| 1426 | - $OBJ_type, |
|
| 1427 | - $OBJ_IDs |
|
| 1428 | - ) |
|
| 1429 | - ); |
|
| 1430 | - } |
|
| 1431 | - } |
|
| 1432 | - } |
|
| 1433 | - return $objects; |
|
| 1434 | - } |
|
| 1435 | - |
|
| 1436 | - |
|
| 1437 | - /** |
|
| 1438 | - * Uses a breadth-first-search in order to find the nearest descendant of |
|
| 1439 | - * the specified type and returns it, else NULL |
|
| 1440 | - * |
|
| 1441 | - * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1442 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1443 | - * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1444 | - * @return EE_Line_Item |
|
| 1445 | - * @throws EE_Error |
|
| 1446 | - * @throws InvalidArgumentException |
|
| 1447 | - * @throws InvalidDataTypeException |
|
| 1448 | - * @throws InvalidInterfaceException |
|
| 1449 | - * @throws ReflectionException |
|
| 1450 | - */ |
|
| 1451 | - public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type) |
|
| 1452 | - { |
|
| 1453 | - return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type); |
|
| 1454 | - } |
|
| 1455 | - |
|
| 1456 | - |
|
| 1457 | - /** |
|
| 1458 | - * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1459 | - * having the specified LIN_code and returns it, else NULL |
|
| 1460 | - * |
|
| 1461 | - * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1462 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1463 | - * @param string $code any value used for LIN_code |
|
| 1464 | - * @return EE_Line_Item |
|
| 1465 | - * @throws EE_Error |
|
| 1466 | - * @throws InvalidArgumentException |
|
| 1467 | - * @throws InvalidDataTypeException |
|
| 1468 | - * @throws InvalidInterfaceException |
|
| 1469 | - * @throws ReflectionException |
|
| 1470 | - */ |
|
| 1471 | - public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code) |
|
| 1472 | - { |
|
| 1473 | - return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code); |
|
| 1474 | - } |
|
| 1475 | - |
|
| 1476 | - |
|
| 1477 | - /** |
|
| 1478 | - * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1479 | - * having the specified LIN_code and returns it, else NULL |
|
| 1480 | - * |
|
| 1481 | - * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1482 | - * @param string $search_field name of EE_Line_Item property |
|
| 1483 | - * @param string $value any value stored in $search_field |
|
| 1484 | - * @return EE_Line_Item |
|
| 1485 | - * @throws EE_Error |
|
| 1486 | - * @throws InvalidArgumentException |
|
| 1487 | - * @throws InvalidDataTypeException |
|
| 1488 | - * @throws InvalidInterfaceException |
|
| 1489 | - * @throws ReflectionException |
|
| 1490 | - */ |
|
| 1491 | - protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value) |
|
| 1492 | - { |
|
| 1493 | - foreach ($parent_line_item->children() as $child) { |
|
| 1494 | - if ($child->get($search_field) == $value) { |
|
| 1495 | - return $child; |
|
| 1496 | - } |
|
| 1497 | - } |
|
| 1498 | - foreach ($parent_line_item->children() as $child) { |
|
| 1499 | - $descendant_found = self::_get_nearest_descendant( |
|
| 1500 | - $child, |
|
| 1501 | - $search_field, |
|
| 1502 | - $value |
|
| 1503 | - ); |
|
| 1504 | - if ($descendant_found) { |
|
| 1505 | - return $descendant_found; |
|
| 1506 | - } |
|
| 1507 | - } |
|
| 1508 | - return null; |
|
| 1509 | - } |
|
| 1510 | - |
|
| 1511 | - |
|
| 1512 | - /** |
|
| 1513 | - * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction, |
|
| 1514 | - * else recursively walks up the line item tree until a parent of type total is found, |
|
| 1515 | - * |
|
| 1516 | - * @param EE_Line_Item $line_item |
|
| 1517 | - * @return EE_Line_Item |
|
| 1518 | - * @throws EE_Error |
|
| 1519 | - */ |
|
| 1520 | - public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item) |
|
| 1521 | - { |
|
| 1522 | - if ($line_item->TXN_ID()) { |
|
| 1523 | - $total_line_item = $line_item->transaction()->total_line_item(false); |
|
| 1524 | - if ($total_line_item instanceof EE_Line_Item) { |
|
| 1525 | - return $total_line_item; |
|
| 1526 | - } |
|
| 1527 | - } else { |
|
| 1528 | - $line_item_parent = $line_item->parent(); |
|
| 1529 | - if ($line_item_parent instanceof EE_Line_Item) { |
|
| 1530 | - if ($line_item_parent->is_total()) { |
|
| 1531 | - return $line_item_parent; |
|
| 1532 | - } |
|
| 1533 | - return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent); |
|
| 1534 | - } |
|
| 1535 | - } |
|
| 1536 | - throw new EE_Error( |
|
| 1537 | - sprintf( |
|
| 1538 | - esc_html__( |
|
| 1539 | - 'A valid grand total for line item %1$d was not found.', |
|
| 1540 | - 'event_espresso' |
|
| 1541 | - ), |
|
| 1542 | - $line_item->ID() |
|
| 1543 | - ) |
|
| 1544 | - ); |
|
| 1545 | - } |
|
| 1546 | - |
|
| 1547 | - |
|
| 1548 | - /** |
|
| 1549 | - * Prints out a representation of the line item tree |
|
| 1550 | - * |
|
| 1551 | - * @param EE_Line_Item $line_item |
|
| 1552 | - * @param int $indentation |
|
| 1553 | - * @return void |
|
| 1554 | - * @throws EE_Error |
|
| 1555 | - */ |
|
| 1556 | - public static function visualize(EE_Line_Item $line_item, $indentation = 0) |
|
| 1557 | - { |
|
| 1558 | - echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1559 | - if (! $indentation) { |
|
| 1560 | - echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1561 | - } |
|
| 1562 | - for ($i = 0; $i < $indentation; $i++) { |
|
| 1563 | - echo '. '; |
|
| 1564 | - } |
|
| 1565 | - $breakdown = ''; |
|
| 1566 | - if ($line_item->is_line_item()) { |
|
| 1567 | - if ($line_item->is_percent()) { |
|
| 1568 | - $breakdown = "{$line_item->percent()}%"; |
|
| 1569 | - } else { |
|
| 1570 | - $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1571 | - } |
|
| 1572 | - } |
|
| 1573 | - echo $line_item->name(); |
|
| 1574 | - echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : "; |
|
| 1575 | - echo '$' . (string) $line_item->total(); |
|
| 1576 | - if ($breakdown) { |
|
| 1577 | - echo " ( {$breakdown} )"; |
|
| 1578 | - } |
|
| 1579 | - if ($line_item->is_taxable()) { |
|
| 1580 | - echo ' * taxable'; |
|
| 1581 | - } |
|
| 1582 | - if ($line_item->children()) { |
|
| 1583 | - foreach ($line_item->children() as $child) { |
|
| 1584 | - self::visualize($child, $indentation + 1); |
|
| 1585 | - } |
|
| 1586 | - } |
|
| 1587 | - } |
|
| 1588 | - |
|
| 1589 | - |
|
| 1590 | - /** |
|
| 1591 | - * Calculates the registration's final price, taking into account that they |
|
| 1592 | - * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes, |
|
| 1593 | - * and receive a portion of any transaction-wide discounts. |
|
| 1594 | - * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount |
|
| 1595 | - * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get |
|
| 1596 | - * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50 |
|
| 1597 | - * and brent's final price should be $5.50. |
|
| 1598 | - * In order to do this, we basically need to traverse the line item tree calculating |
|
| 1599 | - * the running totals (just as if we were recalculating the total), but when we identify |
|
| 1600 | - * regular line items, we need to keep track of their share of the grand total. |
|
| 1601 | - * Also, we need to keep track of the TAXABLE total for each ticket purchase, so |
|
| 1602 | - * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total" |
|
| 1603 | - * when there are non-taxable items; otherwise they would be the same) |
|
| 1604 | - * |
|
| 1605 | - * @param EE_Line_Item $line_item |
|
| 1606 | - * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that |
|
| 1607 | - * can be included in price calculations at this moment |
|
| 1608 | - * @return array keys are line items for tickets IDs and values are their share of the running total, |
|
| 1609 | - * plus the key 'total', and 'taxable' which also has keys of all |
|
| 1610 | - * the ticket IDs. |
|
| 1611 | - * Eg array( |
|
| 1612 | - * 12 => 4.3 |
|
| 1613 | - * 23 => 8.0 |
|
| 1614 | - * 'total' => 16.6, |
|
| 1615 | - * 'taxable' => array( |
|
| 1616 | - * 12 => 10, |
|
| 1617 | - * 23 => 4 |
|
| 1618 | - * ). |
|
| 1619 | - * So to find which registrations have which final price, we need |
|
| 1620 | - * to find which line item is theirs, which can be done with |
|
| 1621 | - * `EEM_Line_Item::instance()->get_line_item_for_registration( |
|
| 1622 | - * $registration );` |
|
| 1623 | - * @throws EE_Error |
|
| 1624 | - * @throws InvalidArgumentException |
|
| 1625 | - * @throws InvalidDataTypeException |
|
| 1626 | - * @throws InvalidInterfaceException |
|
| 1627 | - * @throws ReflectionException |
|
| 1628 | - */ |
|
| 1629 | - public static function calculate_reg_final_prices_per_line_item( |
|
| 1630 | - EE_Line_Item $line_item, |
|
| 1631 | - $billable_ticket_quantities = array() |
|
| 1632 | - ) { |
|
| 1633 | - $running_totals = [ |
|
| 1634 | - 'total' => 0, |
|
| 1635 | - 'taxable' => ['total' => 0] |
|
| 1636 | - ]; |
|
| 1637 | - foreach ($line_item->children() as $child_line_item) { |
|
| 1638 | - switch ($child_line_item->type()) { |
|
| 1639 | - case EEM_Line_Item::type_sub_total: |
|
| 1640 | - $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item( |
|
| 1641 | - $child_line_item, |
|
| 1642 | - $billable_ticket_quantities |
|
| 1643 | - ); |
|
| 1644 | - // combine arrays but preserve numeric keys |
|
| 1645 | - $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals); |
|
| 1646 | - $running_totals['total'] += $running_totals_from_subtotal['total']; |
|
| 1647 | - $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total']; |
|
| 1648 | - break; |
|
| 1649 | - |
|
| 1650 | - case EEM_Line_Item::type_tax_sub_total: |
|
| 1651 | - // find how much the taxes percentage is |
|
| 1652 | - if ($child_line_item->percent() !== 0) { |
|
| 1653 | - $tax_percent_decimal = $child_line_item->percent() / 100; |
|
| 1654 | - } else { |
|
| 1655 | - $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100; |
|
| 1656 | - } |
|
| 1657 | - // and apply to all the taxable totals, and add to the pretax totals |
|
| 1658 | - foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1659 | - // "total" and "taxable" array key is an exception |
|
| 1660 | - if ($line_item_id === 'taxable') { |
|
| 1661 | - continue; |
|
| 1662 | - } |
|
| 1663 | - $taxable_total = $running_totals['taxable'][ $line_item_id ]; |
|
| 1664 | - $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal); |
|
| 1665 | - } |
|
| 1666 | - break; |
|
| 1667 | - |
|
| 1668 | - case EEM_Line_Item::type_line_item: |
|
| 1669 | - // ticket line items or ???? |
|
| 1670 | - if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 1671 | - // kk it's a ticket |
|
| 1672 | - if (isset($running_totals[ $child_line_item->ID() ])) { |
|
| 1673 | - // huh? that shouldn't happen. |
|
| 1674 | - $running_totals['total'] += $child_line_item->total(); |
|
| 1675 | - } else { |
|
| 1676 | - // its not in our running totals yet. great. |
|
| 1677 | - if ($child_line_item->is_taxable()) { |
|
| 1678 | - $taxable_amount = $child_line_item->unit_price(); |
|
| 1679 | - } else { |
|
| 1680 | - $taxable_amount = 0; |
|
| 1681 | - } |
|
| 1682 | - // are we only calculating totals for some tickets? |
|
| 1683 | - if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) { |
|
| 1684 | - $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ]; |
|
| 1685 | - $running_totals[ $child_line_item->ID() ] = $quantity |
|
| 1686 | - ? $child_line_item->unit_price() |
|
| 1687 | - : 0; |
|
| 1688 | - $running_totals['taxable'][ $child_line_item->ID() ] = $quantity |
|
| 1689 | - ? $taxable_amount |
|
| 1690 | - : 0; |
|
| 1691 | - } else { |
|
| 1692 | - $quantity = $child_line_item->quantity(); |
|
| 1693 | - $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price(); |
|
| 1694 | - $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount; |
|
| 1695 | - } |
|
| 1696 | - $running_totals['taxable']['total'] += $taxable_amount * $quantity; |
|
| 1697 | - $running_totals['total'] += $child_line_item->unit_price() * $quantity; |
|
| 1698 | - } |
|
| 1699 | - } else { |
|
| 1700 | - // it's some other type of item added to the cart |
|
| 1701 | - // it should affect the running totals |
|
| 1702 | - // basically we want to convert it into a PERCENT modifier. Because |
|
| 1703 | - // more clearly affect all registration's final price equally |
|
| 1704 | - $line_items_percent_of_running_total = $running_totals['total'] > 0 |
|
| 1705 | - ? ($child_line_item->total() / $running_totals['total']) + 1 |
|
| 1706 | - : 1; |
|
| 1707 | - foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1708 | - // the "taxable" array key is an exception |
|
| 1709 | - if ($line_item_id === 'taxable') { |
|
| 1710 | - continue; |
|
| 1711 | - } |
|
| 1712 | - // update the running totals |
|
| 1713 | - // yes this actually even works for the running grand total! |
|
| 1714 | - $running_totals[ $line_item_id ] = |
|
| 1715 | - $line_items_percent_of_running_total * $this_running_total; |
|
| 1716 | - |
|
| 1717 | - if ($child_line_item->is_taxable()) { |
|
| 1718 | - $running_totals['taxable'][ $line_item_id ] = |
|
| 1719 | - $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ]; |
|
| 1720 | - } |
|
| 1721 | - } |
|
| 1722 | - } |
|
| 1723 | - break; |
|
| 1724 | - } |
|
| 1725 | - } |
|
| 1726 | - return $running_totals; |
|
| 1727 | - } |
|
| 1728 | - |
|
| 1729 | - |
|
| 1730 | - /** |
|
| 1731 | - * @param EE_Line_Item $total_line_item |
|
| 1732 | - * @param EE_Line_Item $ticket_line_item |
|
| 1733 | - * @return float | null |
|
| 1734 | - * @throws EE_Error |
|
| 1735 | - * @throws InvalidArgumentException |
|
| 1736 | - * @throws InvalidDataTypeException |
|
| 1737 | - * @throws InvalidInterfaceException |
|
| 1738 | - * @throws OutOfRangeException |
|
| 1739 | - * @throws ReflectionException |
|
| 1740 | - */ |
|
| 1741 | - public static function calculate_final_price_for_ticket_line_item( |
|
| 1742 | - EE_Line_Item $total_line_item, |
|
| 1743 | - EE_Line_Item $ticket_line_item |
|
| 1744 | - ) { |
|
| 1745 | - static $final_prices_per_ticket_line_item = array(); |
|
| 1746 | - if (empty($final_prices_per_ticket_line_item)) { |
|
| 1747 | - $final_prices_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item( |
|
| 1748 | - $total_line_item |
|
| 1749 | - ); |
|
| 1750 | - } |
|
| 1751 | - // ok now find this new registration's final price |
|
| 1752 | - if (isset($final_prices_per_ticket_line_item[ $ticket_line_item->ID() ])) { |
|
| 1753 | - return $final_prices_per_ticket_line_item[ $ticket_line_item->ID() ]; |
|
| 1754 | - } |
|
| 1755 | - $message = sprintf( |
|
| 1756 | - esc_html__( |
|
| 1757 | - 'The final price for the ticket line item (ID:%1$d) could not be calculated.', |
|
| 1758 | - 'event_espresso' |
|
| 1759 | - ), |
|
| 1760 | - $ticket_line_item->ID() |
|
| 1761 | - ); |
|
| 1762 | - if (WP_DEBUG) { |
|
| 1763 | - $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true); |
|
| 1764 | - throw new OutOfRangeException($message); |
|
| 1765 | - } |
|
| 1766 | - EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message); |
|
| 1767 | - return null; |
|
| 1768 | - } |
|
| 1769 | - |
|
| 1770 | - |
|
| 1771 | - /** |
|
| 1772 | - * Creates a duplicate of the line item tree, except only includes billable items |
|
| 1773 | - * and the portion of line items attributed to billable things |
|
| 1774 | - * |
|
| 1775 | - * @param EE_Line_Item $line_item |
|
| 1776 | - * @param EE_Registration[] $registrations |
|
| 1777 | - * @return EE_Line_Item |
|
| 1778 | - * @throws EE_Error |
|
| 1779 | - * @throws InvalidArgumentException |
|
| 1780 | - * @throws InvalidDataTypeException |
|
| 1781 | - * @throws InvalidInterfaceException |
|
| 1782 | - * @throws ReflectionException |
|
| 1783 | - */ |
|
| 1784 | - public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations) |
|
| 1785 | - { |
|
| 1786 | - $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations); |
|
| 1787 | - foreach ($line_item->children() as $child_li) { |
|
| 1788 | - $copy_li->add_child_line_item( |
|
| 1789 | - EEH_Line_Item::billable_line_item_tree($child_li, $registrations) |
|
| 1790 | - ); |
|
| 1791 | - } |
|
| 1792 | - // if this is the grand total line item, make sure the totals all add up |
|
| 1793 | - // (we could have duplicated this logic AS we copied the line items, but |
|
| 1794 | - // it seems DRYer this way) |
|
| 1795 | - if ($copy_li->type() === EEM_Line_Item::type_total) { |
|
| 1796 | - $copy_li->recalculate_total_including_taxes(); |
|
| 1797 | - } |
|
| 1798 | - return $copy_li; |
|
| 1799 | - } |
|
| 1800 | - |
|
| 1801 | - |
|
| 1802 | - /** |
|
| 1803 | - * Creates a new, unsaved line item from $line_item that factors in the |
|
| 1804 | - * number of billable registrations on $registrations. |
|
| 1805 | - * |
|
| 1806 | - * @param EE_Line_Item $line_item |
|
| 1807 | - * @param EE_Registration[] $registrations |
|
| 1808 | - * @return EE_Line_Item |
|
| 1809 | - * @throws EE_Error |
|
| 1810 | - * @throws InvalidArgumentException |
|
| 1811 | - * @throws InvalidDataTypeException |
|
| 1812 | - * @throws InvalidInterfaceException |
|
| 1813 | - * @throws ReflectionException |
|
| 1814 | - */ |
|
| 1815 | - public static function billable_line_item(EE_Line_Item $line_item, $registrations) |
|
| 1816 | - { |
|
| 1817 | - $new_li_fields = $line_item->model_field_array(); |
|
| 1818 | - if ($line_item->type() === EEM_Line_Item::type_line_item && |
|
| 1819 | - $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1820 | - ) { |
|
| 1821 | - $count = 0; |
|
| 1822 | - foreach ($registrations as $registration) { |
|
| 1823 | - if ($line_item->OBJ_ID() === $registration->ticket_ID() && |
|
| 1824 | - in_array( |
|
| 1825 | - $registration->status_ID(), |
|
| 1826 | - EEM_Registration::reg_statuses_that_allow_payment(), |
|
| 1827 | - true |
|
| 1828 | - ) |
|
| 1829 | - ) { |
|
| 1830 | - $count++; |
|
| 1831 | - } |
|
| 1832 | - } |
|
| 1833 | - $new_li_fields['LIN_quantity'] = $count; |
|
| 1834 | - } |
|
| 1835 | - // don't set the total. We'll leave that up to the code that calculates it |
|
| 1836 | - unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']); |
|
| 1837 | - return EE_Line_Item::new_instance($new_li_fields); |
|
| 1838 | - } |
|
| 1839 | - |
|
| 1840 | - |
|
| 1841 | - /** |
|
| 1842 | - * Returns a modified line item tree where all the subtotals which have a total of 0 |
|
| 1843 | - * are removed, and line items with a quantity of 0 |
|
| 1844 | - * |
|
| 1845 | - * @param EE_Line_Item $line_item |null |
|
| 1846 | - * @return EE_Line_Item|null |
|
| 1847 | - * @throws EE_Error |
|
| 1848 | - * @throws InvalidArgumentException |
|
| 1849 | - * @throws InvalidDataTypeException |
|
| 1850 | - * @throws InvalidInterfaceException |
|
| 1851 | - * @throws ReflectionException |
|
| 1852 | - */ |
|
| 1853 | - public static function non_empty_line_items(EE_Line_Item $line_item) |
|
| 1854 | - { |
|
| 1855 | - $copied_li = EEH_Line_Item::non_empty_line_item($line_item); |
|
| 1856 | - if ($copied_li === null) { |
|
| 1857 | - return null; |
|
| 1858 | - } |
|
| 1859 | - // if this is an event subtotal, we want to only include it if it |
|
| 1860 | - // has a non-zero total and at least one ticket line item child |
|
| 1861 | - $ticket_children = 0; |
|
| 1862 | - foreach ($line_item->children() as $child_li) { |
|
| 1863 | - $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li); |
|
| 1864 | - if ($child_li_copy !== null) { |
|
| 1865 | - $copied_li->add_child_line_item($child_li_copy); |
|
| 1866 | - if ($child_li_copy->type() === EEM_Line_Item::type_line_item && |
|
| 1867 | - $child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1868 | - ) { |
|
| 1869 | - $ticket_children++; |
|
| 1870 | - } |
|
| 1871 | - } |
|
| 1872 | - } |
|
| 1873 | - // if this is an event subtotal with NO ticket children |
|
| 1874 | - // we basically want to ignore it |
|
| 1875 | - if ($ticket_children === 0 |
|
| 1876 | - && $line_item->type() === EEM_Line_Item::type_sub_total |
|
| 1877 | - && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT |
|
| 1878 | - && $line_item->total() === 0 |
|
| 1879 | - ) { |
|
| 1880 | - return null; |
|
| 1881 | - } |
|
| 1882 | - return $copied_li; |
|
| 1883 | - } |
|
| 1884 | - |
|
| 1885 | - |
|
| 1886 | - /** |
|
| 1887 | - * Creates a new, unsaved line item, but if it's a ticket line item |
|
| 1888 | - * with a total of 0, or a subtotal of 0, returns null instead |
|
| 1889 | - * |
|
| 1890 | - * @param EE_Line_Item $line_item |
|
| 1891 | - * @return EE_Line_Item |
|
| 1892 | - * @throws EE_Error |
|
| 1893 | - * @throws InvalidArgumentException |
|
| 1894 | - * @throws InvalidDataTypeException |
|
| 1895 | - * @throws InvalidInterfaceException |
|
| 1896 | - * @throws ReflectionException |
|
| 1897 | - */ |
|
| 1898 | - public static function non_empty_line_item(EE_Line_Item $line_item) |
|
| 1899 | - { |
|
| 1900 | - if ($line_item->type() === EEM_Line_Item::type_line_item |
|
| 1901 | - && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1902 | - && $line_item->quantity() === 0 |
|
| 1903 | - ) { |
|
| 1904 | - return null; |
|
| 1905 | - } |
|
| 1906 | - $new_li_fields = $line_item->model_field_array(); |
|
| 1907 | - // don't set the total. We'll leave that up to the code that calculates it |
|
| 1908 | - unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']); |
|
| 1909 | - return EE_Line_Item::new_instance($new_li_fields); |
|
| 1910 | - } |
|
| 1911 | - |
|
| 1912 | - |
|
| 1913 | - /** |
|
| 1914 | - * Cycles through all of the ticket line items for the supplied total line item |
|
| 1915 | - * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket |
|
| 1916 | - * |
|
| 1917 | - * @param EE_Line_Item $total_line_item |
|
| 1918 | - * @since 4.9.79.p |
|
| 1919 | - * @throws EE_Error |
|
| 1920 | - * @throws InvalidArgumentException |
|
| 1921 | - * @throws InvalidDataTypeException |
|
| 1922 | - * @throws InvalidInterfaceException |
|
| 1923 | - * @throws ReflectionException |
|
| 1924 | - */ |
|
| 1925 | - public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item) |
|
| 1926 | - { |
|
| 1927 | - $ticket_line_items = self::get_ticket_line_items($total_line_item); |
|
| 1928 | - foreach ($ticket_line_items as $ticket_line_item) { |
|
| 1929 | - if ($ticket_line_item instanceof EE_Line_Item |
|
| 1930 | - && $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1931 | - ) { |
|
| 1932 | - $ticket = $ticket_line_item->ticket(); |
|
| 1933 | - if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) { |
|
| 1934 | - $ticket_line_item->set_is_taxable($ticket->taxable()); |
|
| 1935 | - $ticket_line_item->save(); |
|
| 1936 | - } |
|
| 1937 | - } |
|
| 1938 | - } |
|
| 1939 | - } |
|
| 1940 | - |
|
| 1941 | - |
|
| 1942 | - |
|
| 1943 | - /**************************************** @DEPRECATED METHODS *************************************** */ |
|
| 1944 | - /** |
|
| 1945 | - * @deprecated |
|
| 1946 | - * @param EE_Line_Item $total_line_item |
|
| 1947 | - * @return EE_Line_Item |
|
| 1948 | - * @throws EE_Error |
|
| 1949 | - * @throws InvalidArgumentException |
|
| 1950 | - * @throws InvalidDataTypeException |
|
| 1951 | - * @throws InvalidInterfaceException |
|
| 1952 | - * @throws ReflectionException |
|
| 1953 | - */ |
|
| 1954 | - public static function get_items_subtotal(EE_Line_Item $total_line_item) |
|
| 1955 | - { |
|
| 1956 | - EE_Error::doing_it_wrong( |
|
| 1957 | - 'EEH_Line_Item::get_items_subtotal()', |
|
| 1958 | - sprintf( |
|
| 1959 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1960 | - 'EEH_Line_Item::get_pre_tax_subtotal()' |
|
| 1961 | - ), |
|
| 1962 | - '4.6.0' |
|
| 1963 | - ); |
|
| 1964 | - return self::get_pre_tax_subtotal($total_line_item); |
|
| 1965 | - } |
|
| 1966 | - |
|
| 1967 | - |
|
| 1968 | - /** |
|
| 1969 | - * @deprecated |
|
| 1970 | - * @param EE_Transaction $transaction |
|
| 1971 | - * @return EE_Line_Item |
|
| 1972 | - * @throws EE_Error |
|
| 1973 | - * @throws InvalidArgumentException |
|
| 1974 | - * @throws InvalidDataTypeException |
|
| 1975 | - * @throws InvalidInterfaceException |
|
| 1976 | - * @throws ReflectionException |
|
| 1977 | - */ |
|
| 1978 | - public static function create_default_total_line_item($transaction = null) |
|
| 1979 | - { |
|
| 1980 | - EE_Error::doing_it_wrong( |
|
| 1981 | - 'EEH_Line_Item::create_default_total_line_item()', |
|
| 1982 | - sprintf( |
|
| 1983 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1984 | - 'EEH_Line_Item::create_total_line_item()' |
|
| 1985 | - ), |
|
| 1986 | - '4.6.0' |
|
| 1987 | - ); |
|
| 1988 | - return self::create_total_line_item($transaction); |
|
| 1989 | - } |
|
| 1990 | - |
|
| 1991 | - |
|
| 1992 | - /** |
|
| 1993 | - * @deprecated |
|
| 1994 | - * @param EE_Line_Item $total_line_item |
|
| 1995 | - * @param EE_Transaction $transaction |
|
| 1996 | - * @return EE_Line_Item |
|
| 1997 | - * @throws EE_Error |
|
| 1998 | - * @throws InvalidArgumentException |
|
| 1999 | - * @throws InvalidDataTypeException |
|
| 2000 | - * @throws InvalidInterfaceException |
|
| 2001 | - * @throws ReflectionException |
|
| 2002 | - */ |
|
| 2003 | - public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 2004 | - { |
|
| 2005 | - EE_Error::doing_it_wrong( |
|
| 2006 | - 'EEH_Line_Item::create_default_tickets_subtotal()', |
|
| 2007 | - sprintf( |
|
| 2008 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 2009 | - 'EEH_Line_Item::create_pre_tax_subtotal()' |
|
| 2010 | - ), |
|
| 2011 | - '4.6.0' |
|
| 2012 | - ); |
|
| 2013 | - return self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 2014 | - } |
|
| 2015 | - |
|
| 2016 | - |
|
| 2017 | - /** |
|
| 2018 | - * @deprecated |
|
| 2019 | - * @param EE_Line_Item $total_line_item |
|
| 2020 | - * @param EE_Transaction $transaction |
|
| 2021 | - * @return EE_Line_Item |
|
| 2022 | - * @throws EE_Error |
|
| 2023 | - * @throws InvalidArgumentException |
|
| 2024 | - * @throws InvalidDataTypeException |
|
| 2025 | - * @throws InvalidInterfaceException |
|
| 2026 | - * @throws ReflectionException |
|
| 2027 | - */ |
|
| 2028 | - public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 2029 | - { |
|
| 2030 | - EE_Error::doing_it_wrong( |
|
| 2031 | - 'EEH_Line_Item::create_default_taxes_subtotal()', |
|
| 2032 | - sprintf( |
|
| 2033 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 2034 | - 'EEH_Line_Item::create_taxes_subtotal()' |
|
| 2035 | - ), |
|
| 2036 | - '4.6.0' |
|
| 2037 | - ); |
|
| 2038 | - return self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 2039 | - } |
|
| 2040 | - |
|
| 2041 | - |
|
| 2042 | - /** |
|
| 2043 | - * @deprecated |
|
| 2044 | - * @param EE_Line_Item $total_line_item |
|
| 2045 | - * @param EE_Transaction $transaction |
|
| 2046 | - * @return EE_Line_Item |
|
| 2047 | - * @throws EE_Error |
|
| 2048 | - * @throws InvalidArgumentException |
|
| 2049 | - * @throws InvalidDataTypeException |
|
| 2050 | - * @throws InvalidInterfaceException |
|
| 2051 | - * @throws ReflectionException |
|
| 2052 | - */ |
|
| 2053 | - public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 2054 | - { |
|
| 2055 | - EE_Error::doing_it_wrong( |
|
| 2056 | - 'EEH_Line_Item::create_default_event_subtotal()', |
|
| 2057 | - sprintf( |
|
| 2058 | - esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 2059 | - 'EEH_Line_Item::create_event_subtotal()' |
|
| 2060 | - ), |
|
| 2061 | - '4.6.0' |
|
| 2062 | - ); |
|
| 2063 | - return self::create_event_subtotal($total_line_item, $transaction); |
|
| 2064 | - } |
|
| 24 | + /** |
|
| 25 | + * Adds a simple item (unrelated to any other model object) to the provided PARENT line item. |
|
| 26 | + * Does NOT automatically re-calculate the line item totals or update the related transaction. |
|
| 27 | + * You should call recalculate_total_including_taxes() on the grant total line item after this |
|
| 28 | + * to update the subtotals, and EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 29 | + * to keep the registration final prices in-sync with the transaction's total. |
|
| 30 | + * |
|
| 31 | + * @param EE_Line_Item $parent_line_item |
|
| 32 | + * @param string $name |
|
| 33 | + * @param float $unit_price |
|
| 34 | + * @param string $description |
|
| 35 | + * @param int $quantity |
|
| 36 | + * @param boolean $taxable |
|
| 37 | + * @param boolean $code if set to a value, ensures there is only one line item with that code |
|
| 38 | + * @return boolean success |
|
| 39 | + * @throws EE_Error |
|
| 40 | + * @throws InvalidArgumentException |
|
| 41 | + * @throws InvalidDataTypeException |
|
| 42 | + * @throws InvalidInterfaceException |
|
| 43 | + * @throws ReflectionException |
|
| 44 | + */ |
|
| 45 | + public static function add_unrelated_item( |
|
| 46 | + EE_Line_Item $parent_line_item, |
|
| 47 | + $name, |
|
| 48 | + $unit_price, |
|
| 49 | + $description = '', |
|
| 50 | + $quantity = 1, |
|
| 51 | + $taxable = false, |
|
| 52 | + $code = null |
|
| 53 | + ) { |
|
| 54 | + $items_subtotal = self::get_pre_tax_subtotal($parent_line_item); |
|
| 55 | + $line_item = EE_Line_Item::new_instance(array( |
|
| 56 | + 'LIN_name' => $name, |
|
| 57 | + 'LIN_desc' => $description, |
|
| 58 | + 'LIN_unit_price' => $unit_price, |
|
| 59 | + 'LIN_quantity' => $quantity, |
|
| 60 | + 'LIN_percent' => null, |
|
| 61 | + 'LIN_is_taxable' => $taxable, |
|
| 62 | + 'LIN_order' => $items_subtotal instanceof EE_Line_Item ? count($items_subtotal->children()) : 0, |
|
| 63 | + 'LIN_total' => (float) $unit_price * (int) $quantity, |
|
| 64 | + 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 65 | + 'LIN_code' => $code, |
|
| 66 | + )); |
|
| 67 | + $line_item = apply_filters( |
|
| 68 | + 'FHEE__EEH_Line_Item__add_unrelated_item__line_item', |
|
| 69 | + $line_item, |
|
| 70 | + $parent_line_item |
|
| 71 | + ); |
|
| 72 | + return self::add_item($parent_line_item, $line_item); |
|
| 73 | + } |
|
| 74 | + |
|
| 75 | + |
|
| 76 | + /** |
|
| 77 | + * Adds a simple item ( unrelated to any other model object) to the total line item, |
|
| 78 | + * in the correct spot in the line item tree. Automatically |
|
| 79 | + * re-calculates the line item totals and updates the related transaction. But |
|
| 80 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 81 | + * should probably change because of this). |
|
| 82 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 83 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 84 | + * |
|
| 85 | + * @param EE_Line_Item $parent_line_item |
|
| 86 | + * @param string $name |
|
| 87 | + * @param float $percentage_amount |
|
| 88 | + * @param string $description |
|
| 89 | + * @param boolean $taxable |
|
| 90 | + * @return boolean success |
|
| 91 | + * @throws EE_Error |
|
| 92 | + */ |
|
| 93 | + public static function add_percentage_based_item( |
|
| 94 | + EE_Line_Item $parent_line_item, |
|
| 95 | + $name, |
|
| 96 | + $percentage_amount, |
|
| 97 | + $description = '', |
|
| 98 | + $taxable = false |
|
| 99 | + ) { |
|
| 100 | + $line_item = EE_Line_Item::new_instance(array( |
|
| 101 | + 'LIN_name' => $name, |
|
| 102 | + 'LIN_desc' => $description, |
|
| 103 | + 'LIN_unit_price' => 0, |
|
| 104 | + 'LIN_percent' => $percentage_amount, |
|
| 105 | + 'LIN_quantity' => 1, |
|
| 106 | + 'LIN_is_taxable' => $taxable, |
|
| 107 | + 'LIN_total' => (float) ($percentage_amount * ($parent_line_item->total() / 100)), |
|
| 108 | + 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 109 | + 'LIN_parent' => $parent_line_item->ID(), |
|
| 110 | + )); |
|
| 111 | + $line_item = apply_filters( |
|
| 112 | + 'FHEE__EEH_Line_Item__add_percentage_based_item__line_item', |
|
| 113 | + $line_item |
|
| 114 | + ); |
|
| 115 | + return $parent_line_item->add_child_line_item($line_item, false); |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + |
|
| 119 | + /** |
|
| 120 | + * Returns the new line item created by adding a purchase of the ticket |
|
| 121 | + * ensures that ticket line item is saved, and that cart total has been recalculated. |
|
| 122 | + * If this ticket has already been purchased, just increments its count. |
|
| 123 | + * Automatically re-calculates the line item totals and updates the related transaction. But |
|
| 124 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 125 | + * should probably change because of this). |
|
| 126 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 127 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 128 | + * |
|
| 129 | + * @param EE_Line_Item $total_line_item grand total line item of type EEM_Line_Item::type_total |
|
| 130 | + * @param EE_Ticket $ticket |
|
| 131 | + * @param int $qty |
|
| 132 | + * @return EE_Line_Item |
|
| 133 | + * @throws EE_Error |
|
| 134 | + * @throws InvalidArgumentException |
|
| 135 | + * @throws InvalidDataTypeException |
|
| 136 | + * @throws InvalidInterfaceException |
|
| 137 | + * @throws ReflectionException |
|
| 138 | + */ |
|
| 139 | + public static function add_ticket_purchase(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 140 | + { |
|
| 141 | + if (! $total_line_item instanceof EE_Line_Item || ! $total_line_item->is_total()) { |
|
| 142 | + throw new EE_Error( |
|
| 143 | + sprintf( |
|
| 144 | + esc_html__( |
|
| 145 | + 'A valid line item total is required in order to add tickets. A line item of type "%s" was passed.', |
|
| 146 | + 'event_espresso' |
|
| 147 | + ), |
|
| 148 | + $ticket->ID(), |
|
| 149 | + $total_line_item->ID() |
|
| 150 | + ) |
|
| 151 | + ); |
|
| 152 | + } |
|
| 153 | + // either increment the qty for an existing ticket |
|
| 154 | + $line_item = self::increment_ticket_qty_if_already_in_cart($total_line_item, $ticket, $qty); |
|
| 155 | + // or add a new one |
|
| 156 | + if (! $line_item instanceof EE_Line_Item) { |
|
| 157 | + $line_item = self::create_ticket_line_item($total_line_item, $ticket, $qty); |
|
| 158 | + } |
|
| 159 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 160 | + return $line_item; |
|
| 161 | + } |
|
| 162 | + |
|
| 163 | + |
|
| 164 | + /** |
|
| 165 | + * Returns the new line item created by adding a purchase of the ticket |
|
| 166 | + * |
|
| 167 | + * @param EE_Line_Item $total_line_item |
|
| 168 | + * @param EE_Ticket $ticket |
|
| 169 | + * @param int $qty |
|
| 170 | + * @return EE_Line_Item |
|
| 171 | + * @throws EE_Error |
|
| 172 | + * @throws InvalidArgumentException |
|
| 173 | + * @throws InvalidDataTypeException |
|
| 174 | + * @throws InvalidInterfaceException |
|
| 175 | + * @throws ReflectionException |
|
| 176 | + */ |
|
| 177 | + public static function increment_ticket_qty_if_already_in_cart( |
|
| 178 | + EE_Line_Item $total_line_item, |
|
| 179 | + EE_Ticket $ticket, |
|
| 180 | + $qty = 1 |
|
| 181 | + ) { |
|
| 182 | + $line_item = null; |
|
| 183 | + if ($total_line_item instanceof EE_Line_Item && $total_line_item->is_total()) { |
|
| 184 | + $ticket_line_items = EEH_Line_Item::get_ticket_line_items($total_line_item); |
|
| 185 | + foreach ((array) $ticket_line_items as $ticket_line_item) { |
|
| 186 | + if ($ticket_line_item instanceof EE_Line_Item |
|
| 187 | + && (int) $ticket_line_item->OBJ_ID() === (int) $ticket->ID() |
|
| 188 | + ) { |
|
| 189 | + $line_item = $ticket_line_item; |
|
| 190 | + break; |
|
| 191 | + } |
|
| 192 | + } |
|
| 193 | + } |
|
| 194 | + if ($line_item instanceof EE_Line_Item) { |
|
| 195 | + EEH_Line_Item::increment_quantity($line_item, $qty); |
|
| 196 | + return $line_item; |
|
| 197 | + } |
|
| 198 | + return null; |
|
| 199 | + } |
|
| 200 | + |
|
| 201 | + |
|
| 202 | + /** |
|
| 203 | + * Increments the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 204 | + * Does NOT save or recalculate other line items totals |
|
| 205 | + * |
|
| 206 | + * @param EE_Line_Item $line_item |
|
| 207 | + * @param int $qty |
|
| 208 | + * @return void |
|
| 209 | + * @throws EE_Error |
|
| 210 | + * @throws InvalidArgumentException |
|
| 211 | + * @throws InvalidDataTypeException |
|
| 212 | + * @throws InvalidInterfaceException |
|
| 213 | + * @throws ReflectionException |
|
| 214 | + */ |
|
| 215 | + public static function increment_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 216 | + { |
|
| 217 | + if (! $line_item->is_percent()) { |
|
| 218 | + $qty += $line_item->quantity(); |
|
| 219 | + $line_item->set_quantity($qty); |
|
| 220 | + $line_item->set_total($line_item->unit_price() * $qty); |
|
| 221 | + $line_item->save(); |
|
| 222 | + } |
|
| 223 | + foreach ($line_item->children() as $child) { |
|
| 224 | + if ($child->is_sub_line_item()) { |
|
| 225 | + EEH_Line_Item::update_quantity($child, $qty); |
|
| 226 | + } |
|
| 227 | + } |
|
| 228 | + } |
|
| 229 | + |
|
| 230 | + |
|
| 231 | + /** |
|
| 232 | + * Decrements the line item and all its children's quantity by $qty (but percent line items are unaffected). |
|
| 233 | + * Does NOT save or recalculate other line items totals |
|
| 234 | + * |
|
| 235 | + * @param EE_Line_Item $line_item |
|
| 236 | + * @param int $qty |
|
| 237 | + * @return void |
|
| 238 | + * @throws EE_Error |
|
| 239 | + * @throws InvalidArgumentException |
|
| 240 | + * @throws InvalidDataTypeException |
|
| 241 | + * @throws InvalidInterfaceException |
|
| 242 | + * @throws ReflectionException |
|
| 243 | + */ |
|
| 244 | + public static function decrement_quantity(EE_Line_Item $line_item, $qty = 1) |
|
| 245 | + { |
|
| 246 | + if (! $line_item->is_percent()) { |
|
| 247 | + $qty = $line_item->quantity() - $qty; |
|
| 248 | + $qty = max($qty, 0); |
|
| 249 | + $line_item->set_quantity($qty); |
|
| 250 | + $line_item->set_total($line_item->unit_price() * $qty); |
|
| 251 | + $line_item->save(); |
|
| 252 | + } |
|
| 253 | + foreach ($line_item->children() as $child) { |
|
| 254 | + if ($child->is_sub_line_item()) { |
|
| 255 | + EEH_Line_Item::update_quantity($child, $qty); |
|
| 256 | + } |
|
| 257 | + } |
|
| 258 | + } |
|
| 259 | + |
|
| 260 | + |
|
| 261 | + /** |
|
| 262 | + * Updates the line item and its children's quantities to the specified number. |
|
| 263 | + * Does NOT save them or recalculate totals. |
|
| 264 | + * |
|
| 265 | + * @param EE_Line_Item $line_item |
|
| 266 | + * @param int $new_quantity |
|
| 267 | + * @throws EE_Error |
|
| 268 | + * @throws InvalidArgumentException |
|
| 269 | + * @throws InvalidDataTypeException |
|
| 270 | + * @throws InvalidInterfaceException |
|
| 271 | + * @throws ReflectionException |
|
| 272 | + */ |
|
| 273 | + public static function update_quantity(EE_Line_Item $line_item, $new_quantity) |
|
| 274 | + { |
|
| 275 | + if (! $line_item->is_percent()) { |
|
| 276 | + $line_item->set_quantity($new_quantity); |
|
| 277 | + $line_item->set_total($line_item->unit_price() * $new_quantity); |
|
| 278 | + $line_item->save(); |
|
| 279 | + } |
|
| 280 | + foreach ($line_item->children() as $child) { |
|
| 281 | + if ($child->is_sub_line_item()) { |
|
| 282 | + EEH_Line_Item::update_quantity($child, $new_quantity); |
|
| 283 | + } |
|
| 284 | + } |
|
| 285 | + } |
|
| 286 | + |
|
| 287 | + |
|
| 288 | + /** |
|
| 289 | + * Returns the new line item created by adding a purchase of the ticket |
|
| 290 | + * |
|
| 291 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 292 | + * @param EE_Ticket $ticket |
|
| 293 | + * @param int $qty |
|
| 294 | + * @return EE_Line_Item |
|
| 295 | + * @throws EE_Error |
|
| 296 | + * @throws InvalidArgumentException |
|
| 297 | + * @throws InvalidDataTypeException |
|
| 298 | + * @throws InvalidInterfaceException |
|
| 299 | + * @throws ReflectionException |
|
| 300 | + */ |
|
| 301 | + public static function create_ticket_line_item(EE_Line_Item $total_line_item, EE_Ticket $ticket, $qty = 1) |
|
| 302 | + { |
|
| 303 | + $datetimes = $ticket->datetimes(); |
|
| 304 | + $first_datetime = reset($datetimes); |
|
| 305 | + $first_datetime_name = esc_html__('Event', 'event_espresso'); |
|
| 306 | + if ($first_datetime instanceof EE_Datetime && $first_datetime->event() instanceof EE_Event) { |
|
| 307 | + $first_datetime_name = $first_datetime->event()->name(); |
|
| 308 | + } |
|
| 309 | + $event = sprintf(_x('(For %1$s)', '(For Event Name)', 'event_espresso'), $first_datetime_name); |
|
| 310 | + // get event subtotal line |
|
| 311 | + $events_sub_total = self::get_event_line_item_for_ticket($total_line_item, $ticket); |
|
| 312 | + // add $ticket to cart |
|
| 313 | + $line_item = EE_Line_Item::new_instance(array( |
|
| 314 | + 'LIN_name' => $ticket->name(), |
|
| 315 | + 'LIN_desc' => $ticket->description() !== '' ? $ticket->description() . ' ' . $event : $event, |
|
| 316 | + 'LIN_unit_price' => $ticket->price(), |
|
| 317 | + 'LIN_quantity' => $qty, |
|
| 318 | + 'LIN_is_taxable' => $ticket->taxable(), |
|
| 319 | + 'LIN_order' => count($events_sub_total->children()), |
|
| 320 | + 'LIN_total' => $ticket->price() * $qty, |
|
| 321 | + 'LIN_type' => EEM_Line_Item::type_line_item, |
|
| 322 | + 'OBJ_ID' => $ticket->ID(), |
|
| 323 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 324 | + )); |
|
| 325 | + $line_item = apply_filters( |
|
| 326 | + 'FHEE__EEH_Line_Item__create_ticket_line_item__line_item', |
|
| 327 | + $line_item |
|
| 328 | + ); |
|
| 329 | + $events_sub_total->add_child_line_item($line_item); |
|
| 330 | + // now add the sub-line items |
|
| 331 | + $running_total_for_ticket = 0; |
|
| 332 | + foreach ($ticket->prices(array('order_by' => array('PRC_order' => 'ASC'))) as $price) { |
|
| 333 | + $sign = $price->is_discount() ? -1 : 1; |
|
| 334 | + $price_total = $price->is_percent() |
|
| 335 | + ? $running_total_for_ticket * $price->amount() / 100 |
|
| 336 | + : $price->amount() * $qty; |
|
| 337 | + $sub_line_item = EE_Line_Item::new_instance(array( |
|
| 338 | + 'LIN_name' => $price->name(), |
|
| 339 | + 'LIN_desc' => $price->desc(), |
|
| 340 | + 'LIN_quantity' => $price->is_percent() ? null : $qty, |
|
| 341 | + 'LIN_is_taxable' => false, |
|
| 342 | + 'LIN_order' => $price->order(), |
|
| 343 | + 'LIN_total' => $sign * $price_total, |
|
| 344 | + 'LIN_type' => EEM_Line_Item::type_sub_line_item, |
|
| 345 | + 'OBJ_ID' => $price->ID(), |
|
| 346 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PRICE, |
|
| 347 | + )); |
|
| 348 | + $sub_line_item = apply_filters( |
|
| 349 | + 'FHEE__EEH_Line_Item__create_ticket_line_item__sub_line_item', |
|
| 350 | + $sub_line_item |
|
| 351 | + ); |
|
| 352 | + if ($price->is_percent()) { |
|
| 353 | + $sub_line_item->set_percent($sign * $price->amount()); |
|
| 354 | + } else { |
|
| 355 | + $sub_line_item->set_unit_price($sign * $price->amount()); |
|
| 356 | + } |
|
| 357 | + $running_total_for_ticket += $price_total; |
|
| 358 | + $line_item->add_child_line_item($sub_line_item); |
|
| 359 | + } |
|
| 360 | + return $line_item; |
|
| 361 | + } |
|
| 362 | + |
|
| 363 | + |
|
| 364 | + /** |
|
| 365 | + * Adds the specified item under the pre-tax-sub-total line item. Automatically |
|
| 366 | + * re-calculates the line item totals and updates the related transaction. But |
|
| 367 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 368 | + * should probably change because of this). |
|
| 369 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 370 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 371 | + * |
|
| 372 | + * @param EE_Line_Item $total_line_item |
|
| 373 | + * @param EE_Line_Item $item to be added |
|
| 374 | + * @return boolean |
|
| 375 | + * @throws EE_Error |
|
| 376 | + * @throws InvalidArgumentException |
|
| 377 | + * @throws InvalidDataTypeException |
|
| 378 | + * @throws InvalidInterfaceException |
|
| 379 | + * @throws ReflectionException |
|
| 380 | + */ |
|
| 381 | + public static function add_item(EE_Line_Item $total_line_item, EE_Line_Item $item) |
|
| 382 | + { |
|
| 383 | + $pre_tax_subtotal = self::get_pre_tax_subtotal($total_line_item); |
|
| 384 | + if ($pre_tax_subtotal instanceof EE_Line_Item) { |
|
| 385 | + $success = $pre_tax_subtotal->add_child_line_item($item); |
|
| 386 | + } else { |
|
| 387 | + return false; |
|
| 388 | + } |
|
| 389 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 390 | + return $success; |
|
| 391 | + } |
|
| 392 | + |
|
| 393 | + |
|
| 394 | + /** |
|
| 395 | + * cancels an existing ticket line item, |
|
| 396 | + * by decrementing it's quantity by 1 and adding a new "type_cancellation" sub-line-item. |
|
| 397 | + * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 398 | + * |
|
| 399 | + * @param EE_Line_Item $ticket_line_item |
|
| 400 | + * @param int $qty |
|
| 401 | + * @return bool success |
|
| 402 | + * @throws EE_Error |
|
| 403 | + * @throws InvalidArgumentException |
|
| 404 | + * @throws InvalidDataTypeException |
|
| 405 | + * @throws InvalidInterfaceException |
|
| 406 | + * @throws ReflectionException |
|
| 407 | + */ |
|
| 408 | + public static function cancel_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 409 | + { |
|
| 410 | + // validate incoming line_item |
|
| 411 | + if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 412 | + throw new EE_Error( |
|
| 413 | + sprintf( |
|
| 414 | + esc_html__( |
|
| 415 | + 'The supplied line item must have an Object Type of "Ticket", not %1$s.', |
|
| 416 | + 'event_espresso' |
|
| 417 | + ), |
|
| 418 | + $ticket_line_item->type() |
|
| 419 | + ) |
|
| 420 | + ); |
|
| 421 | + } |
|
| 422 | + if ($ticket_line_item->quantity() < $qty) { |
|
| 423 | + throw new EE_Error( |
|
| 424 | + sprintf( |
|
| 425 | + esc_html__( |
|
| 426 | + 'Can not cancel %1$d ticket(s) because the supplied line item has a quantity of %2$d.', |
|
| 427 | + 'event_espresso' |
|
| 428 | + ), |
|
| 429 | + $qty, |
|
| 430 | + $ticket_line_item->quantity() |
|
| 431 | + ) |
|
| 432 | + ); |
|
| 433 | + } |
|
| 434 | + // decrement ticket quantity; don't rely on auto-fixing when recalculating totals to do this |
|
| 435 | + $ticket_line_item->set_quantity($ticket_line_item->quantity() - $qty); |
|
| 436 | + foreach ($ticket_line_item->children() as $child_line_item) { |
|
| 437 | + if ($child_line_item->is_sub_line_item() |
|
| 438 | + && ! $child_line_item->is_percent() |
|
| 439 | + && ! $child_line_item->is_cancellation() |
|
| 440 | + ) { |
|
| 441 | + $child_line_item->set_quantity($child_line_item->quantity() - $qty); |
|
| 442 | + } |
|
| 443 | + } |
|
| 444 | + // get cancellation sub line item |
|
| 445 | + $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 446 | + $ticket_line_item, |
|
| 447 | + EEM_Line_Item::type_cancellation |
|
| 448 | + ); |
|
| 449 | + $cancellation_line_item = reset($cancellation_line_item); |
|
| 450 | + // verify that this ticket was indeed previously cancelled |
|
| 451 | + if ($cancellation_line_item instanceof EE_Line_Item) { |
|
| 452 | + // increment cancelled quantity |
|
| 453 | + $cancellation_line_item->set_quantity($cancellation_line_item->quantity() + $qty); |
|
| 454 | + } else { |
|
| 455 | + // create cancellation sub line item |
|
| 456 | + $cancellation_line_item = EE_Line_Item::new_instance(array( |
|
| 457 | + 'LIN_name' => esc_html__('Cancellation', 'event_espresso'), |
|
| 458 | + 'LIN_desc' => sprintf( |
|
| 459 | + esc_html_x( |
|
| 460 | + 'Cancelled %1$s : %2$s', |
|
| 461 | + 'Cancelled Ticket Name : 2015-01-01 11:11', |
|
| 462 | + 'event_espresso' |
|
| 463 | + ), |
|
| 464 | + $ticket_line_item->name(), |
|
| 465 | + current_time(get_option('date_format') . ' ' . get_option('time_format')) |
|
| 466 | + ), |
|
| 467 | + 'LIN_unit_price' => 0, // $ticket_line_item->unit_price() |
|
| 468 | + 'LIN_quantity' => $qty, |
|
| 469 | + 'LIN_is_taxable' => $ticket_line_item->is_taxable(), |
|
| 470 | + 'LIN_order' => count($ticket_line_item->children()), |
|
| 471 | + 'LIN_total' => 0, // $ticket_line_item->unit_price() |
|
| 472 | + 'LIN_type' => EEM_Line_Item::type_cancellation, |
|
| 473 | + )); |
|
| 474 | + $ticket_line_item->add_child_line_item($cancellation_line_item); |
|
| 475 | + } |
|
| 476 | + if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 477 | + // decrement parent line item quantity |
|
| 478 | + $event_line_item = $ticket_line_item->parent(); |
|
| 479 | + if ($event_line_item instanceof EE_Line_Item |
|
| 480 | + && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT |
|
| 481 | + ) { |
|
| 482 | + $event_line_item->set_quantity($event_line_item->quantity() - $qty); |
|
| 483 | + $event_line_item->save(); |
|
| 484 | + } |
|
| 485 | + EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 486 | + return true; |
|
| 487 | + } |
|
| 488 | + return false; |
|
| 489 | + } |
|
| 490 | + |
|
| 491 | + |
|
| 492 | + /** |
|
| 493 | + * reinstates (un-cancels?) a previously canceled ticket line item, |
|
| 494 | + * by incrementing it's quantity by 1, and decrementing it's "type_cancellation" sub-line-item. |
|
| 495 | + * ALL totals and subtotals will NEED TO BE UPDATED after performing this action |
|
| 496 | + * |
|
| 497 | + * @param EE_Line_Item $ticket_line_item |
|
| 498 | + * @param int $qty |
|
| 499 | + * @return bool success |
|
| 500 | + * @throws EE_Error |
|
| 501 | + * @throws InvalidArgumentException |
|
| 502 | + * @throws InvalidDataTypeException |
|
| 503 | + * @throws InvalidInterfaceException |
|
| 504 | + * @throws ReflectionException |
|
| 505 | + */ |
|
| 506 | + public static function reinstate_canceled_ticket_line_item(EE_Line_Item $ticket_line_item, $qty = 1) |
|
| 507 | + { |
|
| 508 | + // validate incoming line_item |
|
| 509 | + if ($ticket_line_item->OBJ_type() !== EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 510 | + throw new EE_Error( |
|
| 511 | + sprintf( |
|
| 512 | + esc_html__( |
|
| 513 | + 'The supplied line item must have an Object Type of "Ticket", not %1$s.', |
|
| 514 | + 'event_espresso' |
|
| 515 | + ), |
|
| 516 | + $ticket_line_item->type() |
|
| 517 | + ) |
|
| 518 | + ); |
|
| 519 | + } |
|
| 520 | + // get cancellation sub line item |
|
| 521 | + $cancellation_line_item = EEH_Line_Item::get_descendants_of_type( |
|
| 522 | + $ticket_line_item, |
|
| 523 | + EEM_Line_Item::type_cancellation |
|
| 524 | + ); |
|
| 525 | + $cancellation_line_item = reset($cancellation_line_item); |
|
| 526 | + // verify that this ticket was indeed previously cancelled |
|
| 527 | + if (! $cancellation_line_item instanceof EE_Line_Item) { |
|
| 528 | + return false; |
|
| 529 | + } |
|
| 530 | + if ($cancellation_line_item->quantity() > $qty) { |
|
| 531 | + // decrement cancelled quantity |
|
| 532 | + $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 533 | + } elseif ($cancellation_line_item->quantity() === $qty) { |
|
| 534 | + // decrement cancelled quantity in case anyone still has the object kicking around |
|
| 535 | + $cancellation_line_item->set_quantity($cancellation_line_item->quantity() - $qty); |
|
| 536 | + // delete because quantity will end up as 0 |
|
| 537 | + $cancellation_line_item->delete(); |
|
| 538 | + // and attempt to destroy the object, |
|
| 539 | + // even though PHP won't actually destroy it until it needs the memory |
|
| 540 | + unset($cancellation_line_item); |
|
| 541 | + } else { |
|
| 542 | + // what ?!?! negative quantity ?!?! |
|
| 543 | + throw new EE_Error( |
|
| 544 | + sprintf( |
|
| 545 | + esc_html__( |
|
| 546 | + 'Can not reinstate %1$d cancelled ticket(s) because the cancelled ticket quantity is only %2$d.', |
|
| 547 | + 'event_espresso' |
|
| 548 | + ), |
|
| 549 | + $qty, |
|
| 550 | + $cancellation_line_item->quantity() |
|
| 551 | + ) |
|
| 552 | + ); |
|
| 553 | + } |
|
| 554 | + // increment ticket quantity |
|
| 555 | + $ticket_line_item->set_quantity($ticket_line_item->quantity() + $qty); |
|
| 556 | + if ($ticket_line_item->save_this_and_descendants() > 0) { |
|
| 557 | + // increment parent line item quantity |
|
| 558 | + $event_line_item = $ticket_line_item->parent(); |
|
| 559 | + if ($event_line_item instanceof EE_Line_Item |
|
| 560 | + && $event_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT |
|
| 561 | + ) { |
|
| 562 | + $event_line_item->set_quantity($event_line_item->quantity() + $qty); |
|
| 563 | + } |
|
| 564 | + EEH_Line_Item::get_grand_total_and_recalculate_everything($ticket_line_item); |
|
| 565 | + return true; |
|
| 566 | + } |
|
| 567 | + return false; |
|
| 568 | + } |
|
| 569 | + |
|
| 570 | + |
|
| 571 | + /** |
|
| 572 | + * calls EEH_Line_Item::find_transaction_grand_total_for_line_item() |
|
| 573 | + * then EE_Line_Item::recalculate_total_including_taxes() on the result |
|
| 574 | + * |
|
| 575 | + * @param EE_Line_Item $line_item |
|
| 576 | + * @return float |
|
| 577 | + * @throws EE_Error |
|
| 578 | + * @throws InvalidArgumentException |
|
| 579 | + * @throws InvalidDataTypeException |
|
| 580 | + * @throws InvalidInterfaceException |
|
| 581 | + * @throws ReflectionException |
|
| 582 | + */ |
|
| 583 | + public static function get_grand_total_and_recalculate_everything(EE_Line_Item $line_item) |
|
| 584 | + { |
|
| 585 | + $grand_total_line_item = EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item); |
|
| 586 | + return $grand_total_line_item->recalculate_total_including_taxes(); |
|
| 587 | + } |
|
| 588 | + |
|
| 589 | + |
|
| 590 | + /** |
|
| 591 | + * Gets the line item which contains the subtotal of all the items |
|
| 592 | + * |
|
| 593 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 594 | + * @return EE_Line_Item |
|
| 595 | + * @throws EE_Error |
|
| 596 | + * @throws InvalidArgumentException |
|
| 597 | + * @throws InvalidDataTypeException |
|
| 598 | + * @throws InvalidInterfaceException |
|
| 599 | + * @throws ReflectionException |
|
| 600 | + */ |
|
| 601 | + public static function get_pre_tax_subtotal(EE_Line_Item $total_line_item) |
|
| 602 | + { |
|
| 603 | + $pre_tax_subtotal = $total_line_item->get_child_line_item('pre-tax-subtotal'); |
|
| 604 | + return $pre_tax_subtotal instanceof EE_Line_Item |
|
| 605 | + ? $pre_tax_subtotal |
|
| 606 | + : self::create_pre_tax_subtotal($total_line_item); |
|
| 607 | + } |
|
| 608 | + |
|
| 609 | + |
|
| 610 | + /** |
|
| 611 | + * Gets the line item for the taxes subtotal |
|
| 612 | + * |
|
| 613 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 614 | + * @return EE_Line_Item |
|
| 615 | + * @throws EE_Error |
|
| 616 | + * @throws InvalidArgumentException |
|
| 617 | + * @throws InvalidDataTypeException |
|
| 618 | + * @throws InvalidInterfaceException |
|
| 619 | + * @throws ReflectionException |
|
| 620 | + */ |
|
| 621 | + public static function get_taxes_subtotal(EE_Line_Item $total_line_item) |
|
| 622 | + { |
|
| 623 | + $taxes = $total_line_item->get_child_line_item('taxes'); |
|
| 624 | + return $taxes ? $taxes : self::create_taxes_subtotal($total_line_item); |
|
| 625 | + } |
|
| 626 | + |
|
| 627 | + |
|
| 628 | + /** |
|
| 629 | + * sets the TXN ID on an EE_Line_Item if passed a valid EE_Transaction object |
|
| 630 | + * |
|
| 631 | + * @param EE_Line_Item $line_item |
|
| 632 | + * @param EE_Transaction $transaction |
|
| 633 | + * @return void |
|
| 634 | + * @throws EE_Error |
|
| 635 | + * @throws InvalidArgumentException |
|
| 636 | + * @throws InvalidDataTypeException |
|
| 637 | + * @throws InvalidInterfaceException |
|
| 638 | + * @throws ReflectionException |
|
| 639 | + */ |
|
| 640 | + public static function set_TXN_ID(EE_Line_Item $line_item, $transaction = null) |
|
| 641 | + { |
|
| 642 | + if ($transaction) { |
|
| 643 | + /** @type EEM_Transaction $EEM_Transaction */ |
|
| 644 | + $EEM_Transaction = EE_Registry::instance()->load_model('Transaction'); |
|
| 645 | + $TXN_ID = $EEM_Transaction->ensure_is_ID($transaction); |
|
| 646 | + $line_item->set_TXN_ID($TXN_ID); |
|
| 647 | + } |
|
| 648 | + } |
|
| 649 | + |
|
| 650 | + |
|
| 651 | + /** |
|
| 652 | + * Creates a new default total line item for the transaction, |
|
| 653 | + * and its tickets subtotal and taxes subtotal line items (and adds the |
|
| 654 | + * existing taxes as children of the taxes subtotal line item) |
|
| 655 | + * |
|
| 656 | + * @param EE_Transaction $transaction |
|
| 657 | + * @return EE_Line_Item of type total |
|
| 658 | + * @throws EE_Error |
|
| 659 | + * @throws InvalidArgumentException |
|
| 660 | + * @throws InvalidDataTypeException |
|
| 661 | + * @throws InvalidInterfaceException |
|
| 662 | + * @throws ReflectionException |
|
| 663 | + */ |
|
| 664 | + public static function create_total_line_item($transaction = null) |
|
| 665 | + { |
|
| 666 | + $total_line_item = EE_Line_Item::new_instance(array( |
|
| 667 | + 'LIN_code' => 'total', |
|
| 668 | + 'LIN_name' => esc_html__('Grand Total', 'event_espresso'), |
|
| 669 | + 'LIN_type' => EEM_Line_Item::type_total, |
|
| 670 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TRANSACTION, |
|
| 671 | + )); |
|
| 672 | + $total_line_item = apply_filters( |
|
| 673 | + 'FHEE__EEH_Line_Item__create_total_line_item__total_line_item', |
|
| 674 | + $total_line_item |
|
| 675 | + ); |
|
| 676 | + self::set_TXN_ID($total_line_item, $transaction); |
|
| 677 | + self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 678 | + self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 679 | + return $total_line_item; |
|
| 680 | + } |
|
| 681 | + |
|
| 682 | + |
|
| 683 | + /** |
|
| 684 | + * Creates a default items subtotal line item |
|
| 685 | + * |
|
| 686 | + * @param EE_Line_Item $total_line_item |
|
| 687 | + * @param EE_Transaction $transaction |
|
| 688 | + * @return EE_Line_Item |
|
| 689 | + * @throws EE_Error |
|
| 690 | + * @throws InvalidArgumentException |
|
| 691 | + * @throws InvalidDataTypeException |
|
| 692 | + * @throws InvalidInterfaceException |
|
| 693 | + * @throws ReflectionException |
|
| 694 | + */ |
|
| 695 | + protected static function create_pre_tax_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 696 | + { |
|
| 697 | + $pre_tax_line_item = EE_Line_Item::new_instance(array( |
|
| 698 | + 'LIN_code' => 'pre-tax-subtotal', |
|
| 699 | + 'LIN_name' => esc_html__('Pre-Tax Subtotal', 'event_espresso'), |
|
| 700 | + 'LIN_type' => EEM_Line_Item::type_sub_total, |
|
| 701 | + )); |
|
| 702 | + $pre_tax_line_item = apply_filters( |
|
| 703 | + 'FHEE__EEH_Line_Item__create_pre_tax_subtotal__pre_tax_line_item', |
|
| 704 | + $pre_tax_line_item |
|
| 705 | + ); |
|
| 706 | + self::set_TXN_ID($pre_tax_line_item, $transaction); |
|
| 707 | + $total_line_item->add_child_line_item($pre_tax_line_item); |
|
| 708 | + self::create_event_subtotal($pre_tax_line_item, $transaction); |
|
| 709 | + return $pre_tax_line_item; |
|
| 710 | + } |
|
| 711 | + |
|
| 712 | + |
|
| 713 | + /** |
|
| 714 | + * Creates a line item for the taxes subtotal and finds all the tax prices |
|
| 715 | + * and applies taxes to it |
|
| 716 | + * |
|
| 717 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 718 | + * @param EE_Transaction $transaction |
|
| 719 | + * @return EE_Line_Item |
|
| 720 | + * @throws EE_Error |
|
| 721 | + * @throws InvalidArgumentException |
|
| 722 | + * @throws InvalidDataTypeException |
|
| 723 | + * @throws InvalidInterfaceException |
|
| 724 | + * @throws ReflectionException |
|
| 725 | + */ |
|
| 726 | + protected static function create_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 727 | + { |
|
| 728 | + $tax_line_item = EE_Line_Item::new_instance(array( |
|
| 729 | + 'LIN_code' => 'taxes', |
|
| 730 | + 'LIN_name' => esc_html__('Taxes', 'event_espresso'), |
|
| 731 | + 'LIN_type' => EEM_Line_Item::type_tax_sub_total, |
|
| 732 | + 'LIN_order' => 1000,// this should always come last |
|
| 733 | + )); |
|
| 734 | + $tax_line_item = apply_filters( |
|
| 735 | + 'FHEE__EEH_Line_Item__create_taxes_subtotal__tax_line_item', |
|
| 736 | + $tax_line_item |
|
| 737 | + ); |
|
| 738 | + self::set_TXN_ID($tax_line_item, $transaction); |
|
| 739 | + $total_line_item->add_child_line_item($tax_line_item); |
|
| 740 | + // and lastly, add the actual taxes |
|
| 741 | + self::apply_taxes($total_line_item); |
|
| 742 | + return $tax_line_item; |
|
| 743 | + } |
|
| 744 | + |
|
| 745 | + |
|
| 746 | + /** |
|
| 747 | + * Creates a default items subtotal line item |
|
| 748 | + * |
|
| 749 | + * @param EE_Line_Item $pre_tax_line_item |
|
| 750 | + * @param EE_Transaction $transaction |
|
| 751 | + * @param EE_Event $event |
|
| 752 | + * @return EE_Line_Item |
|
| 753 | + * @throws EE_Error |
|
| 754 | + * @throws InvalidArgumentException |
|
| 755 | + * @throws InvalidDataTypeException |
|
| 756 | + * @throws InvalidInterfaceException |
|
| 757 | + * @throws ReflectionException |
|
| 758 | + */ |
|
| 759 | + public static function create_event_subtotal(EE_Line_Item $pre_tax_line_item, $transaction = null, $event = null) |
|
| 760 | + { |
|
| 761 | + $event_line_item = EE_Line_Item::new_instance(array( |
|
| 762 | + 'LIN_code' => self::get_event_code($event), |
|
| 763 | + 'LIN_name' => self::get_event_name($event), |
|
| 764 | + 'LIN_desc' => self::get_event_desc($event), |
|
| 765 | + 'LIN_type' => EEM_Line_Item::type_sub_total, |
|
| 766 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_EVENT, |
|
| 767 | + 'OBJ_ID' => $event instanceof EE_Event ? $event->ID() : 0, |
|
| 768 | + )); |
|
| 769 | + $event_line_item = apply_filters( |
|
| 770 | + 'FHEE__EEH_Line_Item__create_event_subtotal__event_line_item', |
|
| 771 | + $event_line_item |
|
| 772 | + ); |
|
| 773 | + self::set_TXN_ID($event_line_item, $transaction); |
|
| 774 | + $pre_tax_line_item->add_child_line_item($event_line_item); |
|
| 775 | + return $event_line_item; |
|
| 776 | + } |
|
| 777 | + |
|
| 778 | + |
|
| 779 | + /** |
|
| 780 | + * Gets what the event ticket's code SHOULD be |
|
| 781 | + * |
|
| 782 | + * @param EE_Event $event |
|
| 783 | + * @return string |
|
| 784 | + * @throws EE_Error |
|
| 785 | + */ |
|
| 786 | + public static function get_event_code($event) |
|
| 787 | + { |
|
| 788 | + return 'event-' . ($event instanceof EE_Event ? $event->ID() : '0'); |
|
| 789 | + } |
|
| 790 | + |
|
| 791 | + |
|
| 792 | + /** |
|
| 793 | + * Gets the event name |
|
| 794 | + * |
|
| 795 | + * @param EE_Event $event |
|
| 796 | + * @return string |
|
| 797 | + * @throws EE_Error |
|
| 798 | + */ |
|
| 799 | + public static function get_event_name($event) |
|
| 800 | + { |
|
| 801 | + return $event instanceof EE_Event |
|
| 802 | + ? mb_substr($event->name(), 0, 245) |
|
| 803 | + : esc_html__('Event', 'event_espresso'); |
|
| 804 | + } |
|
| 805 | + |
|
| 806 | + |
|
| 807 | + /** |
|
| 808 | + * Gets the event excerpt |
|
| 809 | + * |
|
| 810 | + * @param EE_Event $event |
|
| 811 | + * @return string |
|
| 812 | + * @throws EE_Error |
|
| 813 | + */ |
|
| 814 | + public static function get_event_desc($event) |
|
| 815 | + { |
|
| 816 | + return $event instanceof EE_Event ? $event->short_description() : ''; |
|
| 817 | + } |
|
| 818 | + |
|
| 819 | + |
|
| 820 | + /** |
|
| 821 | + * Given the grand total line item and a ticket, finds the event sub-total |
|
| 822 | + * line item the ticket's purchase should be added onto |
|
| 823 | + * |
|
| 824 | + * @access public |
|
| 825 | + * @param EE_Line_Item $grand_total the grand total line item |
|
| 826 | + * @param EE_Ticket $ticket |
|
| 827 | + * @return EE_Line_Item |
|
| 828 | + * @throws EE_Error |
|
| 829 | + * @throws InvalidArgumentException |
|
| 830 | + * @throws InvalidDataTypeException |
|
| 831 | + * @throws InvalidInterfaceException |
|
| 832 | + * @throws ReflectionException |
|
| 833 | + */ |
|
| 834 | + public static function get_event_line_item_for_ticket(EE_Line_Item $grand_total, EE_Ticket $ticket) |
|
| 835 | + { |
|
| 836 | + $first_datetime = $ticket->first_datetime(); |
|
| 837 | + if (! $first_datetime instanceof EE_Datetime) { |
|
| 838 | + throw new EE_Error( |
|
| 839 | + sprintf( |
|
| 840 | + __('The supplied ticket (ID %d) has no datetimes', 'event_espresso'), |
|
| 841 | + $ticket->ID() |
|
| 842 | + ) |
|
| 843 | + ); |
|
| 844 | + } |
|
| 845 | + $event = $first_datetime->event(); |
|
| 846 | + if (! $event instanceof EE_Event) { |
|
| 847 | + throw new EE_Error( |
|
| 848 | + sprintf( |
|
| 849 | + esc_html__( |
|
| 850 | + 'The supplied ticket (ID %d) has no event data associated with it.', |
|
| 851 | + 'event_espresso' |
|
| 852 | + ), |
|
| 853 | + $ticket->ID() |
|
| 854 | + ) |
|
| 855 | + ); |
|
| 856 | + } |
|
| 857 | + $events_sub_total = EEH_Line_Item::get_event_line_item($grand_total, $event); |
|
| 858 | + if (! $events_sub_total instanceof EE_Line_Item) { |
|
| 859 | + throw new EE_Error( |
|
| 860 | + sprintf( |
|
| 861 | + esc_html__( |
|
| 862 | + 'There is no events sub-total for ticket %s on total line item %d', |
|
| 863 | + 'event_espresso' |
|
| 864 | + ), |
|
| 865 | + $ticket->ID(), |
|
| 866 | + $grand_total->ID() |
|
| 867 | + ) |
|
| 868 | + ); |
|
| 869 | + } |
|
| 870 | + return $events_sub_total; |
|
| 871 | + } |
|
| 872 | + |
|
| 873 | + |
|
| 874 | + /** |
|
| 875 | + * Gets the event line item |
|
| 876 | + * |
|
| 877 | + * @param EE_Line_Item $grand_total |
|
| 878 | + * @param EE_Event $event |
|
| 879 | + * @return EE_Line_Item for the event subtotal which is a child of $grand_total |
|
| 880 | + * @throws EE_Error |
|
| 881 | + * @throws InvalidArgumentException |
|
| 882 | + * @throws InvalidDataTypeException |
|
| 883 | + * @throws InvalidInterfaceException |
|
| 884 | + * @throws ReflectionException |
|
| 885 | + */ |
|
| 886 | + public static function get_event_line_item(EE_Line_Item $grand_total, $event) |
|
| 887 | + { |
|
| 888 | + /** @type EE_Event $event */ |
|
| 889 | + $event = EEM_Event::instance()->ensure_is_obj($event, true); |
|
| 890 | + $event_line_item = null; |
|
| 891 | + $found = false; |
|
| 892 | + foreach (EEH_Line_Item::get_event_subtotals($grand_total) as $event_line_item) { |
|
| 893 | + // default event subtotal, we should only ever find this the first time this method is called |
|
| 894 | + if (! $event_line_item->OBJ_ID()) { |
|
| 895 | + // let's use this! but first... set the event details |
|
| 896 | + EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 897 | + $found = true; |
|
| 898 | + break; |
|
| 899 | + } |
|
| 900 | + if ($event_line_item->OBJ_ID() === $event->ID()) { |
|
| 901 | + // found existing line item for this event in the cart, so break out of loop and use this one |
|
| 902 | + $found = true; |
|
| 903 | + break; |
|
| 904 | + } |
|
| 905 | + } |
|
| 906 | + if (! $found) { |
|
| 907 | + // there is no event sub-total yet, so add it |
|
| 908 | + $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal($grand_total); |
|
| 909 | + // create a new "event" subtotal below that |
|
| 910 | + $event_line_item = EEH_Line_Item::create_event_subtotal($pre_tax_subtotal, null, $event); |
|
| 911 | + // and set the event details |
|
| 912 | + EEH_Line_Item::set_event_subtotal_details($event_line_item, $event); |
|
| 913 | + } |
|
| 914 | + return $event_line_item; |
|
| 915 | + } |
|
| 916 | + |
|
| 917 | + |
|
| 918 | + /** |
|
| 919 | + * Creates a default items subtotal line item |
|
| 920 | + * |
|
| 921 | + * @param EE_Line_Item $event_line_item |
|
| 922 | + * @param EE_Event $event |
|
| 923 | + * @param EE_Transaction $transaction |
|
| 924 | + * @return void |
|
| 925 | + * @throws EE_Error |
|
| 926 | + * @throws InvalidArgumentException |
|
| 927 | + * @throws InvalidDataTypeException |
|
| 928 | + * @throws InvalidInterfaceException |
|
| 929 | + * @throws ReflectionException |
|
| 930 | + */ |
|
| 931 | + public static function set_event_subtotal_details( |
|
| 932 | + EE_Line_Item $event_line_item, |
|
| 933 | + EE_Event $event, |
|
| 934 | + $transaction = null |
|
| 935 | + ) { |
|
| 936 | + if ($event instanceof EE_Event) { |
|
| 937 | + $event_line_item->set_code(self::get_event_code($event)); |
|
| 938 | + $event_line_item->set_name(self::get_event_name($event)); |
|
| 939 | + $event_line_item->set_desc(self::get_event_desc($event)); |
|
| 940 | + $event_line_item->set_OBJ_ID($event->ID()); |
|
| 941 | + } |
|
| 942 | + self::set_TXN_ID($event_line_item, $transaction); |
|
| 943 | + } |
|
| 944 | + |
|
| 945 | + |
|
| 946 | + /** |
|
| 947 | + * Finds what taxes should apply, adds them as tax line items under the taxes sub-total, |
|
| 948 | + * and recalculates the taxes sub-total and the grand total. Resets the taxes, so |
|
| 949 | + * any old taxes are removed |
|
| 950 | + * |
|
| 951 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 952 | + * @param bool $update_txn_status |
|
| 953 | + * @return bool |
|
| 954 | + * @throws EE_Error |
|
| 955 | + * @throws InvalidArgumentException |
|
| 956 | + * @throws InvalidDataTypeException |
|
| 957 | + * @throws InvalidInterfaceException |
|
| 958 | + * @throws ReflectionException |
|
| 959 | + * @throws RuntimeException |
|
| 960 | + */ |
|
| 961 | + public static function apply_taxes(EE_Line_Item $total_line_item, $update_txn_status = false) |
|
| 962 | + { |
|
| 963 | + /** @type EEM_Price $EEM_Price */ |
|
| 964 | + $EEM_Price = EE_Registry::instance()->load_model('Price'); |
|
| 965 | + // get array of taxes via Price Model |
|
| 966 | + $ordered_taxes = $EEM_Price->get_all_prices_that_are_taxes(); |
|
| 967 | + ksort($ordered_taxes); |
|
| 968 | + $taxes_line_item = self::get_taxes_subtotal($total_line_item); |
|
| 969 | + // just to be safe, remove its old tax line items |
|
| 970 | + $deleted = $taxes_line_item->delete_children_line_items(); |
|
| 971 | + $updates = false; |
|
| 972 | + // loop thru taxes |
|
| 973 | + foreach ($ordered_taxes as $order => $taxes) { |
|
| 974 | + foreach ($taxes as $tax) { |
|
| 975 | + if ($tax instanceof EE_Price) { |
|
| 976 | + $tax_line_item = EE_Line_Item::new_instance( |
|
| 977 | + array( |
|
| 978 | + 'LIN_name' => $tax->name(), |
|
| 979 | + 'LIN_desc' => $tax->desc(), |
|
| 980 | + 'LIN_percent' => $tax->amount(), |
|
| 981 | + 'LIN_is_taxable' => false, |
|
| 982 | + 'LIN_order' => $order, |
|
| 983 | + 'LIN_total' => 0, |
|
| 984 | + 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 985 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PRICE, |
|
| 986 | + 'OBJ_ID' => $tax->ID(), |
|
| 987 | + ) |
|
| 988 | + ); |
|
| 989 | + $tax_line_item = apply_filters( |
|
| 990 | + 'FHEE__EEH_Line_Item__apply_taxes__tax_line_item', |
|
| 991 | + $tax_line_item |
|
| 992 | + ); |
|
| 993 | + $updates = $taxes_line_item->add_child_line_item($tax_line_item) ? |
|
| 994 | + true : |
|
| 995 | + $updates; |
|
| 996 | + } |
|
| 997 | + } |
|
| 998 | + } |
|
| 999 | + // only recalculate totals if something changed |
|
| 1000 | + if ($deleted || $updates) { |
|
| 1001 | + $total_line_item->recalculate_total_including_taxes($update_txn_status); |
|
| 1002 | + return true; |
|
| 1003 | + } |
|
| 1004 | + return false; |
|
| 1005 | + } |
|
| 1006 | + |
|
| 1007 | + |
|
| 1008 | + /** |
|
| 1009 | + * Ensures that taxes have been applied to the order, if not applies them. |
|
| 1010 | + * Returns the total amount of tax |
|
| 1011 | + * |
|
| 1012 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 1013 | + * @return float |
|
| 1014 | + * @throws EE_Error |
|
| 1015 | + * @throws InvalidArgumentException |
|
| 1016 | + * @throws InvalidDataTypeException |
|
| 1017 | + * @throws InvalidInterfaceException |
|
| 1018 | + * @throws ReflectionException |
|
| 1019 | + */ |
|
| 1020 | + public static function ensure_taxes_applied($total_line_item) |
|
| 1021 | + { |
|
| 1022 | + $taxes_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 1023 | + if (! $taxes_subtotal->children()) { |
|
| 1024 | + self::apply_taxes($total_line_item); |
|
| 1025 | + } |
|
| 1026 | + return $taxes_subtotal->total(); |
|
| 1027 | + } |
|
| 1028 | + |
|
| 1029 | + |
|
| 1030 | + /** |
|
| 1031 | + * Deletes ALL children of the passed line item |
|
| 1032 | + * |
|
| 1033 | + * @param EE_Line_Item $parent_line_item |
|
| 1034 | + * @return bool |
|
| 1035 | + * @throws EE_Error |
|
| 1036 | + * @throws InvalidArgumentException |
|
| 1037 | + * @throws InvalidDataTypeException |
|
| 1038 | + * @throws InvalidInterfaceException |
|
| 1039 | + * @throws ReflectionException |
|
| 1040 | + */ |
|
| 1041 | + public static function delete_all_child_items(EE_Line_Item $parent_line_item) |
|
| 1042 | + { |
|
| 1043 | + $deleted = 0; |
|
| 1044 | + foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1045 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1046 | + $deleted += EEH_Line_Item::delete_all_child_items($child_line_item); |
|
| 1047 | + if ($child_line_item->ID()) { |
|
| 1048 | + $child_line_item->delete(); |
|
| 1049 | + unset($child_line_item); |
|
| 1050 | + } else { |
|
| 1051 | + $parent_line_item->delete_child_line_item($child_line_item->code()); |
|
| 1052 | + } |
|
| 1053 | + $deleted++; |
|
| 1054 | + } |
|
| 1055 | + } |
|
| 1056 | + return $deleted; |
|
| 1057 | + } |
|
| 1058 | + |
|
| 1059 | + |
|
| 1060 | + /** |
|
| 1061 | + * Deletes the line items as indicated by the line item code(s) provided, |
|
| 1062 | + * regardless of where they're found in the line item tree. Automatically |
|
| 1063 | + * re-calculates the line item totals and updates the related transaction. But |
|
| 1064 | + * DOES NOT automatically upgrade the transaction's registrations' final prices (which |
|
| 1065 | + * should probably change because of this). |
|
| 1066 | + * You should call EE_Registration_Processor::calculate_reg_final_prices_per_line_item() |
|
| 1067 | + * after using this, to keep the registration final prices in-sync with the transaction's total. |
|
| 1068 | + * |
|
| 1069 | + * @param EE_Line_Item $total_line_item of type EEM_Line_Item::type_total |
|
| 1070 | + * @param array|bool|string $line_item_codes |
|
| 1071 | + * @return int number of items successfully removed |
|
| 1072 | + * @throws EE_Error |
|
| 1073 | + */ |
|
| 1074 | + public static function delete_items(EE_Line_Item $total_line_item, $line_item_codes = false) |
|
| 1075 | + { |
|
| 1076 | + |
|
| 1077 | + if ($total_line_item->type() !== EEM_Line_Item::type_total) { |
|
| 1078 | + EE_Error::doing_it_wrong( |
|
| 1079 | + 'EEH_Line_Item::delete_items', |
|
| 1080 | + esc_html__( |
|
| 1081 | + 'This static method should only be called with a TOTAL line item, otherwise we won\'t recalculate the totals correctly', |
|
| 1082 | + 'event_espresso' |
|
| 1083 | + ), |
|
| 1084 | + '4.6.18' |
|
| 1085 | + ); |
|
| 1086 | + } |
|
| 1087 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 1088 | + |
|
| 1089 | + // check if only a single line_item_id was passed |
|
| 1090 | + if (! empty($line_item_codes) && ! is_array($line_item_codes)) { |
|
| 1091 | + // place single line_item_id in an array to appear as multiple line_item_ids |
|
| 1092 | + $line_item_codes = array($line_item_codes); |
|
| 1093 | + } |
|
| 1094 | + $removals = 0; |
|
| 1095 | + // cycle thru line_item_ids |
|
| 1096 | + foreach ($line_item_codes as $line_item_id) { |
|
| 1097 | + $removals += $total_line_item->delete_child_line_item($line_item_id); |
|
| 1098 | + } |
|
| 1099 | + |
|
| 1100 | + if ($removals > 0) { |
|
| 1101 | + $total_line_item->recalculate_taxes_and_tax_total(); |
|
| 1102 | + return $removals; |
|
| 1103 | + } else { |
|
| 1104 | + return false; |
|
| 1105 | + } |
|
| 1106 | + } |
|
| 1107 | + |
|
| 1108 | + |
|
| 1109 | + /** |
|
| 1110 | + * Overwrites the previous tax by clearing out the old taxes, and creates a new |
|
| 1111 | + * tax and updates the total line item accordingly |
|
| 1112 | + * |
|
| 1113 | + * @param EE_Line_Item $total_line_item |
|
| 1114 | + * @param float $amount |
|
| 1115 | + * @param string $name |
|
| 1116 | + * @param string $description |
|
| 1117 | + * @param string $code |
|
| 1118 | + * @param boolean $add_to_existing_line_item |
|
| 1119 | + * if true, and a duplicate line item with the same code is found, |
|
| 1120 | + * $amount will be added onto it; otherwise will simply set the taxes to match $amount |
|
| 1121 | + * @return EE_Line_Item the new tax line item created |
|
| 1122 | + * @throws EE_Error |
|
| 1123 | + * @throws InvalidArgumentException |
|
| 1124 | + * @throws InvalidDataTypeException |
|
| 1125 | + * @throws InvalidInterfaceException |
|
| 1126 | + * @throws ReflectionException |
|
| 1127 | + */ |
|
| 1128 | + public static function set_total_tax_to( |
|
| 1129 | + EE_Line_Item $total_line_item, |
|
| 1130 | + $amount, |
|
| 1131 | + $name = null, |
|
| 1132 | + $description = null, |
|
| 1133 | + $code = null, |
|
| 1134 | + $add_to_existing_line_item = false |
|
| 1135 | + ) { |
|
| 1136 | + $tax_subtotal = self::get_taxes_subtotal($total_line_item); |
|
| 1137 | + $taxable_total = $total_line_item->taxable_total(); |
|
| 1138 | + |
|
| 1139 | + if ($add_to_existing_line_item) { |
|
| 1140 | + $new_tax = $tax_subtotal->get_child_line_item($code); |
|
| 1141 | + EEM_Line_Item::instance()->delete( |
|
| 1142 | + array(array('LIN_code' => array('!=', $code), 'LIN_parent' => $tax_subtotal->ID())) |
|
| 1143 | + ); |
|
| 1144 | + } else { |
|
| 1145 | + $new_tax = null; |
|
| 1146 | + $tax_subtotal->delete_children_line_items(); |
|
| 1147 | + } |
|
| 1148 | + if ($new_tax) { |
|
| 1149 | + $new_tax->set_total($new_tax->total() + $amount); |
|
| 1150 | + $new_tax->set_percent($taxable_total ? $new_tax->total() / $taxable_total * 100 : 0); |
|
| 1151 | + } else { |
|
| 1152 | + // no existing tax item. Create it |
|
| 1153 | + $new_tax = EE_Line_Item::new_instance(array( |
|
| 1154 | + 'TXN_ID' => $total_line_item->TXN_ID(), |
|
| 1155 | + 'LIN_name' => $name ? $name : esc_html__('Tax', 'event_espresso'), |
|
| 1156 | + 'LIN_desc' => $description ? $description : '', |
|
| 1157 | + 'LIN_percent' => $taxable_total ? ($amount / $taxable_total * 100) : 0, |
|
| 1158 | + 'LIN_total' => $amount, |
|
| 1159 | + 'LIN_parent' => $tax_subtotal->ID(), |
|
| 1160 | + 'LIN_type' => EEM_Line_Item::type_tax, |
|
| 1161 | + 'LIN_code' => $code, |
|
| 1162 | + )); |
|
| 1163 | + } |
|
| 1164 | + |
|
| 1165 | + $new_tax = apply_filters( |
|
| 1166 | + 'FHEE__EEH_Line_Item__set_total_tax_to__new_tax_subtotal', |
|
| 1167 | + $new_tax, |
|
| 1168 | + $total_line_item |
|
| 1169 | + ); |
|
| 1170 | + $new_tax->save(); |
|
| 1171 | + $tax_subtotal->set_total($new_tax->total()); |
|
| 1172 | + $tax_subtotal->save(); |
|
| 1173 | + $total_line_item->recalculate_total_including_taxes(); |
|
| 1174 | + return $new_tax; |
|
| 1175 | + } |
|
| 1176 | + |
|
| 1177 | + |
|
| 1178 | + /** |
|
| 1179 | + * Makes all the line items which are children of $line_item taxable (or not). |
|
| 1180 | + * Does NOT save the line items |
|
| 1181 | + * |
|
| 1182 | + * @param EE_Line_Item $line_item |
|
| 1183 | + * @param boolean $taxable |
|
| 1184 | + * @param string $code_substring_for_whitelist if this string is part of the line item's code |
|
| 1185 | + * it will be whitelisted (ie, except from becoming taxable) |
|
| 1186 | + * @throws EE_Error |
|
| 1187 | + */ |
|
| 1188 | + public static function set_line_items_taxable( |
|
| 1189 | + EE_Line_Item $line_item, |
|
| 1190 | + $taxable = true, |
|
| 1191 | + $code_substring_for_whitelist = null |
|
| 1192 | + ) { |
|
| 1193 | + $whitelisted = false; |
|
| 1194 | + if ($code_substring_for_whitelist !== null) { |
|
| 1195 | + $whitelisted = strpos($line_item->code(), $code_substring_for_whitelist) !== false; |
|
| 1196 | + } |
|
| 1197 | + if (! $whitelisted && $line_item->is_line_item()) { |
|
| 1198 | + $line_item->set_is_taxable($taxable); |
|
| 1199 | + } |
|
| 1200 | + foreach ($line_item->children() as $child_line_item) { |
|
| 1201 | + EEH_Line_Item::set_line_items_taxable( |
|
| 1202 | + $child_line_item, |
|
| 1203 | + $taxable, |
|
| 1204 | + $code_substring_for_whitelist |
|
| 1205 | + ); |
|
| 1206 | + } |
|
| 1207 | + } |
|
| 1208 | + |
|
| 1209 | + |
|
| 1210 | + /** |
|
| 1211 | + * Gets all descendants that are event subtotals |
|
| 1212 | + * |
|
| 1213 | + * @uses EEH_Line_Item::get_subtotals_of_object_type() |
|
| 1214 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1215 | + * @return EE_Line_Item[] |
|
| 1216 | + * @throws EE_Error |
|
| 1217 | + */ |
|
| 1218 | + public static function get_event_subtotals(EE_Line_Item $parent_line_item) |
|
| 1219 | + { |
|
| 1220 | + return self::get_subtotals_of_object_type($parent_line_item, EEM_Line_Item::OBJ_TYPE_EVENT); |
|
| 1221 | + } |
|
| 1222 | + |
|
| 1223 | + |
|
| 1224 | + /** |
|
| 1225 | + * Gets all descendants subtotals that match the supplied object type |
|
| 1226 | + * |
|
| 1227 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1228 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1229 | + * @param string $obj_type |
|
| 1230 | + * @return EE_Line_Item[] |
|
| 1231 | + * @throws EE_Error |
|
| 1232 | + */ |
|
| 1233 | + public static function get_subtotals_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1234 | + { |
|
| 1235 | + return self::_get_descendants_by_type_and_object_type( |
|
| 1236 | + $parent_line_item, |
|
| 1237 | + EEM_Line_Item::type_sub_total, |
|
| 1238 | + $obj_type |
|
| 1239 | + ); |
|
| 1240 | + } |
|
| 1241 | + |
|
| 1242 | + |
|
| 1243 | + /** |
|
| 1244 | + * Gets all descendants that are tickets |
|
| 1245 | + * |
|
| 1246 | + * @uses EEH_Line_Item::get_line_items_of_object_type() |
|
| 1247 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1248 | + * @return EE_Line_Item[] |
|
| 1249 | + * @throws EE_Error |
|
| 1250 | + */ |
|
| 1251 | + public static function get_ticket_line_items(EE_Line_Item $parent_line_item) |
|
| 1252 | + { |
|
| 1253 | + return self::get_line_items_of_object_type( |
|
| 1254 | + $parent_line_item, |
|
| 1255 | + EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1256 | + ); |
|
| 1257 | + } |
|
| 1258 | + |
|
| 1259 | + |
|
| 1260 | + /** |
|
| 1261 | + * Gets all descendants subtotals that match the supplied object type |
|
| 1262 | + * |
|
| 1263 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1264 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1265 | + * @param string $obj_type |
|
| 1266 | + * @return EE_Line_Item[] |
|
| 1267 | + * @throws EE_Error |
|
| 1268 | + */ |
|
| 1269 | + public static function get_line_items_of_object_type(EE_Line_Item $parent_line_item, $obj_type = '') |
|
| 1270 | + { |
|
| 1271 | + return self::_get_descendants_by_type_and_object_type( |
|
| 1272 | + $parent_line_item, |
|
| 1273 | + EEM_Line_Item::type_line_item, |
|
| 1274 | + $obj_type |
|
| 1275 | + ); |
|
| 1276 | + } |
|
| 1277 | + |
|
| 1278 | + |
|
| 1279 | + /** |
|
| 1280 | + * Gets all the descendants (ie, children or children of children etc) that are of the type 'tax' |
|
| 1281 | + * |
|
| 1282 | + * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1283 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1284 | + * @return EE_Line_Item[] |
|
| 1285 | + * @throws EE_Error |
|
| 1286 | + */ |
|
| 1287 | + public static function get_tax_descendants(EE_Line_Item $parent_line_item) |
|
| 1288 | + { |
|
| 1289 | + return EEH_Line_Item::get_descendants_of_type( |
|
| 1290 | + $parent_line_item, |
|
| 1291 | + EEM_Line_Item::type_tax |
|
| 1292 | + ); |
|
| 1293 | + } |
|
| 1294 | + |
|
| 1295 | + |
|
| 1296 | + /** |
|
| 1297 | + * Gets all the real items purchased which are children of this item |
|
| 1298 | + * |
|
| 1299 | + * @uses EEH_Line_Item::get_descendants_of_type() |
|
| 1300 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1301 | + * @return EE_Line_Item[] |
|
| 1302 | + * @throws EE_Error |
|
| 1303 | + */ |
|
| 1304 | + public static function get_line_item_descendants(EE_Line_Item $parent_line_item) |
|
| 1305 | + { |
|
| 1306 | + return EEH_Line_Item::get_descendants_of_type( |
|
| 1307 | + $parent_line_item, |
|
| 1308 | + EEM_Line_Item::type_line_item |
|
| 1309 | + ); |
|
| 1310 | + } |
|
| 1311 | + |
|
| 1312 | + |
|
| 1313 | + /** |
|
| 1314 | + * Gets all descendants of supplied line item that match the supplied line item type |
|
| 1315 | + * |
|
| 1316 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1317 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1318 | + * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1319 | + * @return EE_Line_Item[] |
|
| 1320 | + * @throws EE_Error |
|
| 1321 | + */ |
|
| 1322 | + public static function get_descendants_of_type(EE_Line_Item $parent_line_item, $line_item_type) |
|
| 1323 | + { |
|
| 1324 | + return self::_get_descendants_by_type_and_object_type( |
|
| 1325 | + $parent_line_item, |
|
| 1326 | + $line_item_type, |
|
| 1327 | + null |
|
| 1328 | + ); |
|
| 1329 | + } |
|
| 1330 | + |
|
| 1331 | + |
|
| 1332 | + /** |
|
| 1333 | + * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type |
|
| 1334 | + * as well |
|
| 1335 | + * |
|
| 1336 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1337 | + * @param string $line_item_type one of the EEM_Line_Item constants |
|
| 1338 | + * @param string | NULL $obj_type object model class name (minus prefix) or NULL to ignore object type when |
|
| 1339 | + * searching |
|
| 1340 | + * @return EE_Line_Item[] |
|
| 1341 | + * @throws EE_Error |
|
| 1342 | + */ |
|
| 1343 | + protected static function _get_descendants_by_type_and_object_type( |
|
| 1344 | + EE_Line_Item $parent_line_item, |
|
| 1345 | + $line_item_type, |
|
| 1346 | + $obj_type = null |
|
| 1347 | + ) { |
|
| 1348 | + $objects = array(); |
|
| 1349 | + foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1350 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1351 | + if ($child_line_item->type() === $line_item_type |
|
| 1352 | + && ( |
|
| 1353 | + $child_line_item->OBJ_type() === $obj_type || $obj_type === null |
|
| 1354 | + ) |
|
| 1355 | + ) { |
|
| 1356 | + $objects[] = $child_line_item; |
|
| 1357 | + } else { |
|
| 1358 | + // go-through-all-its children looking for more matches |
|
| 1359 | + $objects = array_merge( |
|
| 1360 | + $objects, |
|
| 1361 | + self::_get_descendants_by_type_and_object_type( |
|
| 1362 | + $child_line_item, |
|
| 1363 | + $line_item_type, |
|
| 1364 | + $obj_type |
|
| 1365 | + ) |
|
| 1366 | + ); |
|
| 1367 | + } |
|
| 1368 | + } |
|
| 1369 | + } |
|
| 1370 | + return $objects; |
|
| 1371 | + } |
|
| 1372 | + |
|
| 1373 | + |
|
| 1374 | + /** |
|
| 1375 | + * Gets all descendants subtotals that match the supplied object type |
|
| 1376 | + * |
|
| 1377 | + * @uses EEH_Line_Item::_get_descendants_by_type_and_object_type() |
|
| 1378 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1379 | + * @param string $OBJ_type object type (like Event) |
|
| 1380 | + * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1381 | + * @return EE_Line_Item[] |
|
| 1382 | + * @throws EE_Error |
|
| 1383 | + */ |
|
| 1384 | + public static function get_line_items_by_object_type_and_IDs( |
|
| 1385 | + EE_Line_Item $parent_line_item, |
|
| 1386 | + $OBJ_type = '', |
|
| 1387 | + $OBJ_IDs = array() |
|
| 1388 | + ) { |
|
| 1389 | + return self::_get_descendants_by_object_type_and_object_ID( |
|
| 1390 | + $parent_line_item, |
|
| 1391 | + $OBJ_type, |
|
| 1392 | + $OBJ_IDs |
|
| 1393 | + ); |
|
| 1394 | + } |
|
| 1395 | + |
|
| 1396 | + |
|
| 1397 | + /** |
|
| 1398 | + * Gets all descendants of supplied line item that match the supplied line item type and possibly the object type |
|
| 1399 | + * as well |
|
| 1400 | + * |
|
| 1401 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1402 | + * @param string $OBJ_type object type (like Event) |
|
| 1403 | + * @param array $OBJ_IDs array of OBJ_IDs |
|
| 1404 | + * @return EE_Line_Item[] |
|
| 1405 | + * @throws EE_Error |
|
| 1406 | + */ |
|
| 1407 | + protected static function _get_descendants_by_object_type_and_object_ID( |
|
| 1408 | + EE_Line_Item $parent_line_item, |
|
| 1409 | + $OBJ_type, |
|
| 1410 | + $OBJ_IDs |
|
| 1411 | + ) { |
|
| 1412 | + $objects = array(); |
|
| 1413 | + foreach ($parent_line_item->children() as $child_line_item) { |
|
| 1414 | + if ($child_line_item instanceof EE_Line_Item) { |
|
| 1415 | + if ($child_line_item->OBJ_type() === $OBJ_type |
|
| 1416 | + && is_array($OBJ_IDs) |
|
| 1417 | + && in_array($child_line_item->OBJ_ID(), $OBJ_IDs) |
|
| 1418 | + ) { |
|
| 1419 | + $objects[] = $child_line_item; |
|
| 1420 | + } else { |
|
| 1421 | + // go-through-all-its children looking for more matches |
|
| 1422 | + $objects = array_merge( |
|
| 1423 | + $objects, |
|
| 1424 | + self::_get_descendants_by_object_type_and_object_ID( |
|
| 1425 | + $child_line_item, |
|
| 1426 | + $OBJ_type, |
|
| 1427 | + $OBJ_IDs |
|
| 1428 | + ) |
|
| 1429 | + ); |
|
| 1430 | + } |
|
| 1431 | + } |
|
| 1432 | + } |
|
| 1433 | + return $objects; |
|
| 1434 | + } |
|
| 1435 | + |
|
| 1436 | + |
|
| 1437 | + /** |
|
| 1438 | + * Uses a breadth-first-search in order to find the nearest descendant of |
|
| 1439 | + * the specified type and returns it, else NULL |
|
| 1440 | + * |
|
| 1441 | + * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1442 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1443 | + * @param string $type like one of the EEM_Line_Item::type_* |
|
| 1444 | + * @return EE_Line_Item |
|
| 1445 | + * @throws EE_Error |
|
| 1446 | + * @throws InvalidArgumentException |
|
| 1447 | + * @throws InvalidDataTypeException |
|
| 1448 | + * @throws InvalidInterfaceException |
|
| 1449 | + * @throws ReflectionException |
|
| 1450 | + */ |
|
| 1451 | + public static function get_nearest_descendant_of_type(EE_Line_Item $parent_line_item, $type) |
|
| 1452 | + { |
|
| 1453 | + return self::_get_nearest_descendant($parent_line_item, 'LIN_type', $type); |
|
| 1454 | + } |
|
| 1455 | + |
|
| 1456 | + |
|
| 1457 | + /** |
|
| 1458 | + * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1459 | + * having the specified LIN_code and returns it, else NULL |
|
| 1460 | + * |
|
| 1461 | + * @uses EEH_Line_Item::_get_nearest_descendant() |
|
| 1462 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1463 | + * @param string $code any value used for LIN_code |
|
| 1464 | + * @return EE_Line_Item |
|
| 1465 | + * @throws EE_Error |
|
| 1466 | + * @throws InvalidArgumentException |
|
| 1467 | + * @throws InvalidDataTypeException |
|
| 1468 | + * @throws InvalidInterfaceException |
|
| 1469 | + * @throws ReflectionException |
|
| 1470 | + */ |
|
| 1471 | + public static function get_nearest_descendant_having_code(EE_Line_Item $parent_line_item, $code) |
|
| 1472 | + { |
|
| 1473 | + return self::_get_nearest_descendant($parent_line_item, 'LIN_code', $code); |
|
| 1474 | + } |
|
| 1475 | + |
|
| 1476 | + |
|
| 1477 | + /** |
|
| 1478 | + * Uses a breadth-first-search in order to find the nearest descendant |
|
| 1479 | + * having the specified LIN_code and returns it, else NULL |
|
| 1480 | + * |
|
| 1481 | + * @param EE_Line_Item $parent_line_item - the line item to find descendants of |
|
| 1482 | + * @param string $search_field name of EE_Line_Item property |
|
| 1483 | + * @param string $value any value stored in $search_field |
|
| 1484 | + * @return EE_Line_Item |
|
| 1485 | + * @throws EE_Error |
|
| 1486 | + * @throws InvalidArgumentException |
|
| 1487 | + * @throws InvalidDataTypeException |
|
| 1488 | + * @throws InvalidInterfaceException |
|
| 1489 | + * @throws ReflectionException |
|
| 1490 | + */ |
|
| 1491 | + protected static function _get_nearest_descendant(EE_Line_Item $parent_line_item, $search_field, $value) |
|
| 1492 | + { |
|
| 1493 | + foreach ($parent_line_item->children() as $child) { |
|
| 1494 | + if ($child->get($search_field) == $value) { |
|
| 1495 | + return $child; |
|
| 1496 | + } |
|
| 1497 | + } |
|
| 1498 | + foreach ($parent_line_item->children() as $child) { |
|
| 1499 | + $descendant_found = self::_get_nearest_descendant( |
|
| 1500 | + $child, |
|
| 1501 | + $search_field, |
|
| 1502 | + $value |
|
| 1503 | + ); |
|
| 1504 | + if ($descendant_found) { |
|
| 1505 | + return $descendant_found; |
|
| 1506 | + } |
|
| 1507 | + } |
|
| 1508 | + return null; |
|
| 1509 | + } |
|
| 1510 | + |
|
| 1511 | + |
|
| 1512 | + /** |
|
| 1513 | + * if passed line item has a TXN ID, uses that to jump directly to the grand total line item for the transaction, |
|
| 1514 | + * else recursively walks up the line item tree until a parent of type total is found, |
|
| 1515 | + * |
|
| 1516 | + * @param EE_Line_Item $line_item |
|
| 1517 | + * @return EE_Line_Item |
|
| 1518 | + * @throws EE_Error |
|
| 1519 | + */ |
|
| 1520 | + public static function find_transaction_grand_total_for_line_item(EE_Line_Item $line_item) |
|
| 1521 | + { |
|
| 1522 | + if ($line_item->TXN_ID()) { |
|
| 1523 | + $total_line_item = $line_item->transaction()->total_line_item(false); |
|
| 1524 | + if ($total_line_item instanceof EE_Line_Item) { |
|
| 1525 | + return $total_line_item; |
|
| 1526 | + } |
|
| 1527 | + } else { |
|
| 1528 | + $line_item_parent = $line_item->parent(); |
|
| 1529 | + if ($line_item_parent instanceof EE_Line_Item) { |
|
| 1530 | + if ($line_item_parent->is_total()) { |
|
| 1531 | + return $line_item_parent; |
|
| 1532 | + } |
|
| 1533 | + return EEH_Line_Item::find_transaction_grand_total_for_line_item($line_item_parent); |
|
| 1534 | + } |
|
| 1535 | + } |
|
| 1536 | + throw new EE_Error( |
|
| 1537 | + sprintf( |
|
| 1538 | + esc_html__( |
|
| 1539 | + 'A valid grand total for line item %1$d was not found.', |
|
| 1540 | + 'event_espresso' |
|
| 1541 | + ), |
|
| 1542 | + $line_item->ID() |
|
| 1543 | + ) |
|
| 1544 | + ); |
|
| 1545 | + } |
|
| 1546 | + |
|
| 1547 | + |
|
| 1548 | + /** |
|
| 1549 | + * Prints out a representation of the line item tree |
|
| 1550 | + * |
|
| 1551 | + * @param EE_Line_Item $line_item |
|
| 1552 | + * @param int $indentation |
|
| 1553 | + * @return void |
|
| 1554 | + * @throws EE_Error |
|
| 1555 | + */ |
|
| 1556 | + public static function visualize(EE_Line_Item $line_item, $indentation = 0) |
|
| 1557 | + { |
|
| 1558 | + echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1559 | + if (! $indentation) { |
|
| 1560 | + echo defined('EE_TESTS_DIR') ? "\n" : '<br />'; |
|
| 1561 | + } |
|
| 1562 | + for ($i = 0; $i < $indentation; $i++) { |
|
| 1563 | + echo '. '; |
|
| 1564 | + } |
|
| 1565 | + $breakdown = ''; |
|
| 1566 | + if ($line_item->is_line_item()) { |
|
| 1567 | + if ($line_item->is_percent()) { |
|
| 1568 | + $breakdown = "{$line_item->percent()}%"; |
|
| 1569 | + } else { |
|
| 1570 | + $breakdown = '$' . "{$line_item->unit_price()} x {$line_item->quantity()}"; |
|
| 1571 | + } |
|
| 1572 | + } |
|
| 1573 | + echo $line_item->name(); |
|
| 1574 | + echo " [ ID:{$line_item->ID()} | qty:{$line_item->quantity()} ] {$line_item->type()} : "; |
|
| 1575 | + echo '$' . (string) $line_item->total(); |
|
| 1576 | + if ($breakdown) { |
|
| 1577 | + echo " ( {$breakdown} )"; |
|
| 1578 | + } |
|
| 1579 | + if ($line_item->is_taxable()) { |
|
| 1580 | + echo ' * taxable'; |
|
| 1581 | + } |
|
| 1582 | + if ($line_item->children()) { |
|
| 1583 | + foreach ($line_item->children() as $child) { |
|
| 1584 | + self::visualize($child, $indentation + 1); |
|
| 1585 | + } |
|
| 1586 | + } |
|
| 1587 | + } |
|
| 1588 | + |
|
| 1589 | + |
|
| 1590 | + /** |
|
| 1591 | + * Calculates the registration's final price, taking into account that they |
|
| 1592 | + * need to not only help pay for their OWN ticket, but also any transaction-wide surcharges and taxes, |
|
| 1593 | + * and receive a portion of any transaction-wide discounts. |
|
| 1594 | + * eg1, if I buy a $1 ticket and brent buys a $9 ticket, and we receive a $5 discount |
|
| 1595 | + * then I'll get 1/10 of that $5 discount, which is $0.50, and brent will get |
|
| 1596 | + * 9/10ths of that $5 discount, which is $4.50. So my final price should be $0.50 |
|
| 1597 | + * and brent's final price should be $5.50. |
|
| 1598 | + * In order to do this, we basically need to traverse the line item tree calculating |
|
| 1599 | + * the running totals (just as if we were recalculating the total), but when we identify |
|
| 1600 | + * regular line items, we need to keep track of their share of the grand total. |
|
| 1601 | + * Also, we need to keep track of the TAXABLE total for each ticket purchase, so |
|
| 1602 | + * we can know how to apply taxes to it. (Note: "taxable total" does not equal the "pretax total" |
|
| 1603 | + * when there are non-taxable items; otherwise they would be the same) |
|
| 1604 | + * |
|
| 1605 | + * @param EE_Line_Item $line_item |
|
| 1606 | + * @param array $billable_ticket_quantities array of EE_Ticket IDs and their corresponding quantity that |
|
| 1607 | + * can be included in price calculations at this moment |
|
| 1608 | + * @return array keys are line items for tickets IDs and values are their share of the running total, |
|
| 1609 | + * plus the key 'total', and 'taxable' which also has keys of all |
|
| 1610 | + * the ticket IDs. |
|
| 1611 | + * Eg array( |
|
| 1612 | + * 12 => 4.3 |
|
| 1613 | + * 23 => 8.0 |
|
| 1614 | + * 'total' => 16.6, |
|
| 1615 | + * 'taxable' => array( |
|
| 1616 | + * 12 => 10, |
|
| 1617 | + * 23 => 4 |
|
| 1618 | + * ). |
|
| 1619 | + * So to find which registrations have which final price, we need |
|
| 1620 | + * to find which line item is theirs, which can be done with |
|
| 1621 | + * `EEM_Line_Item::instance()->get_line_item_for_registration( |
|
| 1622 | + * $registration );` |
|
| 1623 | + * @throws EE_Error |
|
| 1624 | + * @throws InvalidArgumentException |
|
| 1625 | + * @throws InvalidDataTypeException |
|
| 1626 | + * @throws InvalidInterfaceException |
|
| 1627 | + * @throws ReflectionException |
|
| 1628 | + */ |
|
| 1629 | + public static function calculate_reg_final_prices_per_line_item( |
|
| 1630 | + EE_Line_Item $line_item, |
|
| 1631 | + $billable_ticket_quantities = array() |
|
| 1632 | + ) { |
|
| 1633 | + $running_totals = [ |
|
| 1634 | + 'total' => 0, |
|
| 1635 | + 'taxable' => ['total' => 0] |
|
| 1636 | + ]; |
|
| 1637 | + foreach ($line_item->children() as $child_line_item) { |
|
| 1638 | + switch ($child_line_item->type()) { |
|
| 1639 | + case EEM_Line_Item::type_sub_total: |
|
| 1640 | + $running_totals_from_subtotal = EEH_Line_Item::calculate_reg_final_prices_per_line_item( |
|
| 1641 | + $child_line_item, |
|
| 1642 | + $billable_ticket_quantities |
|
| 1643 | + ); |
|
| 1644 | + // combine arrays but preserve numeric keys |
|
| 1645 | + $running_totals = array_replace_recursive($running_totals_from_subtotal, $running_totals); |
|
| 1646 | + $running_totals['total'] += $running_totals_from_subtotal['total']; |
|
| 1647 | + $running_totals['taxable']['total'] += $running_totals_from_subtotal['taxable']['total']; |
|
| 1648 | + break; |
|
| 1649 | + |
|
| 1650 | + case EEM_Line_Item::type_tax_sub_total: |
|
| 1651 | + // find how much the taxes percentage is |
|
| 1652 | + if ($child_line_item->percent() !== 0) { |
|
| 1653 | + $tax_percent_decimal = $child_line_item->percent() / 100; |
|
| 1654 | + } else { |
|
| 1655 | + $tax_percent_decimal = EE_Taxes::get_total_taxes_percentage() / 100; |
|
| 1656 | + } |
|
| 1657 | + // and apply to all the taxable totals, and add to the pretax totals |
|
| 1658 | + foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1659 | + // "total" and "taxable" array key is an exception |
|
| 1660 | + if ($line_item_id === 'taxable') { |
|
| 1661 | + continue; |
|
| 1662 | + } |
|
| 1663 | + $taxable_total = $running_totals['taxable'][ $line_item_id ]; |
|
| 1664 | + $running_totals[ $line_item_id ] += ($taxable_total * $tax_percent_decimal); |
|
| 1665 | + } |
|
| 1666 | + break; |
|
| 1667 | + |
|
| 1668 | + case EEM_Line_Item::type_line_item: |
|
| 1669 | + // ticket line items or ???? |
|
| 1670 | + if ($child_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET) { |
|
| 1671 | + // kk it's a ticket |
|
| 1672 | + if (isset($running_totals[ $child_line_item->ID() ])) { |
|
| 1673 | + // huh? that shouldn't happen. |
|
| 1674 | + $running_totals['total'] += $child_line_item->total(); |
|
| 1675 | + } else { |
|
| 1676 | + // its not in our running totals yet. great. |
|
| 1677 | + if ($child_line_item->is_taxable()) { |
|
| 1678 | + $taxable_amount = $child_line_item->unit_price(); |
|
| 1679 | + } else { |
|
| 1680 | + $taxable_amount = 0; |
|
| 1681 | + } |
|
| 1682 | + // are we only calculating totals for some tickets? |
|
| 1683 | + if (isset($billable_ticket_quantities[ $child_line_item->OBJ_ID() ])) { |
|
| 1684 | + $quantity = $billable_ticket_quantities[ $child_line_item->OBJ_ID() ]; |
|
| 1685 | + $running_totals[ $child_line_item->ID() ] = $quantity |
|
| 1686 | + ? $child_line_item->unit_price() |
|
| 1687 | + : 0; |
|
| 1688 | + $running_totals['taxable'][ $child_line_item->ID() ] = $quantity |
|
| 1689 | + ? $taxable_amount |
|
| 1690 | + : 0; |
|
| 1691 | + } else { |
|
| 1692 | + $quantity = $child_line_item->quantity(); |
|
| 1693 | + $running_totals[ $child_line_item->ID() ] = $child_line_item->unit_price(); |
|
| 1694 | + $running_totals['taxable'][ $child_line_item->ID() ] = $taxable_amount; |
|
| 1695 | + } |
|
| 1696 | + $running_totals['taxable']['total'] += $taxable_amount * $quantity; |
|
| 1697 | + $running_totals['total'] += $child_line_item->unit_price() * $quantity; |
|
| 1698 | + } |
|
| 1699 | + } else { |
|
| 1700 | + // it's some other type of item added to the cart |
|
| 1701 | + // it should affect the running totals |
|
| 1702 | + // basically we want to convert it into a PERCENT modifier. Because |
|
| 1703 | + // more clearly affect all registration's final price equally |
|
| 1704 | + $line_items_percent_of_running_total = $running_totals['total'] > 0 |
|
| 1705 | + ? ($child_line_item->total() / $running_totals['total']) + 1 |
|
| 1706 | + : 1; |
|
| 1707 | + foreach ($running_totals as $line_item_id => $this_running_total) { |
|
| 1708 | + // the "taxable" array key is an exception |
|
| 1709 | + if ($line_item_id === 'taxable') { |
|
| 1710 | + continue; |
|
| 1711 | + } |
|
| 1712 | + // update the running totals |
|
| 1713 | + // yes this actually even works for the running grand total! |
|
| 1714 | + $running_totals[ $line_item_id ] = |
|
| 1715 | + $line_items_percent_of_running_total * $this_running_total; |
|
| 1716 | + |
|
| 1717 | + if ($child_line_item->is_taxable()) { |
|
| 1718 | + $running_totals['taxable'][ $line_item_id ] = |
|
| 1719 | + $line_items_percent_of_running_total * $running_totals['taxable'][ $line_item_id ]; |
|
| 1720 | + } |
|
| 1721 | + } |
|
| 1722 | + } |
|
| 1723 | + break; |
|
| 1724 | + } |
|
| 1725 | + } |
|
| 1726 | + return $running_totals; |
|
| 1727 | + } |
|
| 1728 | + |
|
| 1729 | + |
|
| 1730 | + /** |
|
| 1731 | + * @param EE_Line_Item $total_line_item |
|
| 1732 | + * @param EE_Line_Item $ticket_line_item |
|
| 1733 | + * @return float | null |
|
| 1734 | + * @throws EE_Error |
|
| 1735 | + * @throws InvalidArgumentException |
|
| 1736 | + * @throws InvalidDataTypeException |
|
| 1737 | + * @throws InvalidInterfaceException |
|
| 1738 | + * @throws OutOfRangeException |
|
| 1739 | + * @throws ReflectionException |
|
| 1740 | + */ |
|
| 1741 | + public static function calculate_final_price_for_ticket_line_item( |
|
| 1742 | + EE_Line_Item $total_line_item, |
|
| 1743 | + EE_Line_Item $ticket_line_item |
|
| 1744 | + ) { |
|
| 1745 | + static $final_prices_per_ticket_line_item = array(); |
|
| 1746 | + if (empty($final_prices_per_ticket_line_item)) { |
|
| 1747 | + $final_prices_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item( |
|
| 1748 | + $total_line_item |
|
| 1749 | + ); |
|
| 1750 | + } |
|
| 1751 | + // ok now find this new registration's final price |
|
| 1752 | + if (isset($final_prices_per_ticket_line_item[ $ticket_line_item->ID() ])) { |
|
| 1753 | + return $final_prices_per_ticket_line_item[ $ticket_line_item->ID() ]; |
|
| 1754 | + } |
|
| 1755 | + $message = sprintf( |
|
| 1756 | + esc_html__( |
|
| 1757 | + 'The final price for the ticket line item (ID:%1$d) could not be calculated.', |
|
| 1758 | + 'event_espresso' |
|
| 1759 | + ), |
|
| 1760 | + $ticket_line_item->ID() |
|
| 1761 | + ); |
|
| 1762 | + if (WP_DEBUG) { |
|
| 1763 | + $message .= '<br>' . print_r($final_prices_per_ticket_line_item, true); |
|
| 1764 | + throw new OutOfRangeException($message); |
|
| 1765 | + } |
|
| 1766 | + EE_Log::instance()->log(__CLASS__, __FUNCTION__, $message); |
|
| 1767 | + return null; |
|
| 1768 | + } |
|
| 1769 | + |
|
| 1770 | + |
|
| 1771 | + /** |
|
| 1772 | + * Creates a duplicate of the line item tree, except only includes billable items |
|
| 1773 | + * and the portion of line items attributed to billable things |
|
| 1774 | + * |
|
| 1775 | + * @param EE_Line_Item $line_item |
|
| 1776 | + * @param EE_Registration[] $registrations |
|
| 1777 | + * @return EE_Line_Item |
|
| 1778 | + * @throws EE_Error |
|
| 1779 | + * @throws InvalidArgumentException |
|
| 1780 | + * @throws InvalidDataTypeException |
|
| 1781 | + * @throws InvalidInterfaceException |
|
| 1782 | + * @throws ReflectionException |
|
| 1783 | + */ |
|
| 1784 | + public static function billable_line_item_tree(EE_Line_Item $line_item, $registrations) |
|
| 1785 | + { |
|
| 1786 | + $copy_li = EEH_Line_Item::billable_line_item($line_item, $registrations); |
|
| 1787 | + foreach ($line_item->children() as $child_li) { |
|
| 1788 | + $copy_li->add_child_line_item( |
|
| 1789 | + EEH_Line_Item::billable_line_item_tree($child_li, $registrations) |
|
| 1790 | + ); |
|
| 1791 | + } |
|
| 1792 | + // if this is the grand total line item, make sure the totals all add up |
|
| 1793 | + // (we could have duplicated this logic AS we copied the line items, but |
|
| 1794 | + // it seems DRYer this way) |
|
| 1795 | + if ($copy_li->type() === EEM_Line_Item::type_total) { |
|
| 1796 | + $copy_li->recalculate_total_including_taxes(); |
|
| 1797 | + } |
|
| 1798 | + return $copy_li; |
|
| 1799 | + } |
|
| 1800 | + |
|
| 1801 | + |
|
| 1802 | + /** |
|
| 1803 | + * Creates a new, unsaved line item from $line_item that factors in the |
|
| 1804 | + * number of billable registrations on $registrations. |
|
| 1805 | + * |
|
| 1806 | + * @param EE_Line_Item $line_item |
|
| 1807 | + * @param EE_Registration[] $registrations |
|
| 1808 | + * @return EE_Line_Item |
|
| 1809 | + * @throws EE_Error |
|
| 1810 | + * @throws InvalidArgumentException |
|
| 1811 | + * @throws InvalidDataTypeException |
|
| 1812 | + * @throws InvalidInterfaceException |
|
| 1813 | + * @throws ReflectionException |
|
| 1814 | + */ |
|
| 1815 | + public static function billable_line_item(EE_Line_Item $line_item, $registrations) |
|
| 1816 | + { |
|
| 1817 | + $new_li_fields = $line_item->model_field_array(); |
|
| 1818 | + if ($line_item->type() === EEM_Line_Item::type_line_item && |
|
| 1819 | + $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1820 | + ) { |
|
| 1821 | + $count = 0; |
|
| 1822 | + foreach ($registrations as $registration) { |
|
| 1823 | + if ($line_item->OBJ_ID() === $registration->ticket_ID() && |
|
| 1824 | + in_array( |
|
| 1825 | + $registration->status_ID(), |
|
| 1826 | + EEM_Registration::reg_statuses_that_allow_payment(), |
|
| 1827 | + true |
|
| 1828 | + ) |
|
| 1829 | + ) { |
|
| 1830 | + $count++; |
|
| 1831 | + } |
|
| 1832 | + } |
|
| 1833 | + $new_li_fields['LIN_quantity'] = $count; |
|
| 1834 | + } |
|
| 1835 | + // don't set the total. We'll leave that up to the code that calculates it |
|
| 1836 | + unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent'], $new_li_fields['LIN_total']); |
|
| 1837 | + return EE_Line_Item::new_instance($new_li_fields); |
|
| 1838 | + } |
|
| 1839 | + |
|
| 1840 | + |
|
| 1841 | + /** |
|
| 1842 | + * Returns a modified line item tree where all the subtotals which have a total of 0 |
|
| 1843 | + * are removed, and line items with a quantity of 0 |
|
| 1844 | + * |
|
| 1845 | + * @param EE_Line_Item $line_item |null |
|
| 1846 | + * @return EE_Line_Item|null |
|
| 1847 | + * @throws EE_Error |
|
| 1848 | + * @throws InvalidArgumentException |
|
| 1849 | + * @throws InvalidDataTypeException |
|
| 1850 | + * @throws InvalidInterfaceException |
|
| 1851 | + * @throws ReflectionException |
|
| 1852 | + */ |
|
| 1853 | + public static function non_empty_line_items(EE_Line_Item $line_item) |
|
| 1854 | + { |
|
| 1855 | + $copied_li = EEH_Line_Item::non_empty_line_item($line_item); |
|
| 1856 | + if ($copied_li === null) { |
|
| 1857 | + return null; |
|
| 1858 | + } |
|
| 1859 | + // if this is an event subtotal, we want to only include it if it |
|
| 1860 | + // has a non-zero total and at least one ticket line item child |
|
| 1861 | + $ticket_children = 0; |
|
| 1862 | + foreach ($line_item->children() as $child_li) { |
|
| 1863 | + $child_li_copy = EEH_Line_Item::non_empty_line_items($child_li); |
|
| 1864 | + if ($child_li_copy !== null) { |
|
| 1865 | + $copied_li->add_child_line_item($child_li_copy); |
|
| 1866 | + if ($child_li_copy->type() === EEM_Line_Item::type_line_item && |
|
| 1867 | + $child_li_copy->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1868 | + ) { |
|
| 1869 | + $ticket_children++; |
|
| 1870 | + } |
|
| 1871 | + } |
|
| 1872 | + } |
|
| 1873 | + // if this is an event subtotal with NO ticket children |
|
| 1874 | + // we basically want to ignore it |
|
| 1875 | + if ($ticket_children === 0 |
|
| 1876 | + && $line_item->type() === EEM_Line_Item::type_sub_total |
|
| 1877 | + && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_EVENT |
|
| 1878 | + && $line_item->total() === 0 |
|
| 1879 | + ) { |
|
| 1880 | + return null; |
|
| 1881 | + } |
|
| 1882 | + return $copied_li; |
|
| 1883 | + } |
|
| 1884 | + |
|
| 1885 | + |
|
| 1886 | + /** |
|
| 1887 | + * Creates a new, unsaved line item, but if it's a ticket line item |
|
| 1888 | + * with a total of 0, or a subtotal of 0, returns null instead |
|
| 1889 | + * |
|
| 1890 | + * @param EE_Line_Item $line_item |
|
| 1891 | + * @return EE_Line_Item |
|
| 1892 | + * @throws EE_Error |
|
| 1893 | + * @throws InvalidArgumentException |
|
| 1894 | + * @throws InvalidDataTypeException |
|
| 1895 | + * @throws InvalidInterfaceException |
|
| 1896 | + * @throws ReflectionException |
|
| 1897 | + */ |
|
| 1898 | + public static function non_empty_line_item(EE_Line_Item $line_item) |
|
| 1899 | + { |
|
| 1900 | + if ($line_item->type() === EEM_Line_Item::type_line_item |
|
| 1901 | + && $line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1902 | + && $line_item->quantity() === 0 |
|
| 1903 | + ) { |
|
| 1904 | + return null; |
|
| 1905 | + } |
|
| 1906 | + $new_li_fields = $line_item->model_field_array(); |
|
| 1907 | + // don't set the total. We'll leave that up to the code that calculates it |
|
| 1908 | + unset($new_li_fields['LIN_ID'], $new_li_fields['LIN_parent']); |
|
| 1909 | + return EE_Line_Item::new_instance($new_li_fields); |
|
| 1910 | + } |
|
| 1911 | + |
|
| 1912 | + |
|
| 1913 | + /** |
|
| 1914 | + * Cycles through all of the ticket line items for the supplied total line item |
|
| 1915 | + * and ensures that the line item's "is_taxable" field matches that of its corresponding ticket |
|
| 1916 | + * |
|
| 1917 | + * @param EE_Line_Item $total_line_item |
|
| 1918 | + * @since 4.9.79.p |
|
| 1919 | + * @throws EE_Error |
|
| 1920 | + * @throws InvalidArgumentException |
|
| 1921 | + * @throws InvalidDataTypeException |
|
| 1922 | + * @throws InvalidInterfaceException |
|
| 1923 | + * @throws ReflectionException |
|
| 1924 | + */ |
|
| 1925 | + public static function resetIsTaxableForTickets(EE_Line_Item $total_line_item) |
|
| 1926 | + { |
|
| 1927 | + $ticket_line_items = self::get_ticket_line_items($total_line_item); |
|
| 1928 | + foreach ($ticket_line_items as $ticket_line_item) { |
|
| 1929 | + if ($ticket_line_item instanceof EE_Line_Item |
|
| 1930 | + && $ticket_line_item->OBJ_type() === EEM_Line_Item::OBJ_TYPE_TICKET |
|
| 1931 | + ) { |
|
| 1932 | + $ticket = $ticket_line_item->ticket(); |
|
| 1933 | + if ($ticket instanceof EE_Ticket && $ticket->taxable() !== $ticket_line_item->is_taxable()) { |
|
| 1934 | + $ticket_line_item->set_is_taxable($ticket->taxable()); |
|
| 1935 | + $ticket_line_item->save(); |
|
| 1936 | + } |
|
| 1937 | + } |
|
| 1938 | + } |
|
| 1939 | + } |
|
| 1940 | + |
|
| 1941 | + |
|
| 1942 | + |
|
| 1943 | + /**************************************** @DEPRECATED METHODS *************************************** */ |
|
| 1944 | + /** |
|
| 1945 | + * @deprecated |
|
| 1946 | + * @param EE_Line_Item $total_line_item |
|
| 1947 | + * @return EE_Line_Item |
|
| 1948 | + * @throws EE_Error |
|
| 1949 | + * @throws InvalidArgumentException |
|
| 1950 | + * @throws InvalidDataTypeException |
|
| 1951 | + * @throws InvalidInterfaceException |
|
| 1952 | + * @throws ReflectionException |
|
| 1953 | + */ |
|
| 1954 | + public static function get_items_subtotal(EE_Line_Item $total_line_item) |
|
| 1955 | + { |
|
| 1956 | + EE_Error::doing_it_wrong( |
|
| 1957 | + 'EEH_Line_Item::get_items_subtotal()', |
|
| 1958 | + sprintf( |
|
| 1959 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1960 | + 'EEH_Line_Item::get_pre_tax_subtotal()' |
|
| 1961 | + ), |
|
| 1962 | + '4.6.0' |
|
| 1963 | + ); |
|
| 1964 | + return self::get_pre_tax_subtotal($total_line_item); |
|
| 1965 | + } |
|
| 1966 | + |
|
| 1967 | + |
|
| 1968 | + /** |
|
| 1969 | + * @deprecated |
|
| 1970 | + * @param EE_Transaction $transaction |
|
| 1971 | + * @return EE_Line_Item |
|
| 1972 | + * @throws EE_Error |
|
| 1973 | + * @throws InvalidArgumentException |
|
| 1974 | + * @throws InvalidDataTypeException |
|
| 1975 | + * @throws InvalidInterfaceException |
|
| 1976 | + * @throws ReflectionException |
|
| 1977 | + */ |
|
| 1978 | + public static function create_default_total_line_item($transaction = null) |
|
| 1979 | + { |
|
| 1980 | + EE_Error::doing_it_wrong( |
|
| 1981 | + 'EEH_Line_Item::create_default_total_line_item()', |
|
| 1982 | + sprintf( |
|
| 1983 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 1984 | + 'EEH_Line_Item::create_total_line_item()' |
|
| 1985 | + ), |
|
| 1986 | + '4.6.0' |
|
| 1987 | + ); |
|
| 1988 | + return self::create_total_line_item($transaction); |
|
| 1989 | + } |
|
| 1990 | + |
|
| 1991 | + |
|
| 1992 | + /** |
|
| 1993 | + * @deprecated |
|
| 1994 | + * @param EE_Line_Item $total_line_item |
|
| 1995 | + * @param EE_Transaction $transaction |
|
| 1996 | + * @return EE_Line_Item |
|
| 1997 | + * @throws EE_Error |
|
| 1998 | + * @throws InvalidArgumentException |
|
| 1999 | + * @throws InvalidDataTypeException |
|
| 2000 | + * @throws InvalidInterfaceException |
|
| 2001 | + * @throws ReflectionException |
|
| 2002 | + */ |
|
| 2003 | + public static function create_default_tickets_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 2004 | + { |
|
| 2005 | + EE_Error::doing_it_wrong( |
|
| 2006 | + 'EEH_Line_Item::create_default_tickets_subtotal()', |
|
| 2007 | + sprintf( |
|
| 2008 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 2009 | + 'EEH_Line_Item::create_pre_tax_subtotal()' |
|
| 2010 | + ), |
|
| 2011 | + '4.6.0' |
|
| 2012 | + ); |
|
| 2013 | + return self::create_pre_tax_subtotal($total_line_item, $transaction); |
|
| 2014 | + } |
|
| 2015 | + |
|
| 2016 | + |
|
| 2017 | + /** |
|
| 2018 | + * @deprecated |
|
| 2019 | + * @param EE_Line_Item $total_line_item |
|
| 2020 | + * @param EE_Transaction $transaction |
|
| 2021 | + * @return EE_Line_Item |
|
| 2022 | + * @throws EE_Error |
|
| 2023 | + * @throws InvalidArgumentException |
|
| 2024 | + * @throws InvalidDataTypeException |
|
| 2025 | + * @throws InvalidInterfaceException |
|
| 2026 | + * @throws ReflectionException |
|
| 2027 | + */ |
|
| 2028 | + public static function create_default_taxes_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 2029 | + { |
|
| 2030 | + EE_Error::doing_it_wrong( |
|
| 2031 | + 'EEH_Line_Item::create_default_taxes_subtotal()', |
|
| 2032 | + sprintf( |
|
| 2033 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 2034 | + 'EEH_Line_Item::create_taxes_subtotal()' |
|
| 2035 | + ), |
|
| 2036 | + '4.6.0' |
|
| 2037 | + ); |
|
| 2038 | + return self::create_taxes_subtotal($total_line_item, $transaction); |
|
| 2039 | + } |
|
| 2040 | + |
|
| 2041 | + |
|
| 2042 | + /** |
|
| 2043 | + * @deprecated |
|
| 2044 | + * @param EE_Line_Item $total_line_item |
|
| 2045 | + * @param EE_Transaction $transaction |
|
| 2046 | + * @return EE_Line_Item |
|
| 2047 | + * @throws EE_Error |
|
| 2048 | + * @throws InvalidArgumentException |
|
| 2049 | + * @throws InvalidDataTypeException |
|
| 2050 | + * @throws InvalidInterfaceException |
|
| 2051 | + * @throws ReflectionException |
|
| 2052 | + */ |
|
| 2053 | + public static function create_default_event_subtotal(EE_Line_Item $total_line_item, $transaction = null) |
|
| 2054 | + { |
|
| 2055 | + EE_Error::doing_it_wrong( |
|
| 2056 | + 'EEH_Line_Item::create_default_event_subtotal()', |
|
| 2057 | + sprintf( |
|
| 2058 | + esc_html__('Method replaced with %1$s', 'event_espresso'), |
|
| 2059 | + 'EEH_Line_Item::create_event_subtotal()' |
|
| 2060 | + ), |
|
| 2061 | + '4.6.0' |
|
| 2062 | + ); |
|
| 2063 | + return self::create_event_subtotal($total_line_item, $transaction); |
|
| 2064 | + } |
|
| 2065 | 2065 | } |
@@ -324,8 +324,8 @@ discard block |
||
| 324 | 324 | ); |
| 325 | 325 | $query = $wpdb->prepare( |
| 326 | 326 | 'DELETE li |
| 327 | - FROM ' . $this->table() . ' li |
|
| 328 | - LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID |
|
| 327 | + FROM ' . $this->table().' li |
|
| 328 | + LEFT JOIN ' . EEM_Transaction::instance()->table().' t ON li.TXN_ID = t.TXN_ID |
|
| 329 | 329 | WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s', |
| 330 | 330 | // use GMT time because that's what TXN_timestamps are in |
| 331 | 331 | date('Y-m-d H:i:s', time() - $time_to_leave_alone) |
@@ -598,7 +598,7 @@ discard block |
||
| 598 | 598 | */ |
| 599 | 599 | public function getTicketLineItemsForExpiredCarts($timestamp = 0) |
| 600 | 600 | { |
| 601 | - if (! absint($timestamp)) { |
|
| 601 | + if ( ! absint($timestamp)) { |
|
| 602 | 602 | /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */ |
| 603 | 603 | $session_lifespan = LoaderFactory::getLoader()->getShared( |
| 604 | 604 | 'EventEspresso\core\domain\values\session\SessionLifespan' |
@@ -28,601 +28,601 @@ |
||
| 28 | 28 | class EEM_Line_Item extends EEM_Base |
| 29 | 29 | { |
| 30 | 30 | |
| 31 | - /** |
|
| 32 | - * Tax sub-total is just the total of all the taxes, which should be children |
|
| 33 | - * of this line item. There should only ever be one tax sub-total, and it should |
|
| 34 | - * be a direct child of. Its quantity and LIN_unit_price = 1. |
|
| 35 | - */ |
|
| 36 | - const type_tax_sub_total = 'tax-sub-total'; |
|
| 37 | - |
|
| 38 | - /** |
|
| 39 | - * Tax line items indicate a tax applied to all the taxable line items. |
|
| 40 | - * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal |
|
| 41 | - * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1. |
|
| 42 | - */ |
|
| 43 | - const type_tax = 'tax'; |
|
| 44 | - |
|
| 45 | - /** |
|
| 46 | - * Indicating individual items purchased, or discounts or surcharges. |
|
| 47 | - * The sum of all the regular line items plus the tax items should equal the grand total. |
|
| 48 | - * Possible children are sub-line-items and cancellations. |
|
| 49 | - * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children |
|
| 50 | - * LIN_totals. Its LIN_percent = 0. |
|
| 51 | - * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1). |
|
| 52 | - * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1. |
|
| 53 | - */ |
|
| 54 | - const type_line_item = 'line-item'; |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * Line item indicating all the factors that make a single line item. |
|
| 58 | - * Sub-line items should have NO children line items. |
|
| 59 | - * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's |
|
| 60 | - * contribution towards the price of ONE of their parent items, and its LIN_total should be |
|
| 61 | - * = LIN_quantity * LIN_unit_price. Its LIN_percent = 0. |
|
| 62 | - * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should |
|
| 63 | - * = LIN_percent / 100 * sum of lower-priority sibling line items.. |
|
| 64 | - */ |
|
| 65 | - const type_sub_line_item = 'sub-item'; |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal). |
|
| 69 | - * Direct children should be event subtotals. |
|
| 70 | - * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals. |
|
| 71 | - */ |
|
| 72 | - const type_sub_total = 'sub-total'; |
|
| 73 | - |
|
| 74 | - /** |
|
| 75 | - * Line item for the grand total of an order. |
|
| 76 | - * Its direct children should be tax subtotals and (pre-tax) subtotals, |
|
| 77 | - * and possibly a regular line item indicating a transaction-wide discount/surcharge. |
|
| 78 | - * Should have a quantity of 1, a LIN_total and LIN_unit_price of the entire order's amount. |
|
| 79 | - */ |
|
| 80 | - const type_total = 'total'; |
|
| 81 | - |
|
| 82 | - /** |
|
| 83 | - * When a line item is cancelled, a sub-line-item of type 'cancellation' |
|
| 84 | - * should be created, indicating the quantity that were cancelled |
|
| 85 | - * (because a line item could have a quantity of 1, and its cancellation item |
|
| 86 | - * could be for 3, indicating that originally 4 were purchased, but 3 have been |
|
| 87 | - * cancelled, and only one remains). |
|
| 88 | - * When items are refunded, a cancellation line item should be made, which points |
|
| 89 | - * to teh payment model object which actually refunded the payment. |
|
| 90 | - * Cancellations should NOT have any children line items; the should NOT affect |
|
| 91 | - * any calculations, and are only meant as a record that cancellations have occurred. |
|
| 92 | - * Their LIN_percent should be 0. |
|
| 93 | - */ |
|
| 94 | - const type_cancellation = 'cancellation'; |
|
| 95 | - |
|
| 96 | - // various line item object types |
|
| 97 | - const OBJ_TYPE_EVENT = 'Event'; |
|
| 98 | - |
|
| 99 | - const OBJ_TYPE_PRICE = 'Price'; |
|
| 100 | - |
|
| 101 | - const OBJ_TYPE_PROMOTION = 'Promotion'; |
|
| 102 | - |
|
| 103 | - const OBJ_TYPE_TICKET = 'Ticket'; |
|
| 104 | - |
|
| 105 | - const OBJ_TYPE_TRANSACTION = 'Transaction'; |
|
| 106 | - |
|
| 107 | - /** |
|
| 108 | - * @var EEM_Line_Item $_instance |
|
| 109 | - */ |
|
| 110 | - protected static $_instance; |
|
| 111 | - |
|
| 112 | - |
|
| 113 | - /** |
|
| 114 | - * private constructor to prevent direct creation |
|
| 115 | - * |
|
| 116 | - * @Constructor |
|
| 117 | - * @param string $timezone string representing the timezone we want to set for returned Date Time Strings |
|
| 118 | - * (and any incoming timezone data that gets saved). |
|
| 119 | - * Note this just sends the timezone info to the date time model field objects. |
|
| 120 | - * Default is NULL |
|
| 121 | - * (and will be assumed using the set timezone in the 'timezone_string' wp option) |
|
| 122 | - * @throws EE_Error |
|
| 123 | - * @throws InvalidArgumentException |
|
| 124 | - */ |
|
| 125 | - protected function __construct($timezone) |
|
| 126 | - { |
|
| 127 | - $this->singular_item = esc_html__('Line Item', 'event_espresso'); |
|
| 128 | - $this->plural_item = esc_html__('Line Items', 'event_espresso'); |
|
| 129 | - |
|
| 130 | - $this->_tables = array( |
|
| 131 | - 'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID'), |
|
| 132 | - ); |
|
| 133 | - $line_items_can_be_for = apply_filters( |
|
| 134 | - 'FHEE__EEM_Line_Item__line_items_can_be_for', |
|
| 135 | - array('Ticket', 'Price', 'Event') |
|
| 136 | - ); |
|
| 137 | - $this->_fields = array( |
|
| 138 | - 'Line_Item' => array( |
|
| 139 | - 'LIN_ID' => new EE_Primary_Key_Int_Field( |
|
| 140 | - 'LIN_ID', |
|
| 141 | - esc_html__('ID', 'event_espresso') |
|
| 142 | - ), |
|
| 143 | - 'LIN_code' => new EE_Slug_Field( |
|
| 144 | - 'LIN_code', |
|
| 145 | - esc_html__('Code for index into Cart', 'event_espresso'), |
|
| 146 | - true |
|
| 147 | - ), |
|
| 148 | - 'TXN_ID' => new EE_Foreign_Key_Int_Field( |
|
| 149 | - 'TXN_ID', |
|
| 150 | - esc_html__('Transaction ID', 'event_espresso'), |
|
| 151 | - true, |
|
| 152 | - null, |
|
| 153 | - 'Transaction' |
|
| 154 | - ), |
|
| 155 | - 'LIN_name' => new EE_Full_HTML_Field( |
|
| 156 | - 'LIN_name', |
|
| 157 | - esc_html__('Line Item Name', 'event_espresso'), |
|
| 158 | - false, |
|
| 159 | - '' |
|
| 160 | - ), |
|
| 161 | - 'LIN_desc' => new EE_Full_HTML_Field( |
|
| 162 | - 'LIN_desc', |
|
| 163 | - esc_html__('Line Item Description', 'event_espresso'), |
|
| 164 | - true |
|
| 165 | - ), |
|
| 166 | - 'LIN_unit_price' => new EE_Money_Field( |
|
| 167 | - 'LIN_unit_price', |
|
| 168 | - esc_html__('Unit Price', 'event_espresso'), |
|
| 169 | - false, |
|
| 170 | - 0 |
|
| 171 | - ), |
|
| 172 | - 'LIN_percent' => new EE_Float_Field( |
|
| 173 | - 'LIN_percent', |
|
| 174 | - esc_html__('Percent', 'event_espresso'), |
|
| 175 | - false, |
|
| 176 | - 0 |
|
| 177 | - ), |
|
| 178 | - 'LIN_is_taxable' => new EE_Boolean_Field( |
|
| 179 | - 'LIN_is_taxable', |
|
| 180 | - esc_html__('Taxable', 'event_espresso'), |
|
| 181 | - false, |
|
| 182 | - false |
|
| 183 | - ), |
|
| 184 | - 'LIN_order' => new EE_Integer_Field( |
|
| 185 | - 'LIN_order', |
|
| 186 | - esc_html__('Order of Application towards total of parent', 'event_espresso'), |
|
| 187 | - false, |
|
| 188 | - 1 |
|
| 189 | - ), |
|
| 190 | - 'LIN_total' => new EE_Money_Field( |
|
| 191 | - 'LIN_total', |
|
| 192 | - esc_html__('Total (unit price x quantity)', 'event_espresso'), |
|
| 193 | - false, |
|
| 194 | - 0 |
|
| 195 | - ), |
|
| 196 | - 'LIN_quantity' => new EE_Integer_Field( |
|
| 197 | - 'LIN_quantity', |
|
| 198 | - esc_html__('Quantity', 'event_espresso'), |
|
| 199 | - true, |
|
| 200 | - 1 |
|
| 201 | - ), |
|
| 202 | - 'LIN_parent' => new EE_Integer_Field( |
|
| 203 | - 'LIN_parent', |
|
| 204 | - esc_html__("Parent ID (this item goes towards that Line Item's total)", 'event_espresso'), |
|
| 205 | - true, |
|
| 206 | - null |
|
| 207 | - ), |
|
| 208 | - 'LIN_type' => new EE_Enum_Text_Field( |
|
| 209 | - 'LIN_type', |
|
| 210 | - esc_html__('Type', 'event_espresso'), |
|
| 211 | - false, |
|
| 212 | - 'line-item', |
|
| 213 | - array( |
|
| 214 | - self::type_line_item => esc_html__('Line Item', 'event_espresso'), |
|
| 215 | - self::type_sub_line_item => esc_html__('Sub-Item', 'event_espresso'), |
|
| 216 | - self::type_sub_total => esc_html__('Subtotal', 'event_espresso'), |
|
| 217 | - self::type_tax_sub_total => esc_html__('Tax Subtotal', 'event_espresso'), |
|
| 218 | - self::type_tax => esc_html__('Tax', 'event_espresso'), |
|
| 219 | - self::type_total => esc_html__('Total', 'event_espresso'), |
|
| 220 | - self::type_cancellation => esc_html__('Cancellation', 'event_espresso'), |
|
| 221 | - ) |
|
| 222 | - ), |
|
| 223 | - 'OBJ_ID' => new EE_Foreign_Key_Int_Field( |
|
| 224 | - 'OBJ_ID', |
|
| 225 | - esc_html__('ID of Item purchased.', 'event_espresso'), |
|
| 226 | - true, |
|
| 227 | - null, |
|
| 228 | - $line_items_can_be_for |
|
| 229 | - ), |
|
| 230 | - 'OBJ_type' => new EE_Any_Foreign_Model_Name_Field( |
|
| 231 | - 'OBJ_type', |
|
| 232 | - esc_html__('Model Name this Line Item is for', 'event_espresso'), |
|
| 233 | - true, |
|
| 234 | - null, |
|
| 235 | - $line_items_can_be_for |
|
| 236 | - ), |
|
| 237 | - 'LIN_timestamp' => new EE_Datetime_Field( |
|
| 238 | - 'LIN_timestamp', |
|
| 239 | - esc_html__('When the line item was created', 'event_espresso'), |
|
| 240 | - false, |
|
| 241 | - EE_Datetime_Field::now, |
|
| 242 | - $timezone |
|
| 243 | - ), |
|
| 244 | - ), |
|
| 245 | - ); |
|
| 246 | - $this->_model_relations = array( |
|
| 247 | - 'Transaction' => new EE_Belongs_To_Relation(), |
|
| 248 | - 'Ticket' => new EE_Belongs_To_Any_Relation(), |
|
| 249 | - 'Price' => new EE_Belongs_To_Any_Relation(), |
|
| 250 | - 'Event' => new EE_Belongs_To_Any_Relation(), |
|
| 251 | - ); |
|
| 252 | - $this->_model_chain_to_wp_user = 'Transaction.Registration.Event'; |
|
| 253 | - $this->_caps_slug = 'transactions'; |
|
| 254 | - parent::__construct($timezone); |
|
| 255 | - } |
|
| 256 | - |
|
| 257 | - |
|
| 258 | - /** |
|
| 259 | - * Gets all the line items for this transaction of the given type |
|
| 260 | - * |
|
| 261 | - * @param string $line_item_type like one of EEM_Line_Item::type_* |
|
| 262 | - * @param EE_Transaction|int $transaction |
|
| 263 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 264 | - * @throws EE_Error |
|
| 265 | - * @throws InvalidArgumentException |
|
| 266 | - * @throws InvalidDataTypeException |
|
| 267 | - * @throws InvalidInterfaceException |
|
| 268 | - */ |
|
| 269 | - public function get_all_of_type_for_transaction($line_item_type, $transaction) |
|
| 270 | - { |
|
| 271 | - $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction); |
|
| 272 | - return $this->get_all(array( |
|
| 273 | - array( |
|
| 274 | - 'LIN_type' => $line_item_type, |
|
| 275 | - 'TXN_ID' => $transaction, |
|
| 276 | - ), |
|
| 277 | - )); |
|
| 278 | - } |
|
| 279 | - |
|
| 280 | - |
|
| 281 | - /** |
|
| 282 | - * Gets all line items unrelated to tickets that are normal line items |
|
| 283 | - * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category) |
|
| 284 | - * |
|
| 285 | - * @param EE_Transaction|int $transaction |
|
| 286 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 287 | - * @throws EE_Error |
|
| 288 | - * @throws InvalidArgumentException |
|
| 289 | - * @throws InvalidDataTypeException |
|
| 290 | - * @throws InvalidInterfaceException |
|
| 291 | - */ |
|
| 292 | - public function get_all_non_ticket_line_items_for_transaction($transaction) |
|
| 293 | - { |
|
| 294 | - $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction); |
|
| 295 | - return $this->get_all(array( |
|
| 296 | - array( |
|
| 297 | - 'LIN_type' => self::type_line_item, |
|
| 298 | - 'TXN_ID' => $transaction, |
|
| 299 | - 'OR' => array( |
|
| 300 | - 'OBJ_type*notticket' => array('!=', EEM_Line_Item::OBJ_TYPE_TICKET), |
|
| 301 | - 'OBJ_type*null' => array('IS_NULL'), |
|
| 302 | - ), |
|
| 303 | - ), |
|
| 304 | - )); |
|
| 305 | - } |
|
| 306 | - |
|
| 307 | - |
|
| 308 | - /** |
|
| 309 | - * Deletes line items with no transaction who have passed the transaction cutoff time. |
|
| 310 | - * This needs to be very efficient |
|
| 311 | - * because if there are spam bots afoot there will be LOTS of line items |
|
| 312 | - * |
|
| 313 | - * @return int count of how many deleted |
|
| 314 | - * @throws EE_Error |
|
| 315 | - * @throws InvalidArgumentException |
|
| 316 | - * @throws InvalidDataTypeException |
|
| 317 | - * @throws InvalidInterfaceException |
|
| 318 | - */ |
|
| 319 | - public function delete_line_items_with_no_transaction() |
|
| 320 | - { |
|
| 321 | - /** @type WPDB $wpdb */ |
|
| 322 | - global $wpdb; |
|
| 323 | - $time_to_leave_alone = apply_filters( |
|
| 324 | - 'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', |
|
| 325 | - WEEK_IN_SECONDS |
|
| 326 | - ); |
|
| 327 | - $query = $wpdb->prepare( |
|
| 328 | - 'DELETE li |
|
| 31 | + /** |
|
| 32 | + * Tax sub-total is just the total of all the taxes, which should be children |
|
| 33 | + * of this line item. There should only ever be one tax sub-total, and it should |
|
| 34 | + * be a direct child of. Its quantity and LIN_unit_price = 1. |
|
| 35 | + */ |
|
| 36 | + const type_tax_sub_total = 'tax-sub-total'; |
|
| 37 | + |
|
| 38 | + /** |
|
| 39 | + * Tax line items indicate a tax applied to all the taxable line items. |
|
| 40 | + * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal |
|
| 41 | + * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1. |
|
| 42 | + */ |
|
| 43 | + const type_tax = 'tax'; |
|
| 44 | + |
|
| 45 | + /** |
|
| 46 | + * Indicating individual items purchased, or discounts or surcharges. |
|
| 47 | + * The sum of all the regular line items plus the tax items should equal the grand total. |
|
| 48 | + * Possible children are sub-line-items and cancellations. |
|
| 49 | + * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children |
|
| 50 | + * LIN_totals. Its LIN_percent = 0. |
|
| 51 | + * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1). |
|
| 52 | + * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1. |
|
| 53 | + */ |
|
| 54 | + const type_line_item = 'line-item'; |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * Line item indicating all the factors that make a single line item. |
|
| 58 | + * Sub-line items should have NO children line items. |
|
| 59 | + * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's |
|
| 60 | + * contribution towards the price of ONE of their parent items, and its LIN_total should be |
|
| 61 | + * = LIN_quantity * LIN_unit_price. Its LIN_percent = 0. |
|
| 62 | + * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should |
|
| 63 | + * = LIN_percent / 100 * sum of lower-priority sibling line items.. |
|
| 64 | + */ |
|
| 65 | + const type_sub_line_item = 'sub-item'; |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal). |
|
| 69 | + * Direct children should be event subtotals. |
|
| 70 | + * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals. |
|
| 71 | + */ |
|
| 72 | + const type_sub_total = 'sub-total'; |
|
| 73 | + |
|
| 74 | + /** |
|
| 75 | + * Line item for the grand total of an order. |
|
| 76 | + * Its direct children should be tax subtotals and (pre-tax) subtotals, |
|
| 77 | + * and possibly a regular line item indicating a transaction-wide discount/surcharge. |
|
| 78 | + * Should have a quantity of 1, a LIN_total and LIN_unit_price of the entire order's amount. |
|
| 79 | + */ |
|
| 80 | + const type_total = 'total'; |
|
| 81 | + |
|
| 82 | + /** |
|
| 83 | + * When a line item is cancelled, a sub-line-item of type 'cancellation' |
|
| 84 | + * should be created, indicating the quantity that were cancelled |
|
| 85 | + * (because a line item could have a quantity of 1, and its cancellation item |
|
| 86 | + * could be for 3, indicating that originally 4 were purchased, but 3 have been |
|
| 87 | + * cancelled, and only one remains). |
|
| 88 | + * When items are refunded, a cancellation line item should be made, which points |
|
| 89 | + * to teh payment model object which actually refunded the payment. |
|
| 90 | + * Cancellations should NOT have any children line items; the should NOT affect |
|
| 91 | + * any calculations, and are only meant as a record that cancellations have occurred. |
|
| 92 | + * Their LIN_percent should be 0. |
|
| 93 | + */ |
|
| 94 | + const type_cancellation = 'cancellation'; |
|
| 95 | + |
|
| 96 | + // various line item object types |
|
| 97 | + const OBJ_TYPE_EVENT = 'Event'; |
|
| 98 | + |
|
| 99 | + const OBJ_TYPE_PRICE = 'Price'; |
|
| 100 | + |
|
| 101 | + const OBJ_TYPE_PROMOTION = 'Promotion'; |
|
| 102 | + |
|
| 103 | + const OBJ_TYPE_TICKET = 'Ticket'; |
|
| 104 | + |
|
| 105 | + const OBJ_TYPE_TRANSACTION = 'Transaction'; |
|
| 106 | + |
|
| 107 | + /** |
|
| 108 | + * @var EEM_Line_Item $_instance |
|
| 109 | + */ |
|
| 110 | + protected static $_instance; |
|
| 111 | + |
|
| 112 | + |
|
| 113 | + /** |
|
| 114 | + * private constructor to prevent direct creation |
|
| 115 | + * |
|
| 116 | + * @Constructor |
|
| 117 | + * @param string $timezone string representing the timezone we want to set for returned Date Time Strings |
|
| 118 | + * (and any incoming timezone data that gets saved). |
|
| 119 | + * Note this just sends the timezone info to the date time model field objects. |
|
| 120 | + * Default is NULL |
|
| 121 | + * (and will be assumed using the set timezone in the 'timezone_string' wp option) |
|
| 122 | + * @throws EE_Error |
|
| 123 | + * @throws InvalidArgumentException |
|
| 124 | + */ |
|
| 125 | + protected function __construct($timezone) |
|
| 126 | + { |
|
| 127 | + $this->singular_item = esc_html__('Line Item', 'event_espresso'); |
|
| 128 | + $this->plural_item = esc_html__('Line Items', 'event_espresso'); |
|
| 129 | + |
|
| 130 | + $this->_tables = array( |
|
| 131 | + 'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID'), |
|
| 132 | + ); |
|
| 133 | + $line_items_can_be_for = apply_filters( |
|
| 134 | + 'FHEE__EEM_Line_Item__line_items_can_be_for', |
|
| 135 | + array('Ticket', 'Price', 'Event') |
|
| 136 | + ); |
|
| 137 | + $this->_fields = array( |
|
| 138 | + 'Line_Item' => array( |
|
| 139 | + 'LIN_ID' => new EE_Primary_Key_Int_Field( |
|
| 140 | + 'LIN_ID', |
|
| 141 | + esc_html__('ID', 'event_espresso') |
|
| 142 | + ), |
|
| 143 | + 'LIN_code' => new EE_Slug_Field( |
|
| 144 | + 'LIN_code', |
|
| 145 | + esc_html__('Code for index into Cart', 'event_espresso'), |
|
| 146 | + true |
|
| 147 | + ), |
|
| 148 | + 'TXN_ID' => new EE_Foreign_Key_Int_Field( |
|
| 149 | + 'TXN_ID', |
|
| 150 | + esc_html__('Transaction ID', 'event_espresso'), |
|
| 151 | + true, |
|
| 152 | + null, |
|
| 153 | + 'Transaction' |
|
| 154 | + ), |
|
| 155 | + 'LIN_name' => new EE_Full_HTML_Field( |
|
| 156 | + 'LIN_name', |
|
| 157 | + esc_html__('Line Item Name', 'event_espresso'), |
|
| 158 | + false, |
|
| 159 | + '' |
|
| 160 | + ), |
|
| 161 | + 'LIN_desc' => new EE_Full_HTML_Field( |
|
| 162 | + 'LIN_desc', |
|
| 163 | + esc_html__('Line Item Description', 'event_espresso'), |
|
| 164 | + true |
|
| 165 | + ), |
|
| 166 | + 'LIN_unit_price' => new EE_Money_Field( |
|
| 167 | + 'LIN_unit_price', |
|
| 168 | + esc_html__('Unit Price', 'event_espresso'), |
|
| 169 | + false, |
|
| 170 | + 0 |
|
| 171 | + ), |
|
| 172 | + 'LIN_percent' => new EE_Float_Field( |
|
| 173 | + 'LIN_percent', |
|
| 174 | + esc_html__('Percent', 'event_espresso'), |
|
| 175 | + false, |
|
| 176 | + 0 |
|
| 177 | + ), |
|
| 178 | + 'LIN_is_taxable' => new EE_Boolean_Field( |
|
| 179 | + 'LIN_is_taxable', |
|
| 180 | + esc_html__('Taxable', 'event_espresso'), |
|
| 181 | + false, |
|
| 182 | + false |
|
| 183 | + ), |
|
| 184 | + 'LIN_order' => new EE_Integer_Field( |
|
| 185 | + 'LIN_order', |
|
| 186 | + esc_html__('Order of Application towards total of parent', 'event_espresso'), |
|
| 187 | + false, |
|
| 188 | + 1 |
|
| 189 | + ), |
|
| 190 | + 'LIN_total' => new EE_Money_Field( |
|
| 191 | + 'LIN_total', |
|
| 192 | + esc_html__('Total (unit price x quantity)', 'event_espresso'), |
|
| 193 | + false, |
|
| 194 | + 0 |
|
| 195 | + ), |
|
| 196 | + 'LIN_quantity' => new EE_Integer_Field( |
|
| 197 | + 'LIN_quantity', |
|
| 198 | + esc_html__('Quantity', 'event_espresso'), |
|
| 199 | + true, |
|
| 200 | + 1 |
|
| 201 | + ), |
|
| 202 | + 'LIN_parent' => new EE_Integer_Field( |
|
| 203 | + 'LIN_parent', |
|
| 204 | + esc_html__("Parent ID (this item goes towards that Line Item's total)", 'event_espresso'), |
|
| 205 | + true, |
|
| 206 | + null |
|
| 207 | + ), |
|
| 208 | + 'LIN_type' => new EE_Enum_Text_Field( |
|
| 209 | + 'LIN_type', |
|
| 210 | + esc_html__('Type', 'event_espresso'), |
|
| 211 | + false, |
|
| 212 | + 'line-item', |
|
| 213 | + array( |
|
| 214 | + self::type_line_item => esc_html__('Line Item', 'event_espresso'), |
|
| 215 | + self::type_sub_line_item => esc_html__('Sub-Item', 'event_espresso'), |
|
| 216 | + self::type_sub_total => esc_html__('Subtotal', 'event_espresso'), |
|
| 217 | + self::type_tax_sub_total => esc_html__('Tax Subtotal', 'event_espresso'), |
|
| 218 | + self::type_tax => esc_html__('Tax', 'event_espresso'), |
|
| 219 | + self::type_total => esc_html__('Total', 'event_espresso'), |
|
| 220 | + self::type_cancellation => esc_html__('Cancellation', 'event_espresso'), |
|
| 221 | + ) |
|
| 222 | + ), |
|
| 223 | + 'OBJ_ID' => new EE_Foreign_Key_Int_Field( |
|
| 224 | + 'OBJ_ID', |
|
| 225 | + esc_html__('ID of Item purchased.', 'event_espresso'), |
|
| 226 | + true, |
|
| 227 | + null, |
|
| 228 | + $line_items_can_be_for |
|
| 229 | + ), |
|
| 230 | + 'OBJ_type' => new EE_Any_Foreign_Model_Name_Field( |
|
| 231 | + 'OBJ_type', |
|
| 232 | + esc_html__('Model Name this Line Item is for', 'event_espresso'), |
|
| 233 | + true, |
|
| 234 | + null, |
|
| 235 | + $line_items_can_be_for |
|
| 236 | + ), |
|
| 237 | + 'LIN_timestamp' => new EE_Datetime_Field( |
|
| 238 | + 'LIN_timestamp', |
|
| 239 | + esc_html__('When the line item was created', 'event_espresso'), |
|
| 240 | + false, |
|
| 241 | + EE_Datetime_Field::now, |
|
| 242 | + $timezone |
|
| 243 | + ), |
|
| 244 | + ), |
|
| 245 | + ); |
|
| 246 | + $this->_model_relations = array( |
|
| 247 | + 'Transaction' => new EE_Belongs_To_Relation(), |
|
| 248 | + 'Ticket' => new EE_Belongs_To_Any_Relation(), |
|
| 249 | + 'Price' => new EE_Belongs_To_Any_Relation(), |
|
| 250 | + 'Event' => new EE_Belongs_To_Any_Relation(), |
|
| 251 | + ); |
|
| 252 | + $this->_model_chain_to_wp_user = 'Transaction.Registration.Event'; |
|
| 253 | + $this->_caps_slug = 'transactions'; |
|
| 254 | + parent::__construct($timezone); |
|
| 255 | + } |
|
| 256 | + |
|
| 257 | + |
|
| 258 | + /** |
|
| 259 | + * Gets all the line items for this transaction of the given type |
|
| 260 | + * |
|
| 261 | + * @param string $line_item_type like one of EEM_Line_Item::type_* |
|
| 262 | + * @param EE_Transaction|int $transaction |
|
| 263 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 264 | + * @throws EE_Error |
|
| 265 | + * @throws InvalidArgumentException |
|
| 266 | + * @throws InvalidDataTypeException |
|
| 267 | + * @throws InvalidInterfaceException |
|
| 268 | + */ |
|
| 269 | + public function get_all_of_type_for_transaction($line_item_type, $transaction) |
|
| 270 | + { |
|
| 271 | + $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction); |
|
| 272 | + return $this->get_all(array( |
|
| 273 | + array( |
|
| 274 | + 'LIN_type' => $line_item_type, |
|
| 275 | + 'TXN_ID' => $transaction, |
|
| 276 | + ), |
|
| 277 | + )); |
|
| 278 | + } |
|
| 279 | + |
|
| 280 | + |
|
| 281 | + /** |
|
| 282 | + * Gets all line items unrelated to tickets that are normal line items |
|
| 283 | + * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category) |
|
| 284 | + * |
|
| 285 | + * @param EE_Transaction|int $transaction |
|
| 286 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 287 | + * @throws EE_Error |
|
| 288 | + * @throws InvalidArgumentException |
|
| 289 | + * @throws InvalidDataTypeException |
|
| 290 | + * @throws InvalidInterfaceException |
|
| 291 | + */ |
|
| 292 | + public function get_all_non_ticket_line_items_for_transaction($transaction) |
|
| 293 | + { |
|
| 294 | + $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction); |
|
| 295 | + return $this->get_all(array( |
|
| 296 | + array( |
|
| 297 | + 'LIN_type' => self::type_line_item, |
|
| 298 | + 'TXN_ID' => $transaction, |
|
| 299 | + 'OR' => array( |
|
| 300 | + 'OBJ_type*notticket' => array('!=', EEM_Line_Item::OBJ_TYPE_TICKET), |
|
| 301 | + 'OBJ_type*null' => array('IS_NULL'), |
|
| 302 | + ), |
|
| 303 | + ), |
|
| 304 | + )); |
|
| 305 | + } |
|
| 306 | + |
|
| 307 | + |
|
| 308 | + /** |
|
| 309 | + * Deletes line items with no transaction who have passed the transaction cutoff time. |
|
| 310 | + * This needs to be very efficient |
|
| 311 | + * because if there are spam bots afoot there will be LOTS of line items |
|
| 312 | + * |
|
| 313 | + * @return int count of how many deleted |
|
| 314 | + * @throws EE_Error |
|
| 315 | + * @throws InvalidArgumentException |
|
| 316 | + * @throws InvalidDataTypeException |
|
| 317 | + * @throws InvalidInterfaceException |
|
| 318 | + */ |
|
| 319 | + public function delete_line_items_with_no_transaction() |
|
| 320 | + { |
|
| 321 | + /** @type WPDB $wpdb */ |
|
| 322 | + global $wpdb; |
|
| 323 | + $time_to_leave_alone = apply_filters( |
|
| 324 | + 'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', |
|
| 325 | + WEEK_IN_SECONDS |
|
| 326 | + ); |
|
| 327 | + $query = $wpdb->prepare( |
|
| 328 | + 'DELETE li |
|
| 329 | 329 | FROM ' . $this->table() . ' li |
| 330 | 330 | LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID |
| 331 | 331 | WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s', |
| 332 | - // use GMT time because that's what TXN_timestamps are in |
|
| 333 | - date('Y-m-d H:i:s', time() - $time_to_leave_alone) |
|
| 334 | - ); |
|
| 335 | - return $wpdb->query($query); |
|
| 336 | - } |
|
| 337 | - |
|
| 338 | - |
|
| 339 | - /** |
|
| 340 | - * get_line_item_for_transaction_object |
|
| 341 | - * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket |
|
| 342 | - * |
|
| 343 | - * @param int $TXN_ID |
|
| 344 | - * @param EE_Base_Class $object |
|
| 345 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 346 | - * @throws EE_Error |
|
| 347 | - * @throws InvalidArgumentException |
|
| 348 | - * @throws InvalidDataTypeException |
|
| 349 | - * @throws InvalidInterfaceException |
|
| 350 | - * @throws ReflectionException |
|
| 351 | - */ |
|
| 352 | - public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object) |
|
| 353 | - { |
|
| 354 | - return $this->get_all(array( |
|
| 355 | - array( |
|
| 356 | - 'TXN_ID' => $TXN_ID, |
|
| 357 | - 'OBJ_type' => str_replace('EE_', '', get_class($object)), |
|
| 358 | - 'OBJ_ID' => $object->ID(), |
|
| 359 | - ), |
|
| 360 | - )); |
|
| 361 | - } |
|
| 362 | - |
|
| 363 | - |
|
| 364 | - /** |
|
| 365 | - * get_object_line_items_for_transaction |
|
| 366 | - * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs |
|
| 367 | - * |
|
| 368 | - * @param int $TXN_ID |
|
| 369 | - * @param string $OBJ_type |
|
| 370 | - * @param array $OBJ_IDs |
|
| 371 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 372 | - * @throws EE_Error |
|
| 373 | - */ |
|
| 374 | - public function get_object_line_items_for_transaction( |
|
| 375 | - $TXN_ID, |
|
| 376 | - $OBJ_type = EEM_Line_Item::OBJ_TYPE_EVENT, |
|
| 377 | - $OBJ_IDs = array() |
|
| 378 | - ) { |
|
| 379 | - $query_params = array( |
|
| 380 | - 'OBJ_type' => $OBJ_type, |
|
| 381 | - // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query |
|
| 382 | - 'OBJ_ID' => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs, |
|
| 383 | - ); |
|
| 384 | - if ($TXN_ID) { |
|
| 385 | - $query_params['TXN_ID'] = $TXN_ID; |
|
| 386 | - } |
|
| 387 | - return $this->get_all(array($query_params)); |
|
| 388 | - } |
|
| 389 | - |
|
| 390 | - |
|
| 391 | - /** |
|
| 392 | - * get_all_ticket_line_items_for_transaction |
|
| 393 | - * |
|
| 394 | - * @param EE_Transaction $transaction |
|
| 395 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 396 | - * @throws EE_Error |
|
| 397 | - * @throws InvalidArgumentException |
|
| 398 | - * @throws InvalidDataTypeException |
|
| 399 | - * @throws InvalidInterfaceException |
|
| 400 | - * @throws ReflectionException |
|
| 401 | - */ |
|
| 402 | - public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction) |
|
| 403 | - { |
|
| 404 | - return $this->get_all(array( |
|
| 405 | - array( |
|
| 406 | - 'TXN_ID' => $transaction->ID(), |
|
| 407 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 408 | - ), |
|
| 409 | - )); |
|
| 410 | - } |
|
| 411 | - |
|
| 412 | - |
|
| 413 | - /** |
|
| 414 | - * get_ticket_line_item_for_transaction |
|
| 415 | - * |
|
| 416 | - * @param int $TXN_ID |
|
| 417 | - * @param int $TKT_ID |
|
| 418 | - * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 419 | - * @throws EE_Error |
|
| 420 | - * @throws InvalidArgumentException |
|
| 421 | - * @throws InvalidDataTypeException |
|
| 422 | - * @throws InvalidInterfaceException |
|
| 423 | - */ |
|
| 424 | - public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID) |
|
| 425 | - { |
|
| 426 | - return $this->get_one(array( |
|
| 427 | - array( |
|
| 428 | - 'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID), |
|
| 429 | - 'OBJ_ID' => $TKT_ID, |
|
| 430 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 431 | - ), |
|
| 432 | - )); |
|
| 433 | - } |
|
| 434 | - |
|
| 435 | - |
|
| 436 | - /** |
|
| 437 | - * get_existing_promotion_line_item |
|
| 438 | - * searches the cart for existing line items for the specified promotion |
|
| 439 | - * |
|
| 440 | - * @since 1.0.0 |
|
| 441 | - * @param EE_Line_Item $parent_line_item |
|
| 442 | - * @param EE_Promotion $promotion |
|
| 443 | - * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 444 | - * @throws EE_Error |
|
| 445 | - * @throws InvalidArgumentException |
|
| 446 | - * @throws InvalidDataTypeException |
|
| 447 | - * @throws InvalidInterfaceException |
|
| 448 | - * @throws ReflectionException |
|
| 449 | - */ |
|
| 450 | - public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion) |
|
| 451 | - { |
|
| 452 | - return $this->get_one(array( |
|
| 453 | - array( |
|
| 454 | - 'TXN_ID' => $parent_line_item->TXN_ID(), |
|
| 455 | - 'LIN_parent' => $parent_line_item->ID(), |
|
| 456 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PROMOTION, |
|
| 457 | - 'OBJ_ID' => $promotion->ID(), |
|
| 458 | - ), |
|
| 459 | - )); |
|
| 460 | - } |
|
| 461 | - |
|
| 462 | - |
|
| 463 | - /** |
|
| 464 | - * get_all_promotion_line_items |
|
| 465 | - * searches the cart for any and all existing promotion line items |
|
| 466 | - * |
|
| 467 | - * @since 1.0.0 |
|
| 468 | - * @param EE_Line_Item $parent_line_item |
|
| 469 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 470 | - * @throws EE_Error |
|
| 471 | - * @throws InvalidArgumentException |
|
| 472 | - * @throws InvalidDataTypeException |
|
| 473 | - * @throws InvalidInterfaceException |
|
| 474 | - * @throws ReflectionException |
|
| 475 | - */ |
|
| 476 | - public function get_all_promotion_line_items(EE_Line_Item $parent_line_item) |
|
| 477 | - { |
|
| 478 | - return $this->get_all(array( |
|
| 479 | - array( |
|
| 480 | - 'TXN_ID' => $parent_line_item->TXN_ID(), |
|
| 481 | - 'LIN_parent' => $parent_line_item->ID(), |
|
| 482 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PROMOTION, |
|
| 483 | - ), |
|
| 484 | - )); |
|
| 485 | - } |
|
| 486 | - |
|
| 487 | - |
|
| 488 | - /** |
|
| 489 | - * Gets the registration's corresponding line item. |
|
| 490 | - * Note: basically does NOT support having multiple line items for a single ticket, |
|
| 491 | - * which would happen if some of the registrations had a price modifier while others didn't. |
|
| 492 | - * In order to support that, we'd probably need a LIN_ID on registrations or something. |
|
| 493 | - * |
|
| 494 | - * @param EE_Registration $registration |
|
| 495 | - * @return EE_Base_Class|EE_Line_ITem|EE_Soft_Delete_Base_Class|NULL |
|
| 496 | - * @throws EE_Error |
|
| 497 | - */ |
|
| 498 | - public function get_line_item_for_registration(EE_Registration $registration) |
|
| 499 | - { |
|
| 500 | - return $this->get_one($this->line_item_for_registration_query_params($registration)); |
|
| 501 | - } |
|
| 502 | - |
|
| 503 | - |
|
| 504 | - /** |
|
| 505 | - * Gets the query params used to retrieve a specific line item for the given registration |
|
| 506 | - * |
|
| 507 | - * @param EE_Registration $registration |
|
| 508 | - * @param array $original_query_params any extra query params you'd like to be merged with |
|
| 509 | - * @return array @see |
|
| 510 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 511 | - * @throws EE_Error |
|
| 512 | - */ |
|
| 513 | - public function line_item_for_registration_query_params( |
|
| 514 | - EE_Registration $registration, |
|
| 515 | - $original_query_params = array() |
|
| 516 | - ) { |
|
| 517 | - return array_replace_recursive($original_query_params, array( |
|
| 518 | - array( |
|
| 519 | - 'OBJ_ID' => $registration->ticket_ID(), |
|
| 520 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 521 | - 'TXN_ID' => $registration->transaction_ID(), |
|
| 522 | - ), |
|
| 523 | - )); |
|
| 524 | - } |
|
| 525 | - |
|
| 526 | - |
|
| 527 | - /** |
|
| 528 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 529 | - * @throws InvalidInterfaceException |
|
| 530 | - * @throws InvalidDataTypeException |
|
| 531 | - * @throws EE_Error |
|
| 532 | - * @throws InvalidArgumentException |
|
| 533 | - */ |
|
| 534 | - public function get_total_line_items_with_no_transaction() |
|
| 535 | - { |
|
| 536 | - return $this->get_total_line_items_for_carts(); |
|
| 537 | - } |
|
| 538 | - |
|
| 539 | - |
|
| 540 | - /** |
|
| 541 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 542 | - * @throws InvalidInterfaceException |
|
| 543 | - * @throws InvalidDataTypeException |
|
| 544 | - * @throws EE_Error |
|
| 545 | - * @throws InvalidArgumentException |
|
| 546 | - */ |
|
| 547 | - public function get_total_line_items_for_active_carts() |
|
| 548 | - { |
|
| 549 | - return $this->get_total_line_items_for_carts(false); |
|
| 550 | - } |
|
| 551 | - |
|
| 552 | - |
|
| 553 | - /** |
|
| 554 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 555 | - * @throws InvalidInterfaceException |
|
| 556 | - * @throws InvalidDataTypeException |
|
| 557 | - * @throws EE_Error |
|
| 558 | - * @throws InvalidArgumentException |
|
| 559 | - */ |
|
| 560 | - public function get_total_line_items_for_expired_carts() |
|
| 561 | - { |
|
| 562 | - return $this->get_total_line_items_for_carts(true); |
|
| 563 | - } |
|
| 564 | - |
|
| 565 | - |
|
| 566 | - /** |
|
| 567 | - * Returns an array of grand total line items where the TXN_ID is 0. |
|
| 568 | - * If $expired is set to true, then only line items for expired sessions will be returned. |
|
| 569 | - * If $expired is set to false, then only line items for active sessions will be returned. |
|
| 570 | - * |
|
| 571 | - * @param null $expired |
|
| 572 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 573 | - * @throws EE_Error |
|
| 574 | - * @throws InvalidArgumentException |
|
| 575 | - * @throws InvalidDataTypeException |
|
| 576 | - * @throws InvalidInterfaceException |
|
| 577 | - */ |
|
| 578 | - private function get_total_line_items_for_carts($expired = null) |
|
| 579 | - { |
|
| 580 | - $where_params = array( |
|
| 581 | - 'TXN_ID' => 0, |
|
| 582 | - 'LIN_type' => 'total', |
|
| 583 | - ); |
|
| 584 | - if ($expired !== null) { |
|
| 585 | - /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */ |
|
| 586 | - $session_lifespan = LoaderFactory::getLoader()->getShared( |
|
| 587 | - 'EventEspresso\core\domain\values\session\SessionLifespan' |
|
| 588 | - ); |
|
| 589 | - $where_params['LIN_timestamp'] = array( |
|
| 590 | - $expired ? '<=' : '>', |
|
| 591 | - $session_lifespan->expiration(), |
|
| 592 | - ); |
|
| 593 | - } |
|
| 594 | - return $this->get_all(array($where_params)); |
|
| 595 | - } |
|
| 596 | - |
|
| 597 | - |
|
| 598 | - /** |
|
| 599 | - * Returns an array of ticket total line items where the TXN_ID is 0 |
|
| 600 | - * AND the timestamp is older than the session lifespan. |
|
| 601 | - * |
|
| 602 | - * @param int $timestamp |
|
| 603 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 604 | - * @throws EE_Error |
|
| 605 | - * @throws InvalidArgumentException |
|
| 606 | - * @throws InvalidDataTypeException |
|
| 607 | - * @throws InvalidInterfaceException |
|
| 608 | - */ |
|
| 609 | - public function getTicketLineItemsForExpiredCarts($timestamp = 0) |
|
| 610 | - { |
|
| 611 | - if (! absint($timestamp)) { |
|
| 612 | - /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */ |
|
| 613 | - $session_lifespan = LoaderFactory::getLoader()->getShared( |
|
| 614 | - 'EventEspresso\core\domain\values\session\SessionLifespan' |
|
| 615 | - ); |
|
| 616 | - $timestamp = $session_lifespan->expiration(); |
|
| 617 | - } |
|
| 618 | - return $this->get_all( |
|
| 619 | - array( |
|
| 620 | - array( |
|
| 621 | - 'TXN_ID' => 0, |
|
| 622 | - 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 623 | - 'LIN_timestamp' => array('<=', $timestamp), |
|
| 624 | - ), |
|
| 625 | - ) |
|
| 626 | - ); |
|
| 627 | - } |
|
| 332 | + // use GMT time because that's what TXN_timestamps are in |
|
| 333 | + date('Y-m-d H:i:s', time() - $time_to_leave_alone) |
|
| 334 | + ); |
|
| 335 | + return $wpdb->query($query); |
|
| 336 | + } |
|
| 337 | + |
|
| 338 | + |
|
| 339 | + /** |
|
| 340 | + * get_line_item_for_transaction_object |
|
| 341 | + * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket |
|
| 342 | + * |
|
| 343 | + * @param int $TXN_ID |
|
| 344 | + * @param EE_Base_Class $object |
|
| 345 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 346 | + * @throws EE_Error |
|
| 347 | + * @throws InvalidArgumentException |
|
| 348 | + * @throws InvalidDataTypeException |
|
| 349 | + * @throws InvalidInterfaceException |
|
| 350 | + * @throws ReflectionException |
|
| 351 | + */ |
|
| 352 | + public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object) |
|
| 353 | + { |
|
| 354 | + return $this->get_all(array( |
|
| 355 | + array( |
|
| 356 | + 'TXN_ID' => $TXN_ID, |
|
| 357 | + 'OBJ_type' => str_replace('EE_', '', get_class($object)), |
|
| 358 | + 'OBJ_ID' => $object->ID(), |
|
| 359 | + ), |
|
| 360 | + )); |
|
| 361 | + } |
|
| 362 | + |
|
| 363 | + |
|
| 364 | + /** |
|
| 365 | + * get_object_line_items_for_transaction |
|
| 366 | + * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs |
|
| 367 | + * |
|
| 368 | + * @param int $TXN_ID |
|
| 369 | + * @param string $OBJ_type |
|
| 370 | + * @param array $OBJ_IDs |
|
| 371 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 372 | + * @throws EE_Error |
|
| 373 | + */ |
|
| 374 | + public function get_object_line_items_for_transaction( |
|
| 375 | + $TXN_ID, |
|
| 376 | + $OBJ_type = EEM_Line_Item::OBJ_TYPE_EVENT, |
|
| 377 | + $OBJ_IDs = array() |
|
| 378 | + ) { |
|
| 379 | + $query_params = array( |
|
| 380 | + 'OBJ_type' => $OBJ_type, |
|
| 381 | + // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query |
|
| 382 | + 'OBJ_ID' => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs, |
|
| 383 | + ); |
|
| 384 | + if ($TXN_ID) { |
|
| 385 | + $query_params['TXN_ID'] = $TXN_ID; |
|
| 386 | + } |
|
| 387 | + return $this->get_all(array($query_params)); |
|
| 388 | + } |
|
| 389 | + |
|
| 390 | + |
|
| 391 | + /** |
|
| 392 | + * get_all_ticket_line_items_for_transaction |
|
| 393 | + * |
|
| 394 | + * @param EE_Transaction $transaction |
|
| 395 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 396 | + * @throws EE_Error |
|
| 397 | + * @throws InvalidArgumentException |
|
| 398 | + * @throws InvalidDataTypeException |
|
| 399 | + * @throws InvalidInterfaceException |
|
| 400 | + * @throws ReflectionException |
|
| 401 | + */ |
|
| 402 | + public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction) |
|
| 403 | + { |
|
| 404 | + return $this->get_all(array( |
|
| 405 | + array( |
|
| 406 | + 'TXN_ID' => $transaction->ID(), |
|
| 407 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 408 | + ), |
|
| 409 | + )); |
|
| 410 | + } |
|
| 411 | + |
|
| 412 | + |
|
| 413 | + /** |
|
| 414 | + * get_ticket_line_item_for_transaction |
|
| 415 | + * |
|
| 416 | + * @param int $TXN_ID |
|
| 417 | + * @param int $TKT_ID |
|
| 418 | + * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 419 | + * @throws EE_Error |
|
| 420 | + * @throws InvalidArgumentException |
|
| 421 | + * @throws InvalidDataTypeException |
|
| 422 | + * @throws InvalidInterfaceException |
|
| 423 | + */ |
|
| 424 | + public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID) |
|
| 425 | + { |
|
| 426 | + return $this->get_one(array( |
|
| 427 | + array( |
|
| 428 | + 'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID), |
|
| 429 | + 'OBJ_ID' => $TKT_ID, |
|
| 430 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 431 | + ), |
|
| 432 | + )); |
|
| 433 | + } |
|
| 434 | + |
|
| 435 | + |
|
| 436 | + /** |
|
| 437 | + * get_existing_promotion_line_item |
|
| 438 | + * searches the cart for existing line items for the specified promotion |
|
| 439 | + * |
|
| 440 | + * @since 1.0.0 |
|
| 441 | + * @param EE_Line_Item $parent_line_item |
|
| 442 | + * @param EE_Promotion $promotion |
|
| 443 | + * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL |
|
| 444 | + * @throws EE_Error |
|
| 445 | + * @throws InvalidArgumentException |
|
| 446 | + * @throws InvalidDataTypeException |
|
| 447 | + * @throws InvalidInterfaceException |
|
| 448 | + * @throws ReflectionException |
|
| 449 | + */ |
|
| 450 | + public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion) |
|
| 451 | + { |
|
| 452 | + return $this->get_one(array( |
|
| 453 | + array( |
|
| 454 | + 'TXN_ID' => $parent_line_item->TXN_ID(), |
|
| 455 | + 'LIN_parent' => $parent_line_item->ID(), |
|
| 456 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PROMOTION, |
|
| 457 | + 'OBJ_ID' => $promotion->ID(), |
|
| 458 | + ), |
|
| 459 | + )); |
|
| 460 | + } |
|
| 461 | + |
|
| 462 | + |
|
| 463 | + /** |
|
| 464 | + * get_all_promotion_line_items |
|
| 465 | + * searches the cart for any and all existing promotion line items |
|
| 466 | + * |
|
| 467 | + * @since 1.0.0 |
|
| 468 | + * @param EE_Line_Item $parent_line_item |
|
| 469 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 470 | + * @throws EE_Error |
|
| 471 | + * @throws InvalidArgumentException |
|
| 472 | + * @throws InvalidDataTypeException |
|
| 473 | + * @throws InvalidInterfaceException |
|
| 474 | + * @throws ReflectionException |
|
| 475 | + */ |
|
| 476 | + public function get_all_promotion_line_items(EE_Line_Item $parent_line_item) |
|
| 477 | + { |
|
| 478 | + return $this->get_all(array( |
|
| 479 | + array( |
|
| 480 | + 'TXN_ID' => $parent_line_item->TXN_ID(), |
|
| 481 | + 'LIN_parent' => $parent_line_item->ID(), |
|
| 482 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_PROMOTION, |
|
| 483 | + ), |
|
| 484 | + )); |
|
| 485 | + } |
|
| 486 | + |
|
| 487 | + |
|
| 488 | + /** |
|
| 489 | + * Gets the registration's corresponding line item. |
|
| 490 | + * Note: basically does NOT support having multiple line items for a single ticket, |
|
| 491 | + * which would happen if some of the registrations had a price modifier while others didn't. |
|
| 492 | + * In order to support that, we'd probably need a LIN_ID on registrations or something. |
|
| 493 | + * |
|
| 494 | + * @param EE_Registration $registration |
|
| 495 | + * @return EE_Base_Class|EE_Line_ITem|EE_Soft_Delete_Base_Class|NULL |
|
| 496 | + * @throws EE_Error |
|
| 497 | + */ |
|
| 498 | + public function get_line_item_for_registration(EE_Registration $registration) |
|
| 499 | + { |
|
| 500 | + return $this->get_one($this->line_item_for_registration_query_params($registration)); |
|
| 501 | + } |
|
| 502 | + |
|
| 503 | + |
|
| 504 | + /** |
|
| 505 | + * Gets the query params used to retrieve a specific line item for the given registration |
|
| 506 | + * |
|
| 507 | + * @param EE_Registration $registration |
|
| 508 | + * @param array $original_query_params any extra query params you'd like to be merged with |
|
| 509 | + * @return array @see |
|
| 510 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 511 | + * @throws EE_Error |
|
| 512 | + */ |
|
| 513 | + public function line_item_for_registration_query_params( |
|
| 514 | + EE_Registration $registration, |
|
| 515 | + $original_query_params = array() |
|
| 516 | + ) { |
|
| 517 | + return array_replace_recursive($original_query_params, array( |
|
| 518 | + array( |
|
| 519 | + 'OBJ_ID' => $registration->ticket_ID(), |
|
| 520 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 521 | + 'TXN_ID' => $registration->transaction_ID(), |
|
| 522 | + ), |
|
| 523 | + )); |
|
| 524 | + } |
|
| 525 | + |
|
| 526 | + |
|
| 527 | + /** |
|
| 528 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 529 | + * @throws InvalidInterfaceException |
|
| 530 | + * @throws InvalidDataTypeException |
|
| 531 | + * @throws EE_Error |
|
| 532 | + * @throws InvalidArgumentException |
|
| 533 | + */ |
|
| 534 | + public function get_total_line_items_with_no_transaction() |
|
| 535 | + { |
|
| 536 | + return $this->get_total_line_items_for_carts(); |
|
| 537 | + } |
|
| 538 | + |
|
| 539 | + |
|
| 540 | + /** |
|
| 541 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 542 | + * @throws InvalidInterfaceException |
|
| 543 | + * @throws InvalidDataTypeException |
|
| 544 | + * @throws EE_Error |
|
| 545 | + * @throws InvalidArgumentException |
|
| 546 | + */ |
|
| 547 | + public function get_total_line_items_for_active_carts() |
|
| 548 | + { |
|
| 549 | + return $this->get_total_line_items_for_carts(false); |
|
| 550 | + } |
|
| 551 | + |
|
| 552 | + |
|
| 553 | + /** |
|
| 554 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 555 | + * @throws InvalidInterfaceException |
|
| 556 | + * @throws InvalidDataTypeException |
|
| 557 | + * @throws EE_Error |
|
| 558 | + * @throws InvalidArgumentException |
|
| 559 | + */ |
|
| 560 | + public function get_total_line_items_for_expired_carts() |
|
| 561 | + { |
|
| 562 | + return $this->get_total_line_items_for_carts(true); |
|
| 563 | + } |
|
| 564 | + |
|
| 565 | + |
|
| 566 | + /** |
|
| 567 | + * Returns an array of grand total line items where the TXN_ID is 0. |
|
| 568 | + * If $expired is set to true, then only line items for expired sessions will be returned. |
|
| 569 | + * If $expired is set to false, then only line items for active sessions will be returned. |
|
| 570 | + * |
|
| 571 | + * @param null $expired |
|
| 572 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 573 | + * @throws EE_Error |
|
| 574 | + * @throws InvalidArgumentException |
|
| 575 | + * @throws InvalidDataTypeException |
|
| 576 | + * @throws InvalidInterfaceException |
|
| 577 | + */ |
|
| 578 | + private function get_total_line_items_for_carts($expired = null) |
|
| 579 | + { |
|
| 580 | + $where_params = array( |
|
| 581 | + 'TXN_ID' => 0, |
|
| 582 | + 'LIN_type' => 'total', |
|
| 583 | + ); |
|
| 584 | + if ($expired !== null) { |
|
| 585 | + /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */ |
|
| 586 | + $session_lifespan = LoaderFactory::getLoader()->getShared( |
|
| 587 | + 'EventEspresso\core\domain\values\session\SessionLifespan' |
|
| 588 | + ); |
|
| 589 | + $where_params['LIN_timestamp'] = array( |
|
| 590 | + $expired ? '<=' : '>', |
|
| 591 | + $session_lifespan->expiration(), |
|
| 592 | + ); |
|
| 593 | + } |
|
| 594 | + return $this->get_all(array($where_params)); |
|
| 595 | + } |
|
| 596 | + |
|
| 597 | + |
|
| 598 | + /** |
|
| 599 | + * Returns an array of ticket total line items where the TXN_ID is 0 |
|
| 600 | + * AND the timestamp is older than the session lifespan. |
|
| 601 | + * |
|
| 602 | + * @param int $timestamp |
|
| 603 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 604 | + * @throws EE_Error |
|
| 605 | + * @throws InvalidArgumentException |
|
| 606 | + * @throws InvalidDataTypeException |
|
| 607 | + * @throws InvalidInterfaceException |
|
| 608 | + */ |
|
| 609 | + public function getTicketLineItemsForExpiredCarts($timestamp = 0) |
|
| 610 | + { |
|
| 611 | + if (! absint($timestamp)) { |
|
| 612 | + /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */ |
|
| 613 | + $session_lifespan = LoaderFactory::getLoader()->getShared( |
|
| 614 | + 'EventEspresso\core\domain\values\session\SessionLifespan' |
|
| 615 | + ); |
|
| 616 | + $timestamp = $session_lifespan->expiration(); |
|
| 617 | + } |
|
| 618 | + return $this->get_all( |
|
| 619 | + array( |
|
| 620 | + array( |
|
| 621 | + 'TXN_ID' => 0, |
|
| 622 | + 'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET, |
|
| 623 | + 'LIN_timestamp' => array('<=', $timestamp), |
|
| 624 | + ), |
|
| 625 | + ) |
|
| 626 | + ); |
|
| 627 | + } |
|
| 628 | 628 | } |
@@ -356,7 +356,7 @@ discard block |
||
| 356 | 356 | // enqueue style |
| 357 | 357 | wp_register_style( |
| 358 | 358 | 'espresso_txn', |
| 359 | - TXN_ASSETS_URL . 'espresso_transactions_admin.css', |
|
| 359 | + TXN_ASSETS_URL.'espresso_transactions_admin.css', |
|
| 360 | 360 | array(), |
| 361 | 361 | EVENT_ESPRESSO_VERSION |
| 362 | 362 | ); |
@@ -364,7 +364,7 @@ discard block |
||
| 364 | 364 | // scripts |
| 365 | 365 | wp_register_script( |
| 366 | 366 | 'espresso_txn', |
| 367 | - TXN_ASSETS_URL . 'espresso_transactions_admin.js', |
|
| 367 | + TXN_ASSETS_URL.'espresso_transactions_admin.js', |
|
| 368 | 368 | array( |
| 369 | 369 | 'ee_admin_js', |
| 370 | 370 | 'ee-datepicker', |
@@ -492,7 +492,7 @@ discard block |
||
| 492 | 492 | $this->_transaction->verify_abandoned_transaction_status(); |
| 493 | 493 | } |
| 494 | 494 | |
| 495 | - if (! $this->_transaction instanceof EE_Transaction) { |
|
| 495 | + if ( ! $this->_transaction instanceof EE_Transaction) { |
|
| 496 | 496 | $error_msg = sprintf( |
| 497 | 497 | esc_html__( |
| 498 | 498 | 'An error occurred and the details for the transaction with the ID # %d could not be retrieved.', |
@@ -585,7 +585,7 @@ discard block |
||
| 585 | 585 | 'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items', |
| 586 | 586 | array( |
| 587 | 587 | 'overpaid' => array( |
| 588 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code, |
|
| 588 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::overpaid_status_code, |
|
| 589 | 589 | 'desc' => EEH_Template::pretty_status( |
| 590 | 590 | EEM_Transaction::overpaid_status_code, |
| 591 | 591 | false, |
@@ -593,7 +593,7 @@ discard block |
||
| 593 | 593 | ), |
| 594 | 594 | ), |
| 595 | 595 | 'complete' => array( |
| 596 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code, |
|
| 596 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::complete_status_code, |
|
| 597 | 597 | 'desc' => EEH_Template::pretty_status( |
| 598 | 598 | EEM_Transaction::complete_status_code, |
| 599 | 599 | false, |
@@ -601,7 +601,7 @@ discard block |
||
| 601 | 601 | ), |
| 602 | 602 | ), |
| 603 | 603 | 'incomplete' => array( |
| 604 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code, |
|
| 604 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::incomplete_status_code, |
|
| 605 | 605 | 'desc' => EEH_Template::pretty_status( |
| 606 | 606 | EEM_Transaction::incomplete_status_code, |
| 607 | 607 | false, |
@@ -609,7 +609,7 @@ discard block |
||
| 609 | 609 | ), |
| 610 | 610 | ), |
| 611 | 611 | 'abandoned' => array( |
| 612 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code, |
|
| 612 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::abandoned_status_code, |
|
| 613 | 613 | 'desc' => EEH_Template::pretty_status( |
| 614 | 614 | EEM_Transaction::abandoned_status_code, |
| 615 | 615 | false, |
@@ -617,7 +617,7 @@ discard block |
||
| 617 | 617 | ), |
| 618 | 618 | ), |
| 619 | 619 | 'failed' => array( |
| 620 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code, |
|
| 620 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Transaction::failed_status_code, |
|
| 621 | 621 | 'desc' => EEH_Template::pretty_status( |
| 622 | 622 | EEM_Transaction::failed_status_code, |
| 623 | 623 | false, |
@@ -666,7 +666,7 @@ discard block |
||
| 666 | 666 | 'Click to Edit event', |
| 667 | 667 | 'event_espresso' |
| 668 | 668 | ) |
| 669 | - . '">' . $event->name() . '</a>', |
|
| 669 | + . '">'.$event->name().'</a>', |
|
| 670 | 670 | '</h3>' |
| 671 | 671 | ) |
| 672 | 672 | : ''; |
@@ -700,7 +700,7 @@ discard block |
||
| 700 | 700 | |
| 701 | 701 | $this->_set_transaction_object(); |
| 702 | 702 | |
| 703 | - if (! $this->_transaction instanceof EE_Transaction) { |
|
| 703 | + if ( ! $this->_transaction instanceof EE_Transaction) { |
|
| 704 | 704 | return; |
| 705 | 705 | } |
| 706 | 706 | $primary_registration = $this->_transaction->primary_registration(); |
@@ -714,9 +714,9 @@ discard block |
||
| 714 | 714 | $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp'); |
| 715 | 715 | $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso'); |
| 716 | 716 | |
| 717 | - $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ]; |
|
| 717 | + $this->_template_args['txn_status']['value'] = self::$_txn_status[$this->_transaction->status_ID()]; |
|
| 718 | 718 | $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso'); |
| 719 | - $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID(); |
|
| 719 | + $this->_template_args['txn_status']['class'] = 'status-'.$this->_transaction->status_ID(); |
|
| 720 | 720 | |
| 721 | 721 | $this->_template_args['grand_total'] = $this->_transaction->total(); |
| 722 | 722 | $this->_template_args['total_paid'] = $this->_transaction->paid(); |
@@ -832,7 +832,7 @@ discard block |
||
| 832 | 832 | // grab messages at the last second |
| 833 | 833 | $this->_template_args['notices'] = EE_Error::get_notices(); |
| 834 | 834 | // path to template |
| 835 | - $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php'; |
|
| 835 | + $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_header.template.php'; |
|
| 836 | 836 | $this->_template_args['admin_page_header'] = EEH_Template::display_template( |
| 837 | 837 | $template_path, |
| 838 | 838 | $this->_template_args, |
@@ -861,7 +861,7 @@ discard block |
||
| 861 | 861 | |
| 862 | 862 | $this->_set_transaction_object(); |
| 863 | 863 | |
| 864 | - if (! $this->_transaction instanceof EE_Transaction) { |
|
| 864 | + if ( ! $this->_transaction instanceof EE_Transaction) { |
|
| 865 | 865 | return; |
| 866 | 866 | } |
| 867 | 867 | add_meta_box( |
@@ -917,7 +917,7 @@ discard block |
||
| 917 | 917 | { |
| 918 | 918 | $content = ''; |
| 919 | 919 | $actions = array(); |
| 920 | - if (! $transaction instanceof EE_Transaction) { |
|
| 920 | + if ( ! $transaction instanceof EE_Transaction) { |
|
| 921 | 921 | return $content; |
| 922 | 922 | } |
| 923 | 923 | /** @var EE_Registration $primary_registration */ |
@@ -998,7 +998,7 @@ discard block |
||
| 998 | 998 | ); |
| 999 | 999 | if ($actions) { |
| 1000 | 1000 | $content = '<ul>'; |
| 1001 | - $content .= '<li>' . implode('</li><li>', $actions) . '</li>'; |
|
| 1001 | + $content .= '<li>'.implode('</li><li>', $actions).'</li>'; |
|
| 1002 | 1002 | $content .= '</uL>'; |
| 1003 | 1003 | } |
| 1004 | 1004 | return $content; |
@@ -1059,7 +1059,7 @@ discard block |
||
| 1059 | 1059 | |
| 1060 | 1060 | // process payment details |
| 1061 | 1061 | $payments = $this->_transaction->payments(); |
| 1062 | - if (! empty($payments)) { |
|
| 1062 | + if ( ! empty($payments)) { |
|
| 1063 | 1063 | $this->_template_args['payments'] = $payments; |
| 1064 | 1064 | $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments); |
| 1065 | 1065 | } else { |
@@ -1120,7 +1120,7 @@ discard block |
||
| 1120 | 1120 | esc_html__('%1$s : Initiated %2$s', 'event_espresso'), |
| 1121 | 1121 | ucwords(str_replace('_', ' ', $reg_step)), |
| 1122 | 1122 | date( |
| 1123 | - get_option('date_format') . ' ' . get_option('time_format'), |
|
| 1123 | + get_option('date_format').' '.get_option('time_format'), |
|
| 1124 | 1124 | $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS) |
| 1125 | 1125 | ) |
| 1126 | 1126 | ) |
@@ -1173,7 +1173,7 @@ discard block |
||
| 1173 | 1173 | |
| 1174 | 1174 | // 'espresso_delete_payment_nonce' |
| 1175 | 1175 | |
| 1176 | - $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php'; |
|
| 1176 | + $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_txn_details.template.php'; |
|
| 1177 | 1177 | echo EEH_Template::display_template($template_path, $this->_template_args, true); |
| 1178 | 1178 | } |
| 1179 | 1179 | |
@@ -1205,18 +1205,18 @@ discard block |
||
| 1205 | 1205 | ), |
| 1206 | 1206 | ) |
| 1207 | 1207 | ); |
| 1208 | - if (! empty($reg_payments)) { |
|
| 1208 | + if ( ! empty($reg_payments)) { |
|
| 1209 | 1209 | foreach ($payments as $payment) { |
| 1210 | - if (! $payment instanceof EE_Payment) { |
|
| 1210 | + if ( ! $payment instanceof EE_Payment) { |
|
| 1211 | 1211 | continue; |
| 1212 | - } elseif (! isset($existing_reg_payments[ $payment->ID() ])) { |
|
| 1213 | - $existing_reg_payments[ $payment->ID() ] = array(); |
|
| 1212 | + } elseif ( ! isset($existing_reg_payments[$payment->ID()])) { |
|
| 1213 | + $existing_reg_payments[$payment->ID()] = array(); |
|
| 1214 | 1214 | } |
| 1215 | 1215 | foreach ($reg_payments as $reg_payment) { |
| 1216 | 1216 | if ($reg_payment instanceof EE_Registration_Payment |
| 1217 | 1217 | && $reg_payment->payment_ID() === $payment->ID() |
| 1218 | 1218 | ) { |
| 1219 | - $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID(); |
|
| 1219 | + $existing_reg_payments[$payment->ID()][] = $reg_payment->registration_ID(); |
|
| 1220 | 1220 | } |
| 1221 | 1221 | } |
| 1222 | 1222 | } |
@@ -1254,22 +1254,22 @@ discard block |
||
| 1254 | 1254 | ), |
| 1255 | 1255 | ), |
| 1256 | 1256 | ); |
| 1257 | - $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div( |
|
| 1257 | + $registrations_to_apply_payment_to = EEH_HTML::br().EEH_HTML::div( |
|
| 1258 | 1258 | '', |
| 1259 | 1259 | 'txn-admin-apply-payment-to-registrations-dv', |
| 1260 | 1260 | '', |
| 1261 | 1261 | 'clear: both; margin: 1.5em 0 0; display: none;' |
| 1262 | 1262 | ); |
| 1263 | - $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap'); |
|
| 1263 | + $registrations_to_apply_payment_to .= EEH_HTML::br().EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap'); |
|
| 1264 | 1264 | $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl'); |
| 1265 | 1265 | $registrations_to_apply_payment_to .= EEH_HTML::thead( |
| 1266 | 1266 | EEH_HTML::tr( |
| 1267 | - EEH_HTML::th(esc_html__('ID', 'event_espresso')) . |
|
| 1268 | - EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) . |
|
| 1269 | - EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) . |
|
| 1270 | - EEH_HTML::th(esc_html__('Event', 'event_espresso')) . |
|
| 1271 | - EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') . |
|
| 1272 | - EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') . |
|
| 1267 | + EEH_HTML::th(esc_html__('ID', 'event_espresso')). |
|
| 1268 | + EEH_HTML::th(esc_html__('Registrant', 'event_espresso')). |
|
| 1269 | + EEH_HTML::th(esc_html__('Ticket', 'event_espresso')). |
|
| 1270 | + EEH_HTML::th(esc_html__('Event', 'event_espresso')). |
|
| 1271 | + EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr'). |
|
| 1272 | + EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr'). |
|
| 1273 | 1273 | EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr') |
| 1274 | 1274 | ) |
| 1275 | 1275 | ); |
@@ -1284,7 +1284,7 @@ discard block |
||
| 1284 | 1284 | : esc_html__('Unknown Attendee', 'event_espresso'); |
| 1285 | 1285 | $owing = $registration->final_price() - $registration->paid(); |
| 1286 | 1286 | $taxable = $registration->ticket()->taxable() |
| 1287 | - ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>' |
|
| 1287 | + ? ' <span class="smaller-text lt-grey-text"> '.esc_html__('+ tax', 'event_espresso').'</span>' |
|
| 1288 | 1288 | : ''; |
| 1289 | 1289 | $checked = empty($existing_reg_payments) |
| 1290 | 1290 | || in_array($registration->ID(), $existing_reg_payments, true) |
@@ -1292,26 +1292,26 @@ discard block |
||
| 1292 | 1292 | : ''; |
| 1293 | 1293 | $disabled = $registration->final_price() > 0 ? '' : ' disabled'; |
| 1294 | 1294 | $registrations_to_apply_payment_to .= EEH_HTML::tr( |
| 1295 | - EEH_HTML::td($registration->ID()) . |
|
| 1296 | - EEH_HTML::td($attendee_name) . |
|
| 1295 | + EEH_HTML::td($registration->ID()). |
|
| 1296 | + EEH_HTML::td($attendee_name). |
|
| 1297 | 1297 | EEH_HTML::td( |
| 1298 | - $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable |
|
| 1299 | - ) . |
|
| 1300 | - EEH_HTML::td($registration->event_name()) . |
|
| 1301 | - EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') . |
|
| 1298 | + $registration->ticket()->name().' : '.$registration->ticket()->pretty_price().$taxable |
|
| 1299 | + ). |
|
| 1300 | + EEH_HTML::td($registration->event_name()). |
|
| 1301 | + EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr'). |
|
| 1302 | 1302 | EEH_HTML::td( |
| 1303 | 1303 | EEH_Template::format_currency($owing), |
| 1304 | 1304 | '', |
| 1305 | 1305 | 'txn-admin-payment-owing-td jst-cntr' |
| 1306 | - ) . |
|
| 1306 | + ). |
|
| 1307 | 1307 | EEH_HTML::td( |
| 1308 | - '<input type="checkbox" value="' . $registration->ID() |
|
| 1308 | + '<input type="checkbox" value="'.$registration->ID() |
|
| 1309 | 1309 | . '" name="txn_admin_payment[registrations]"' |
| 1310 | - . $checked . $disabled . '>', |
|
| 1310 | + . $checked.$disabled.'>', |
|
| 1311 | 1311 | '', |
| 1312 | 1312 | 'jst-cntr' |
| 1313 | 1313 | ), |
| 1314 | - 'apply-payment-registration-row-' . $registration->ID() |
|
| 1314 | + 'apply-payment-registration-row-'.$registration->ID() |
|
| 1315 | 1315 | ); |
| 1316 | 1316 | } |
| 1317 | 1317 | } |
@@ -1392,12 +1392,12 @@ discard block |
||
| 1392 | 1392 | array( |
| 1393 | 1393 | 'OR*payment_method_for_payment' => array( |
| 1394 | 1394 | 'PMD_ID' => array('IN', $payment_methods_of_payments), |
| 1395 | - 'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'), |
|
| 1395 | + 'PMD_scope' => array('LIKE', '%'.EEM_Payment_Method::scope_admin.'%'), |
|
| 1396 | 1396 | ), |
| 1397 | 1397 | ), |
| 1398 | 1398 | ); |
| 1399 | 1399 | } else { |
| 1400 | - $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'))); |
|
| 1400 | + $query_args = array(array('PMD_scope' => array('LIKE', '%'.EEM_Payment_Method::scope_admin.'%'))); |
|
| 1401 | 1401 | } |
| 1402 | 1402 | $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args); |
| 1403 | 1403 | } |
@@ -1430,7 +1430,7 @@ discard block |
||
| 1430 | 1430 | 'Line_Item', |
| 1431 | 1431 | array(array('LIN_type' => 'line-item')) |
| 1432 | 1432 | ); |
| 1433 | - if (! empty($line_items)) { |
|
| 1433 | + if ( ! empty($line_items)) { |
|
| 1434 | 1434 | foreach ($line_items as $item) { |
| 1435 | 1435 | if ($item instanceof EE_Line_Item) { |
| 1436 | 1436 | switch ($item->OBJ_type()) { |
@@ -1440,7 +1440,7 @@ discard block |
||
| 1440 | 1440 | $ticket = $item->ticket(); |
| 1441 | 1441 | // right now we're only handling tickets here. |
| 1442 | 1442 | // Cause its expected that only tickets will have attendees right? |
| 1443 | - if (! $ticket instanceof EE_Ticket) { |
|
| 1443 | + if ( ! $ticket instanceof EE_Ticket) { |
|
| 1444 | 1444 | break; |
| 1445 | 1445 | } |
| 1446 | 1446 | try { |
@@ -1449,45 +1449,45 @@ discard block |
||
| 1449 | 1449 | EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
| 1450 | 1450 | $event_name = esc_html__('Unknown Event', 'event_espresso'); |
| 1451 | 1451 | } |
| 1452 | - $event_name .= ' - ' . $item->name(); |
|
| 1452 | + $event_name .= ' - '.$item->name(); |
|
| 1453 | 1453 | $ticket_price = EEH_Template::format_currency($item->unit_price()); |
| 1454 | 1454 | // now get all of the registrations for this transaction that use this ticket |
| 1455 | 1455 | $registrations = $ticket->registrations( |
| 1456 | 1456 | array(array('TXN_ID' => $this->_transaction->ID())) |
| 1457 | 1457 | ); |
| 1458 | 1458 | foreach ($registrations as $registration) { |
| 1459 | - if (! $registration instanceof EE_Registration) { |
|
| 1459 | + if ( ! $registration instanceof EE_Registration) { |
|
| 1460 | 1460 | break; |
| 1461 | 1461 | } |
| 1462 | - $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID'] |
|
| 1462 | + $this->_template_args['event_attendees'][$registration->ID()]['STS_ID'] |
|
| 1463 | 1463 | = $registration->status_ID(); |
| 1464 | - $this->_template_args['event_attendees'][ $registration->ID() ]['att_num'] |
|
| 1464 | + $this->_template_args['event_attendees'][$registration->ID()]['att_num'] |
|
| 1465 | 1465 | = $registration->count(); |
| 1466 | - $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name'] |
|
| 1466 | + $this->_template_args['event_attendees'][$registration->ID()]['event_ticket_name'] |
|
| 1467 | 1467 | = $event_name; |
| 1468 | - $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price'] |
|
| 1468 | + $this->_template_args['event_attendees'][$registration->ID()]['ticket_price'] |
|
| 1469 | 1469 | = $ticket_price; |
| 1470 | 1470 | // attendee info |
| 1471 | 1471 | $attendee = $registration->get_first_related('Attendee'); |
| 1472 | 1472 | if ($attendee instanceof EE_Attendee) { |
| 1473 | - $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] |
|
| 1473 | + $this->_template_args['event_attendees'][$registration->ID()]['att_id'] |
|
| 1474 | 1474 | = $attendee->ID(); |
| 1475 | - $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] |
|
| 1475 | + $this->_template_args['event_attendees'][$registration->ID()]['attendee'] |
|
| 1476 | 1476 | = $attendee->full_name(); |
| 1477 | - $this->_template_args['event_attendees'][ $registration->ID() ]['email'] |
|
| 1478 | - = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name |
|
| 1477 | + $this->_template_args['event_attendees'][$registration->ID()]['email'] |
|
| 1478 | + = '<a href="mailto:'.$attendee->email().'?subject='.$event_name |
|
| 1479 | 1479 | . esc_html__( |
| 1480 | 1480 | ' Event', |
| 1481 | 1481 | 'event_espresso' |
| 1482 | 1482 | ) |
| 1483 | - . '">' . $attendee->email() . '</a>'; |
|
| 1484 | - $this->_template_args['event_attendees'][ $registration->ID() ]['address'] |
|
| 1483 | + . '">'.$attendee->email().'</a>'; |
|
| 1484 | + $this->_template_args['event_attendees'][$registration->ID()]['address'] |
|
| 1485 | 1485 | = EEH_Address::format($attendee, 'inline', false, false); |
| 1486 | 1486 | } else { |
| 1487 | - $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = ''; |
|
| 1488 | - $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = ''; |
|
| 1489 | - $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = ''; |
|
| 1490 | - $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = ''; |
|
| 1487 | + $this->_template_args['event_attendees'][$registration->ID()]['att_id'] = ''; |
|
| 1488 | + $this->_template_args['event_attendees'][$registration->ID()]['attendee'] = ''; |
|
| 1489 | + $this->_template_args['event_attendees'][$registration->ID()]['email'] = ''; |
|
| 1490 | + $this->_template_args['event_attendees'][$registration->ID()]['address'] = ''; |
|
| 1491 | 1491 | } |
| 1492 | 1492 | } |
| 1493 | 1493 | break; |
@@ -1503,7 +1503,7 @@ discard block |
||
| 1503 | 1503 | TXN_ADMIN_URL |
| 1504 | 1504 | ); |
| 1505 | 1505 | echo EEH_Template::display_template( |
| 1506 | - TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php', |
|
| 1506 | + TXN_TEMPLATE_PATH.'txn_admin_details_main_meta_box_attendees.template.php', |
|
| 1507 | 1507 | $this->_template_args, |
| 1508 | 1508 | true |
| 1509 | 1509 | ); |
@@ -1538,7 +1538,7 @@ discard block |
||
| 1538 | 1538 | $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration |
| 1539 | 1539 | ? $this->_transaction->primary_registration()->get_first_related('Attendee') |
| 1540 | 1540 | : null; |
| 1541 | - if (! $primary_att instanceof EE_Attendee) { |
|
| 1541 | + if ( ! $primary_att instanceof EE_Attendee) { |
|
| 1542 | 1542 | $this->_template_args['no_attendee_message'] = esc_html__( |
| 1543 | 1543 | 'There is no attached contact for this transaction. The transaction either failed due to an error or was abandoned.', |
| 1544 | 1544 | 'event_espresso' |
@@ -1560,7 +1560,7 @@ discard block |
||
| 1560 | 1560 | // get formatted address for registrant |
| 1561 | 1561 | $this->_template_args['formatted_address'] = EEH_Address::format($primary_att); |
| 1562 | 1562 | echo EEH_Template::display_template( |
| 1563 | - TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php', |
|
| 1563 | + TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_registrant.template.php', |
|
| 1564 | 1564 | $this->_template_args, |
| 1565 | 1565 | true |
| 1566 | 1566 | ); |
@@ -1585,7 +1585,7 @@ discard block |
||
| 1585 | 1585 | TXN_ADMIN_URL |
| 1586 | 1586 | ); |
| 1587 | 1587 | |
| 1588 | - $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php'; |
|
| 1588 | + $template_path = TXN_TEMPLATE_PATH.'txn_admin_details_side_meta_box_billing_info.template.php'; |
|
| 1589 | 1589 | echo EEH_Template::display_template($template_path, $this->_template_args, true); |
| 1590 | 1590 | } |
| 1591 | 1591 | |
@@ -1611,7 +1611,7 @@ discard block |
||
| 1611 | 1611 | 'ee_edit_payments', |
| 1612 | 1612 | 'apply_payment_or_refund_from_registration_details' |
| 1613 | 1613 | ); |
| 1614 | - if (! empty($valid_data) && $has_access) { |
|
| 1614 | + if ( ! empty($valid_data) && $has_access) { |
|
| 1615 | 1615 | $PAY_ID = $valid_data['PAY_ID']; |
| 1616 | 1616 | // save the new payment |
| 1617 | 1617 | $payment = $this->_create_payment_from_request_data($valid_data); |
@@ -1624,7 +1624,7 @@ discard block |
||
| 1624 | 1624 | $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment); |
| 1625 | 1625 | $this->_remove_existing_registration_payments($payment, $PAY_ID); |
| 1626 | 1626 | // apply payment to registrations (if applicable) |
| 1627 | - if (! empty($REG_IDs)) { |
|
| 1627 | + if ( ! empty($REG_IDs)) { |
|
| 1628 | 1628 | $this->_update_registration_payments($transaction, $payment, $REG_IDs); |
| 1629 | 1629 | $this->_maybe_send_notifications(); |
| 1630 | 1630 | // now process status changes for the same registrations |
@@ -1695,14 +1695,14 @@ discard block |
||
| 1695 | 1695 | */ |
| 1696 | 1696 | protected function _validate_payment_request_data() |
| 1697 | 1697 | { |
| 1698 | - if (! isset($this->_req_data['txn_admin_payment'])) { |
|
| 1698 | + if ( ! isset($this->_req_data['txn_admin_payment'])) { |
|
| 1699 | 1699 | return array(); |
| 1700 | 1700 | } |
| 1701 | 1701 | $payment_form = $this->_generate_payment_form_section(); |
| 1702 | 1702 | try { |
| 1703 | 1703 | if ($payment_form->was_submitted()) { |
| 1704 | 1704 | $payment_form->receive_form_submission(); |
| 1705 | - if (! $payment_form->is_valid()) { |
|
| 1705 | + if ( ! $payment_form->is_valid()) { |
|
| 1706 | 1706 | $submission_error_messages = array(); |
| 1707 | 1707 | foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) { |
| 1708 | 1708 | if ($validation_error instanceof EE_Validation_Error) { |
@@ -1883,7 +1883,7 @@ discard block |
||
| 1883 | 1883 | array('Y-m-d', 'g:i a') |
| 1884 | 1884 | ); |
| 1885 | 1885 | |
| 1886 | - if (! $payment->save()) { |
|
| 1886 | + if ( ! $payment->save()) { |
|
| 1887 | 1887 | EE_Error::add_error( |
| 1888 | 1888 | sprintf( |
| 1889 | 1889 | esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'), |
@@ -2088,12 +2088,12 @@ discard block |
||
| 2088 | 2088 | // but add in some conditions regarding payment, |
| 2089 | 2089 | // so that we don't apply payments to registrations that are free or have already been paid for |
| 2090 | 2090 | // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative ) |
| 2091 | - if (! $payment->is_a_refund()) { |
|
| 2091 | + if ( ! $payment->is_a_refund()) { |
|
| 2092 | 2092 | $registration_query_where_params['REG_final_price'] = array('!=', 0); |
| 2093 | 2093 | $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true); |
| 2094 | 2094 | } |
| 2095 | 2095 | $registrations = $transaction->registrations(array($registration_query_where_params)); |
| 2096 | - if (! empty($registrations)) { |
|
| 2096 | + if ( ! empty($registrations)) { |
|
| 2097 | 2097 | /** @type EE_Payment_Processor $payment_processor */ |
| 2098 | 2098 | $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
| 2099 | 2099 | $payment_processor->process_registration_payments($transaction, $payment, $registrations); |
@@ -2118,7 +2118,7 @@ discard block |
||
| 2118 | 2118 | protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array()) |
| 2119 | 2119 | { |
| 2120 | 2120 | // first if there is no change in status then we get out. |
| 2121 | - if (! isset($this->_req_data['txn_reg_status_change']['reg_status']) |
|
| 2121 | + if ( ! isset($this->_req_data['txn_reg_status_change']['reg_status']) |
|
| 2122 | 2122 | || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN' |
| 2123 | 2123 | ) { |
| 2124 | 2124 | // no error message, no change requested, just nothing to do man. |
@@ -2176,7 +2176,7 @@ discard block |
||
| 2176 | 2176 | 'pay_status' => $payment->STS_ID(), |
| 2177 | 2177 | 'PAY_ID' => $payment->ID(), |
| 2178 | 2178 | 'STS_ID' => $payment->STS_ID(), |
| 2179 | - 'status' => self::$_pay_status[ $payment->STS_ID() ], |
|
| 2179 | + 'status' => self::$_pay_status[$payment->STS_ID()], |
|
| 2180 | 2180 | 'date' => $payment->timestamp('Y-m-d', 'h:i a'), |
| 2181 | 2181 | 'method' => strtoupper($payment->source()), |
| 2182 | 2182 | 'PM_ID' => $payment->payment_method() ? $payment->payment_method()->ID() : 1, |
@@ -2296,11 +2296,11 @@ discard block |
||
| 2296 | 2296 | { |
| 2297 | 2297 | $registration_payment_data = array(); |
| 2298 | 2298 | // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows. |
| 2299 | - if (! empty($REG_IDs)) { |
|
| 2299 | + if ( ! empty($REG_IDs)) { |
|
| 2300 | 2300 | $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs)))); |
| 2301 | 2301 | foreach ($registrations as $registration) { |
| 2302 | 2302 | if ($registration instanceof EE_Registration) { |
| 2303 | - $registration_payment_data[ $registration->ID() ] = array( |
|
| 2303 | + $registration_payment_data[$registration->ID()] = array( |
|
| 2304 | 2304 | 'paid' => $registration->pretty_paid(), |
| 2305 | 2305 | 'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()), |
| 2306 | 2306 | ); |
@@ -2412,8 +2412,8 @@ discard block |
||
| 2412 | 2412 | : date('m/d/Y'); |
| 2413 | 2413 | |
| 2414 | 2414 | // make sure our timestamps start and end right at the boundaries for each day |
| 2415 | - $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00'; |
|
| 2416 | - $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59'; |
|
| 2415 | + $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00'; |
|
| 2416 | + $end_date = date('Y-m-d', strtotime($end_date)).' 23:59:59'; |
|
| 2417 | 2417 | |
| 2418 | 2418 | |
| 2419 | 2419 | // convert to timestamps |
@@ -2472,7 +2472,7 @@ discard block |
||
| 2472 | 2472 | } |
| 2473 | 2473 | |
| 2474 | 2474 | if (isset($this->_req_data['s'])) { |
| 2475 | - $search_string = '%' . $this->_req_data['s'] . '%'; |
|
| 2475 | + $search_string = '%'.$this->_req_data['s'].'%'; |
|
| 2476 | 2476 | $_where['OR'] = array( |
| 2477 | 2477 | 'Registration.Event.EVT_name' => array('LIKE', $search_string), |
| 2478 | 2478 | 'Registration.Event.EVT_desc' => array('LIKE', $search_string), |
@@ -2499,11 +2499,11 @@ discard block |
||
| 2499 | 2499 | } |
| 2500 | 2500 | |
| 2501 | 2501 | // failed transactions |
| 2502 | - $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count) |
|
| 2502 | + $failed = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count) |
|
| 2503 | 2503 | || ($count && $view === 'failed'); |
| 2504 | - $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count) |
|
| 2504 | + $abandoned = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count) |
|
| 2505 | 2505 | || ($count && $view === 'abandoned'); |
| 2506 | - $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count) |
|
| 2506 | + $incomplete = ( ! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count) |
|
| 2507 | 2507 | || ($count && $view === 'incomplete'); |
| 2508 | 2508 | |
| 2509 | 2509 | if ($failed) { |
@@ -13,2562 +13,2562 @@ |
||
| 13 | 13 | class Transactions_Admin_Page extends EE_Admin_Page |
| 14 | 14 | { |
| 15 | 15 | |
| 16 | - /** |
|
| 17 | - * @var EE_Transaction |
|
| 18 | - */ |
|
| 19 | - private $_transaction; |
|
| 20 | - |
|
| 21 | - /** |
|
| 22 | - * @var EE_Session |
|
| 23 | - */ |
|
| 24 | - private $_session; |
|
| 25 | - |
|
| 26 | - /** |
|
| 27 | - * @var array $_txn_status |
|
| 28 | - */ |
|
| 29 | - private static $_txn_status; |
|
| 30 | - |
|
| 31 | - /** |
|
| 32 | - * @var array $_pay_status |
|
| 33 | - */ |
|
| 34 | - private static $_pay_status; |
|
| 35 | - |
|
| 36 | - /** |
|
| 37 | - * @var array $_existing_reg_payment_REG_IDs |
|
| 38 | - */ |
|
| 39 | - protected $_existing_reg_payment_REG_IDs; |
|
| 40 | - |
|
| 41 | - |
|
| 42 | - /** |
|
| 43 | - * _init_page_props |
|
| 44 | - * |
|
| 45 | - * @return void |
|
| 46 | - */ |
|
| 47 | - protected function _init_page_props() |
|
| 48 | - { |
|
| 49 | - $this->page_slug = TXN_PG_SLUG; |
|
| 50 | - $this->page_label = esc_html__('Transactions', 'event_espresso'); |
|
| 51 | - $this->_admin_base_url = TXN_ADMIN_URL; |
|
| 52 | - $this->_admin_base_path = TXN_ADMIN; |
|
| 53 | - } |
|
| 54 | - |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * _ajax_hooks |
|
| 58 | - * |
|
| 59 | - * @return void |
|
| 60 | - */ |
|
| 61 | - protected function _ajax_hooks() |
|
| 62 | - { |
|
| 63 | - add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds')); |
|
| 64 | - add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds')); |
|
| 65 | - add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment')); |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - |
|
| 69 | - /** |
|
| 70 | - * _define_page_props |
|
| 71 | - * |
|
| 72 | - * @return void |
|
| 73 | - */ |
|
| 74 | - protected function _define_page_props() |
|
| 75 | - { |
|
| 76 | - $this->_admin_page_title = $this->page_label; |
|
| 77 | - $this->_labels = array( |
|
| 78 | - 'buttons' => array( |
|
| 79 | - 'add' => esc_html__('Add New Transaction', 'event_espresso'), |
|
| 80 | - 'edit' => esc_html__('Edit Transaction', 'event_espresso'), |
|
| 81 | - 'delete' => esc_html__('Delete Transaction', 'event_espresso'), |
|
| 82 | - ), |
|
| 83 | - ); |
|
| 84 | - } |
|
| 85 | - |
|
| 86 | - |
|
| 87 | - /** |
|
| 88 | - * grab url requests and route them |
|
| 89 | - * |
|
| 90 | - * @access private |
|
| 91 | - * @return void |
|
| 92 | - * @throws EE_Error |
|
| 93 | - * @throws InvalidArgumentException |
|
| 94 | - * @throws InvalidDataTypeException |
|
| 95 | - * @throws InvalidInterfaceException |
|
| 96 | - */ |
|
| 97 | - public function _set_page_routes() |
|
| 98 | - { |
|
| 99 | - |
|
| 100 | - $this->_set_transaction_status_array(); |
|
| 101 | - |
|
| 102 | - $txn_id = ! empty($this->_req_data['TXN_ID']) |
|
| 103 | - && ! is_array($this->_req_data['TXN_ID']) |
|
| 104 | - ? $this->_req_data['TXN_ID'] |
|
| 105 | - : 0; |
|
| 106 | - |
|
| 107 | - $this->_page_routes = array( |
|
| 108 | - |
|
| 109 | - 'default' => array( |
|
| 110 | - 'func' => '_transactions_overview_list_table', |
|
| 111 | - 'capability' => 'ee_read_transactions', |
|
| 112 | - ), |
|
| 113 | - |
|
| 114 | - 'view_transaction' => array( |
|
| 115 | - 'func' => '_transaction_details', |
|
| 116 | - 'capability' => 'ee_read_transaction', |
|
| 117 | - 'obj_id' => $txn_id, |
|
| 118 | - ), |
|
| 119 | - |
|
| 120 | - 'send_payment_reminder' => array( |
|
| 121 | - 'func' => '_send_payment_reminder', |
|
| 122 | - 'noheader' => true, |
|
| 123 | - 'capability' => 'ee_send_message', |
|
| 124 | - ), |
|
| 125 | - |
|
| 126 | - 'espresso_apply_payment' => array( |
|
| 127 | - 'func' => 'apply_payments_or_refunds', |
|
| 128 | - 'noheader' => true, |
|
| 129 | - 'capability' => 'ee_edit_payments', |
|
| 130 | - ), |
|
| 131 | - |
|
| 132 | - 'espresso_apply_refund' => array( |
|
| 133 | - 'func' => 'apply_payments_or_refunds', |
|
| 134 | - 'noheader' => true, |
|
| 135 | - 'capability' => 'ee_edit_payments', |
|
| 136 | - ), |
|
| 137 | - |
|
| 138 | - 'espresso_delete_payment' => array( |
|
| 139 | - 'func' => 'delete_payment', |
|
| 140 | - 'noheader' => true, |
|
| 141 | - 'capability' => 'ee_delete_payments', |
|
| 142 | - ), |
|
| 143 | - |
|
| 144 | - 'espresso_recalculate_line_items' => array( |
|
| 145 | - 'func' => 'recalculateLineItems', |
|
| 146 | - 'noheader' => true, |
|
| 147 | - 'capability' => 'ee_edit_payments', |
|
| 148 | - ), |
|
| 149 | - |
|
| 150 | - ); |
|
| 151 | - } |
|
| 152 | - |
|
| 153 | - |
|
| 154 | - protected function _set_page_config() |
|
| 155 | - { |
|
| 156 | - $this->_page_config = array( |
|
| 157 | - 'default' => array( |
|
| 158 | - 'nav' => array( |
|
| 159 | - 'label' => esc_html__('Overview', 'event_espresso'), |
|
| 160 | - 'order' => 10, |
|
| 161 | - ), |
|
| 162 | - 'list_table' => 'EE_Admin_Transactions_List_Table', |
|
| 163 | - 'help_tabs' => array( |
|
| 164 | - 'transactions_overview_help_tab' => array( |
|
| 165 | - 'title' => esc_html__('Transactions Overview', 'event_espresso'), |
|
| 166 | - 'filename' => 'transactions_overview', |
|
| 167 | - ), |
|
| 168 | - 'transactions_overview_table_column_headings_help_tab' => array( |
|
| 169 | - 'title' => esc_html__('Transactions Table Column Headings', 'event_espresso'), |
|
| 170 | - 'filename' => 'transactions_overview_table_column_headings', |
|
| 171 | - ), |
|
| 172 | - 'transactions_overview_views_filters_help_tab' => array( |
|
| 173 | - 'title' => esc_html__('Transaction Views & Filters & Search', 'event_espresso'), |
|
| 174 | - 'filename' => 'transactions_overview_views_filters_search', |
|
| 175 | - ), |
|
| 176 | - ), |
|
| 177 | - 'help_tour' => array('Transactions_Overview_Help_Tour'), |
|
| 178 | - /** |
|
| 179 | - * commented out because currently we are not displaying tips for transaction list table status but this |
|
| 180 | - * may change in a later iteration so want to keep the code for then. |
|
| 181 | - */ |
|
| 182 | - // 'qtips' => array( 'Transactions_List_Table_Tips' ), |
|
| 183 | - 'require_nonce' => false, |
|
| 184 | - ), |
|
| 185 | - 'view_transaction' => array( |
|
| 186 | - 'nav' => array( |
|
| 187 | - 'label' => esc_html__('View Transaction', 'event_espresso'), |
|
| 188 | - 'order' => 5, |
|
| 189 | - 'url' => isset($this->_req_data['TXN_ID']) |
|
| 190 | - ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url) |
|
| 191 | - : $this->_admin_base_url, |
|
| 192 | - 'persistent' => false, |
|
| 193 | - ), |
|
| 194 | - 'help_tabs' => array( |
|
| 195 | - 'transactions_view_transaction_help_tab' => array( |
|
| 196 | - 'title' => esc_html__('View Transaction', 'event_espresso'), |
|
| 197 | - 'filename' => 'transactions_view_transaction', |
|
| 198 | - ), |
|
| 199 | - 'transactions_view_transaction_transaction_details_table_help_tab' => array( |
|
| 200 | - 'title' => esc_html__('Transaction Details Table', 'event_espresso'), |
|
| 201 | - 'filename' => 'transactions_view_transaction_transaction_details_table', |
|
| 202 | - ), |
|
| 203 | - 'transactions_view_transaction_attendees_registered_help_tab' => array( |
|
| 204 | - 'title' => esc_html__('Attendees Registered', 'event_espresso'), |
|
| 205 | - 'filename' => 'transactions_view_transaction_attendees_registered', |
|
| 206 | - ), |
|
| 207 | - 'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array( |
|
| 208 | - 'title' => esc_html__('Primary Registrant & Billing Information', 'event_espresso'), |
|
| 209 | - 'filename' => 'transactions_view_transaction_primary_registrant_billing_information', |
|
| 210 | - ), |
|
| 211 | - ), |
|
| 212 | - 'qtips' => array('Transaction_Details_Tips'), |
|
| 213 | - 'help_tour' => array('Transaction_Details_Help_Tour'), |
|
| 214 | - 'metaboxes' => array('_transaction_details_metaboxes'), |
|
| 215 | - |
|
| 216 | - 'require_nonce' => false, |
|
| 217 | - ), |
|
| 218 | - ); |
|
| 219 | - } |
|
| 220 | - |
|
| 221 | - |
|
| 222 | - /** |
|
| 223 | - * The below methods aren't used by this class currently |
|
| 224 | - */ |
|
| 225 | - protected function _add_screen_options() |
|
| 226 | - { |
|
| 227 | - // noop |
|
| 228 | - } |
|
| 229 | - |
|
| 230 | - |
|
| 231 | - protected function _add_feature_pointers() |
|
| 232 | - { |
|
| 233 | - // noop |
|
| 234 | - } |
|
| 235 | - |
|
| 236 | - |
|
| 237 | - public function admin_init() |
|
| 238 | - { |
|
| 239 | - // IF a registration was JUST added via the admin... |
|
| 240 | - if (isset( |
|
| 241 | - $this->_req_data['redirect_from'], |
|
| 242 | - $this->_req_data['EVT_ID'], |
|
| 243 | - $this->_req_data['event_name'] |
|
| 244 | - )) { |
|
| 245 | - // then set a cookie so that we can block any attempts to use |
|
| 246 | - // the back button as a way to enter another registration. |
|
| 247 | - setcookie( |
|
| 248 | - 'ee_registration_added', |
|
| 249 | - $this->_req_data['EVT_ID'], |
|
| 250 | - time() + WEEK_IN_SECONDS, |
|
| 251 | - '/' |
|
| 252 | - ); |
|
| 253 | - // and update the global |
|
| 254 | - $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID']; |
|
| 255 | - } |
|
| 256 | - EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__( |
|
| 257 | - 'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.', |
|
| 258 | - 'event_espresso' |
|
| 259 | - ); |
|
| 260 | - EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__( |
|
| 261 | - 'An error occurred! Please refresh the page and try again.', |
|
| 262 | - 'event_espresso' |
|
| 263 | - ); |
|
| 264 | - EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status; |
|
| 265 | - EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status; |
|
| 266 | - EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso'); |
|
| 267 | - EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__( |
|
| 268 | - 'This transaction has been overpaid ! Payments Total', |
|
| 269 | - 'event_espresso' |
|
| 270 | - ); |
|
| 271 | - } |
|
| 272 | - |
|
| 273 | - |
|
| 274 | - public function admin_notices() |
|
| 275 | - { |
|
| 276 | - // noop |
|
| 277 | - } |
|
| 278 | - |
|
| 279 | - |
|
| 280 | - public function admin_footer_scripts() |
|
| 281 | - { |
|
| 282 | - // noop |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - |
|
| 286 | - /** |
|
| 287 | - * _set_transaction_status_array |
|
| 288 | - * sets list of transaction statuses |
|
| 289 | - * |
|
| 290 | - * @access private |
|
| 291 | - * @return void |
|
| 292 | - * @throws EE_Error |
|
| 293 | - * @throws InvalidArgumentException |
|
| 294 | - * @throws InvalidDataTypeException |
|
| 295 | - * @throws InvalidInterfaceException |
|
| 296 | - */ |
|
| 297 | - private function _set_transaction_status_array() |
|
| 298 | - { |
|
| 299 | - self::$_txn_status = EEM_Transaction::instance()->status_array(true); |
|
| 300 | - } |
|
| 301 | - |
|
| 302 | - |
|
| 303 | - /** |
|
| 304 | - * get_transaction_status_array |
|
| 305 | - * return the transaction status array for wp_list_table |
|
| 306 | - * |
|
| 307 | - * @access public |
|
| 308 | - * @return array |
|
| 309 | - */ |
|
| 310 | - public function get_transaction_status_array() |
|
| 311 | - { |
|
| 312 | - return self::$_txn_status; |
|
| 313 | - } |
|
| 314 | - |
|
| 315 | - |
|
| 316 | - /** |
|
| 317 | - * get list of payment statuses |
|
| 318 | - * |
|
| 319 | - * @access private |
|
| 320 | - * @return void |
|
| 321 | - * @throws EE_Error |
|
| 322 | - * @throws InvalidArgumentException |
|
| 323 | - * @throws InvalidDataTypeException |
|
| 324 | - * @throws InvalidInterfaceException |
|
| 325 | - */ |
|
| 326 | - private function _get_payment_status_array() |
|
| 327 | - { |
|
| 328 | - self::$_pay_status = EEM_Payment::instance()->status_array(true); |
|
| 329 | - $this->_template_args['payment_status'] = self::$_pay_status; |
|
| 330 | - } |
|
| 331 | - |
|
| 332 | - |
|
| 333 | - /** |
|
| 334 | - * _add_screen_options_default |
|
| 335 | - * |
|
| 336 | - * @access protected |
|
| 337 | - * @return void |
|
| 338 | - * @throws InvalidArgumentException |
|
| 339 | - * @throws InvalidDataTypeException |
|
| 340 | - * @throws InvalidInterfaceException |
|
| 341 | - */ |
|
| 342 | - protected function _add_screen_options_default() |
|
| 343 | - { |
|
| 344 | - $this->_per_page_screen_option(); |
|
| 345 | - } |
|
| 346 | - |
|
| 347 | - |
|
| 348 | - /** |
|
| 349 | - * load_scripts_styles |
|
| 350 | - * |
|
| 351 | - * @access public |
|
| 352 | - * @return void |
|
| 353 | - */ |
|
| 354 | - public function load_scripts_styles() |
|
| 355 | - { |
|
| 356 | - // enqueue style |
|
| 357 | - wp_register_style( |
|
| 358 | - 'espresso_txn', |
|
| 359 | - TXN_ASSETS_URL . 'espresso_transactions_admin.css', |
|
| 360 | - array(), |
|
| 361 | - EVENT_ESPRESSO_VERSION |
|
| 362 | - ); |
|
| 363 | - wp_enqueue_style('espresso_txn'); |
|
| 364 | - // scripts |
|
| 365 | - wp_register_script( |
|
| 366 | - 'espresso_txn', |
|
| 367 | - TXN_ASSETS_URL . 'espresso_transactions_admin.js', |
|
| 368 | - array( |
|
| 369 | - 'ee_admin_js', |
|
| 370 | - 'ee-datepicker', |
|
| 371 | - 'jquery-ui-datepicker', |
|
| 372 | - 'jquery-ui-draggable', |
|
| 373 | - 'ee-dialog', |
|
| 374 | - 'ee-accounting', |
|
| 375 | - 'ee-serialize-full-array', |
|
| 376 | - ), |
|
| 377 | - EVENT_ESPRESSO_VERSION, |
|
| 378 | - true |
|
| 379 | - ); |
|
| 380 | - wp_enqueue_script('espresso_txn'); |
|
| 381 | - } |
|
| 382 | - |
|
| 383 | - |
|
| 384 | - /** |
|
| 385 | - * load_scripts_styles_view_transaction |
|
| 386 | - * |
|
| 387 | - * @access public |
|
| 388 | - * @return void |
|
| 389 | - */ |
|
| 390 | - public function load_scripts_styles_view_transaction() |
|
| 391 | - { |
|
| 392 | - // styles |
|
| 393 | - wp_enqueue_style('espresso-ui-theme'); |
|
| 394 | - } |
|
| 395 | - |
|
| 396 | - |
|
| 397 | - /** |
|
| 398 | - * load_scripts_styles_default |
|
| 399 | - * |
|
| 400 | - * @access public |
|
| 401 | - * @return void |
|
| 402 | - */ |
|
| 403 | - public function load_scripts_styles_default() |
|
| 404 | - { |
|
| 405 | - // styles |
|
| 406 | - wp_enqueue_style('espresso-ui-theme'); |
|
| 407 | - } |
|
| 408 | - |
|
| 409 | - |
|
| 410 | - /** |
|
| 411 | - * _set_list_table_views_default |
|
| 412 | - * |
|
| 413 | - * @access protected |
|
| 414 | - * @return void |
|
| 415 | - */ |
|
| 416 | - protected function _set_list_table_views_default() |
|
| 417 | - { |
|
| 418 | - $this->_views = array( |
|
| 419 | - 'all' => array( |
|
| 420 | - 'slug' => 'all', |
|
| 421 | - 'label' => esc_html__('View All Transactions', 'event_espresso'), |
|
| 422 | - 'count' => 0, |
|
| 423 | - ), |
|
| 424 | - 'abandoned' => array( |
|
| 425 | - 'slug' => 'abandoned', |
|
| 426 | - 'label' => esc_html__('Abandoned Transactions', 'event_espresso'), |
|
| 427 | - 'count' => 0, |
|
| 428 | - ), |
|
| 429 | - 'incomplete' => array( |
|
| 430 | - 'slug' => 'incomplete', |
|
| 431 | - 'label' => esc_html__('Incomplete Transactions', 'event_espresso'), |
|
| 432 | - 'count' => 0, |
|
| 433 | - ), |
|
| 434 | - ); |
|
| 435 | - if (/** |
|
| 436 | - * Filters whether a link to the "Failed Transactions" list table |
|
| 437 | - * appears on the Transactions Admin Page list table. |
|
| 438 | - * List display can be turned back on via the following: |
|
| 439 | - * add_filter( |
|
| 440 | - * 'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list', |
|
| 441 | - * '__return_true' |
|
| 442 | - * ); |
|
| 443 | - * |
|
| 444 | - * @since 4.9.70.p |
|
| 445 | - * @param boolean $display_failed_txns_list |
|
| 446 | - * @param Transactions_Admin_Page $this |
|
| 447 | - */ |
|
| 448 | - apply_filters( |
|
| 449 | - 'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list', |
|
| 450 | - false, |
|
| 451 | - $this |
|
| 452 | - ) |
|
| 453 | - ) { |
|
| 454 | - $this->_views['failed'] = array( |
|
| 455 | - 'slug' => 'failed', |
|
| 456 | - 'label' => esc_html__('Failed Transactions', 'event_espresso'), |
|
| 457 | - 'count' => 0, |
|
| 458 | - ); |
|
| 459 | - } |
|
| 460 | - } |
|
| 461 | - |
|
| 462 | - |
|
| 463 | - /** |
|
| 464 | - * _set_transaction_object |
|
| 465 | - * This sets the _transaction property for the transaction details screen |
|
| 466 | - * |
|
| 467 | - * @access private |
|
| 468 | - * @return void |
|
| 469 | - * @throws EE_Error |
|
| 470 | - * @throws InvalidArgumentException |
|
| 471 | - * @throws RuntimeException |
|
| 472 | - * @throws InvalidDataTypeException |
|
| 473 | - * @throws InvalidInterfaceException |
|
| 474 | - * @throws ReflectionException |
|
| 475 | - */ |
|
| 476 | - private function _set_transaction_object() |
|
| 477 | - { |
|
| 478 | - if ($this->_transaction instanceof EE_Transaction) { |
|
| 479 | - return; |
|
| 480 | - } //get out we've already set the object |
|
| 481 | - |
|
| 482 | - $TXN_ID = ! empty($this->_req_data['TXN_ID']) |
|
| 483 | - ? absint($this->_req_data['TXN_ID']) |
|
| 484 | - : false; |
|
| 485 | - |
|
| 486 | - // get transaction object |
|
| 487 | - $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
| 488 | - $this->_session = $this->_transaction instanceof EE_Transaction |
|
| 489 | - ? $this->_transaction->session_data() |
|
| 490 | - : null; |
|
| 491 | - if ($this->_transaction instanceof EE_Transaction) { |
|
| 492 | - $this->_transaction->verify_abandoned_transaction_status(); |
|
| 493 | - } |
|
| 494 | - |
|
| 495 | - if (! $this->_transaction instanceof EE_Transaction) { |
|
| 496 | - $error_msg = sprintf( |
|
| 497 | - esc_html__( |
|
| 498 | - 'An error occurred and the details for the transaction with the ID # %d could not be retrieved.', |
|
| 499 | - 'event_espresso' |
|
| 500 | - ), |
|
| 501 | - $TXN_ID |
|
| 502 | - ); |
|
| 503 | - EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 504 | - } |
|
| 505 | - } |
|
| 506 | - |
|
| 507 | - |
|
| 508 | - /** |
|
| 509 | - * _transaction_legend_items |
|
| 510 | - * |
|
| 511 | - * @access protected |
|
| 512 | - * @return array |
|
| 513 | - * @throws EE_Error |
|
| 514 | - * @throws InvalidArgumentException |
|
| 515 | - * @throws ReflectionException |
|
| 516 | - * @throws InvalidDataTypeException |
|
| 517 | - * @throws InvalidInterfaceException |
|
| 518 | - */ |
|
| 519 | - protected function _transaction_legend_items() |
|
| 520 | - { |
|
| 521 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
| 522 | - $items = array(); |
|
| 523 | - |
|
| 524 | - if (EE_Registry::instance()->CAP->current_user_can( |
|
| 525 | - 'ee_read_global_messages', |
|
| 526 | - 'view_filtered_messages' |
|
| 527 | - )) { |
|
| 528 | - $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for'); |
|
| 529 | - if (is_array($related_for_icon) |
|
| 530 | - && isset($related_for_icon['css_class'], $related_for_icon['label']) |
|
| 531 | - ) { |
|
| 532 | - $items['view_related_messages'] = array( |
|
| 533 | - 'class' => $related_for_icon['css_class'], |
|
| 534 | - 'desc' => $related_for_icon['label'], |
|
| 535 | - ); |
|
| 536 | - } |
|
| 537 | - } |
|
| 538 | - |
|
| 539 | - $items = apply_filters( |
|
| 540 | - 'FHEE__Transactions_Admin_Page___transaction_legend_items__items', |
|
| 541 | - array_merge( |
|
| 542 | - $items, |
|
| 543 | - array( |
|
| 544 | - 'view_details' => array( |
|
| 545 | - 'class' => 'dashicons dashicons-cart', |
|
| 546 | - 'desc' => esc_html__('View Transaction Details', 'event_espresso'), |
|
| 547 | - ), |
|
| 548 | - 'view_invoice' => array( |
|
| 549 | - 'class' => 'dashicons dashicons-media-spreadsheet', |
|
| 550 | - 'desc' => esc_html__('View Transaction Invoice', 'event_espresso'), |
|
| 551 | - ), |
|
| 552 | - 'view_receipt' => array( |
|
| 553 | - 'class' => 'dashicons dashicons-media-default', |
|
| 554 | - 'desc' => esc_html__('View Transaction Receipt', 'event_espresso'), |
|
| 555 | - ), |
|
| 556 | - 'view_registration' => array( |
|
| 557 | - 'class' => 'dashicons dashicons-clipboard', |
|
| 558 | - 'desc' => esc_html__('View Registration Details', 'event_espresso'), |
|
| 559 | - ), |
|
| 560 | - 'payment_overview_link' => array( |
|
| 561 | - 'class' => 'dashicons dashicons-money', |
|
| 562 | - 'desc' => esc_html__('Make Payment on Frontend', 'event_espresso'), |
|
| 563 | - ), |
|
| 564 | - ) |
|
| 565 | - ) |
|
| 566 | - ); |
|
| 567 | - |
|
| 568 | - if (EEH_MSG_Template::is_mt_active('payment_reminder') |
|
| 569 | - && EE_Registry::instance()->CAP->current_user_can( |
|
| 570 | - 'ee_send_message', |
|
| 571 | - 'espresso_transactions_send_payment_reminder' |
|
| 572 | - ) |
|
| 573 | - ) { |
|
| 574 | - $items['send_payment_reminder'] = array( |
|
| 575 | - 'class' => 'dashicons dashicons-email-alt', |
|
| 576 | - 'desc' => esc_html__('Send Payment Reminder', 'event_espresso'), |
|
| 577 | - ); |
|
| 578 | - } else { |
|
| 579 | - $items['blank*'] = array( |
|
| 580 | - 'class' => '', |
|
| 581 | - 'desc' => '', |
|
| 582 | - ); |
|
| 583 | - } |
|
| 584 | - $more_items = apply_filters( |
|
| 585 | - 'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items', |
|
| 586 | - array( |
|
| 587 | - 'overpaid' => array( |
|
| 588 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code, |
|
| 589 | - 'desc' => EEH_Template::pretty_status( |
|
| 590 | - EEM_Transaction::overpaid_status_code, |
|
| 591 | - false, |
|
| 592 | - 'sentence' |
|
| 593 | - ), |
|
| 594 | - ), |
|
| 595 | - 'complete' => array( |
|
| 596 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code, |
|
| 597 | - 'desc' => EEH_Template::pretty_status( |
|
| 598 | - EEM_Transaction::complete_status_code, |
|
| 599 | - false, |
|
| 600 | - 'sentence' |
|
| 601 | - ), |
|
| 602 | - ), |
|
| 603 | - 'incomplete' => array( |
|
| 604 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code, |
|
| 605 | - 'desc' => EEH_Template::pretty_status( |
|
| 606 | - EEM_Transaction::incomplete_status_code, |
|
| 607 | - false, |
|
| 608 | - 'sentence' |
|
| 609 | - ), |
|
| 610 | - ), |
|
| 611 | - 'abandoned' => array( |
|
| 612 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code, |
|
| 613 | - 'desc' => EEH_Template::pretty_status( |
|
| 614 | - EEM_Transaction::abandoned_status_code, |
|
| 615 | - false, |
|
| 616 | - 'sentence' |
|
| 617 | - ), |
|
| 618 | - ), |
|
| 619 | - 'failed' => array( |
|
| 620 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code, |
|
| 621 | - 'desc' => EEH_Template::pretty_status( |
|
| 622 | - EEM_Transaction::failed_status_code, |
|
| 623 | - false, |
|
| 624 | - 'sentence' |
|
| 625 | - ), |
|
| 626 | - ), |
|
| 627 | - ) |
|
| 628 | - ); |
|
| 629 | - |
|
| 630 | - return array_merge($items, $more_items); |
|
| 631 | - } |
|
| 632 | - |
|
| 633 | - |
|
| 634 | - /** |
|
| 635 | - * _transactions_overview_list_table |
|
| 636 | - * |
|
| 637 | - * @access protected |
|
| 638 | - * @return void |
|
| 639 | - * @throws DomainException |
|
| 640 | - * @throws EE_Error |
|
| 641 | - * @throws InvalidArgumentException |
|
| 642 | - * @throws InvalidDataTypeException |
|
| 643 | - * @throws InvalidInterfaceException |
|
| 644 | - * @throws ReflectionException |
|
| 645 | - */ |
|
| 646 | - protected function _transactions_overview_list_table() |
|
| 647 | - { |
|
| 648 | - $this->_admin_page_title = esc_html__('Transactions', 'event_espresso'); |
|
| 649 | - $event = isset($this->_req_data['EVT_ID']) |
|
| 650 | - ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']) |
|
| 651 | - : null; |
|
| 652 | - $this->_template_args['admin_page_header'] = $event instanceof EE_Event |
|
| 653 | - ? sprintf( |
|
| 654 | - esc_html__( |
|
| 655 | - '%sViewing Transactions for the Event: %s%s', |
|
| 656 | - 'event_espresso' |
|
| 657 | - ), |
|
| 658 | - '<h3>', |
|
| 659 | - '<a href="' |
|
| 660 | - . EE_Admin_Page::add_query_args_and_nonce( |
|
| 661 | - array('action' => 'edit', 'post' => $event->ID()), |
|
| 662 | - EVENTS_ADMIN_URL |
|
| 663 | - ) |
|
| 664 | - . '" title="' |
|
| 665 | - . esc_attr__( |
|
| 666 | - 'Click to Edit event', |
|
| 667 | - 'event_espresso' |
|
| 668 | - ) |
|
| 669 | - . '">' . $event->name() . '</a>', |
|
| 670 | - '</h3>' |
|
| 671 | - ) |
|
| 672 | - : ''; |
|
| 673 | - $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items()); |
|
| 674 | - $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 675 | - } |
|
| 676 | - |
|
| 677 | - |
|
| 678 | - /** |
|
| 679 | - * _transaction_details |
|
| 680 | - * generates HTML for the View Transaction Details Admin page |
|
| 681 | - * |
|
| 682 | - * @access protected |
|
| 683 | - * @return void |
|
| 684 | - * @throws DomainException |
|
| 685 | - * @throws EE_Error |
|
| 686 | - * @throws InvalidArgumentException |
|
| 687 | - * @throws InvalidDataTypeException |
|
| 688 | - * @throws InvalidInterfaceException |
|
| 689 | - * @throws RuntimeException |
|
| 690 | - * @throws ReflectionException |
|
| 691 | - */ |
|
| 692 | - protected function _transaction_details() |
|
| 693 | - { |
|
| 694 | - do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction); |
|
| 695 | - |
|
| 696 | - $this->_set_transaction_status_array(); |
|
| 697 | - |
|
| 698 | - $this->_template_args = array(); |
|
| 699 | - $this->_template_args['transactions_page'] = $this->_wp_page_slug; |
|
| 700 | - |
|
| 701 | - $this->_set_transaction_object(); |
|
| 702 | - |
|
| 703 | - if (! $this->_transaction instanceof EE_Transaction) { |
|
| 704 | - return; |
|
| 705 | - } |
|
| 706 | - $primary_registration = $this->_transaction->primary_registration(); |
|
| 707 | - $attendee = $primary_registration instanceof EE_Registration |
|
| 708 | - ? $primary_registration->attendee() |
|
| 709 | - : null; |
|
| 710 | - |
|
| 711 | - $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID(); |
|
| 712 | - $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso'); |
|
| 713 | - |
|
| 714 | - $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp'); |
|
| 715 | - $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso'); |
|
| 716 | - |
|
| 717 | - $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ]; |
|
| 718 | - $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso'); |
|
| 719 | - $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID(); |
|
| 720 | - |
|
| 721 | - $this->_template_args['grand_total'] = $this->_transaction->total(); |
|
| 722 | - $this->_template_args['total_paid'] = $this->_transaction->paid(); |
|
| 723 | - |
|
| 724 | - $amount_due = $this->_transaction->total() - $this->_transaction->paid(); |
|
| 725 | - $this->_template_args['amount_due'] = EEH_Template::format_currency( |
|
| 726 | - $amount_due, |
|
| 727 | - true |
|
| 728 | - ); |
|
| 729 | - if (EE_Registry::instance()->CFG->currency->sign_b4) { |
|
| 730 | - $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign |
|
| 731 | - . $this->_template_args['amount_due']; |
|
| 732 | - } else { |
|
| 733 | - $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign; |
|
| 734 | - } |
|
| 735 | - $this->_template_args['amount_due_class'] = ''; |
|
| 736 | - |
|
| 737 | - if ($this->_transaction->paid() === $this->_transaction->total()) { |
|
| 738 | - // paid in full |
|
| 739 | - $this->_template_args['amount_due'] = false; |
|
| 740 | - } elseif ($this->_transaction->paid() > $this->_transaction->total()) { |
|
| 741 | - // overpaid |
|
| 742 | - $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn'; |
|
| 743 | - } elseif ($this->_transaction->total() > (float) 0) { |
|
| 744 | - if ($this->_transaction->paid() > (float) 0) { |
|
| 745 | - // monies owing |
|
| 746 | - $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn'; |
|
| 747 | - } elseif ($this->_transaction->paid() === (float) 0) { |
|
| 748 | - // no payments made yet |
|
| 749 | - $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn'; |
|
| 750 | - } |
|
| 751 | - } elseif ($this->_transaction->total() === (float) 0) { |
|
| 752 | - // free event |
|
| 753 | - $this->_template_args['amount_due'] = false; |
|
| 754 | - } |
|
| 755 | - |
|
| 756 | - $payment_method = $this->_transaction->payment_method(); |
|
| 757 | - |
|
| 758 | - $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method |
|
| 759 | - ? $payment_method->admin_name() |
|
| 760 | - : esc_html__('Unknown', 'event_espresso'); |
|
| 761 | - |
|
| 762 | - $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign; |
|
| 763 | - // link back to overview |
|
| 764 | - $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER']) |
|
| 765 | - ? $_SERVER['HTTP_REFERER'] |
|
| 766 | - : TXN_ADMIN_URL; |
|
| 767 | - |
|
| 768 | - |
|
| 769 | - // next link |
|
| 770 | - $next_txn = $this->_transaction->next( |
|
| 771 | - null, |
|
| 772 | - array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))), |
|
| 773 | - 'TXN_ID' |
|
| 774 | - ); |
|
| 775 | - $this->_template_args['next_transaction'] = $next_txn |
|
| 776 | - ? $this->_next_link( |
|
| 777 | - EE_Admin_Page::add_query_args_and_nonce( |
|
| 778 | - array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']), |
|
| 779 | - TXN_ADMIN_URL |
|
| 780 | - ), |
|
| 781 | - 'dashicons dashicons-arrow-right ee-icon-size-22' |
|
| 782 | - ) |
|
| 783 | - : ''; |
|
| 784 | - // previous link |
|
| 785 | - $previous_txn = $this->_transaction->previous( |
|
| 786 | - null, |
|
| 787 | - array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))), |
|
| 788 | - 'TXN_ID' |
|
| 789 | - ); |
|
| 790 | - $this->_template_args['previous_transaction'] = $previous_txn |
|
| 791 | - ? $this->_previous_link( |
|
| 792 | - EE_Admin_Page::add_query_args_and_nonce( |
|
| 793 | - array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']), |
|
| 794 | - TXN_ADMIN_URL |
|
| 795 | - ), |
|
| 796 | - 'dashicons dashicons-arrow-left ee-icon-size-22' |
|
| 797 | - ) |
|
| 798 | - : ''; |
|
| 799 | - |
|
| 800 | - // were we just redirected here after adding a new registration ??? |
|
| 801 | - if (isset( |
|
| 802 | - $this->_req_data['redirect_from'], |
|
| 803 | - $this->_req_data['EVT_ID'], |
|
| 804 | - $this->_req_data['event_name'] |
|
| 805 | - )) { |
|
| 806 | - if (EE_Registry::instance()->CAP->current_user_can( |
|
| 807 | - 'ee_edit_registrations', |
|
| 808 | - 'espresso_registrations_new_registration', |
|
| 809 | - $this->_req_data['EVT_ID'] |
|
| 810 | - )) { |
|
| 811 | - $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="'; |
|
| 812 | - $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce( |
|
| 813 | - array( |
|
| 814 | - 'page' => 'espresso_registrations', |
|
| 815 | - 'action' => 'new_registration', |
|
| 816 | - 'return' => 'default', |
|
| 817 | - 'TXN_ID' => $this->_transaction->ID(), |
|
| 818 | - 'event_id' => $this->_req_data['EVT_ID'], |
|
| 819 | - ), |
|
| 820 | - REG_ADMIN_URL |
|
| 821 | - ); |
|
| 822 | - $this->_admin_page_title .= '">'; |
|
| 823 | - |
|
| 824 | - $this->_admin_page_title .= sprintf( |
|
| 825 | - esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'), |
|
| 826 | - htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8') |
|
| 827 | - ); |
|
| 828 | - $this->_admin_page_title .= '</a>'; |
|
| 829 | - } |
|
| 830 | - EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__); |
|
| 831 | - } |
|
| 832 | - // grab messages at the last second |
|
| 833 | - $this->_template_args['notices'] = EE_Error::get_notices(); |
|
| 834 | - // path to template |
|
| 835 | - $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php'; |
|
| 836 | - $this->_template_args['admin_page_header'] = EEH_Template::display_template( |
|
| 837 | - $template_path, |
|
| 838 | - $this->_template_args, |
|
| 839 | - true |
|
| 840 | - ); |
|
| 841 | - |
|
| 842 | - // the details template wrapper |
|
| 843 | - $this->display_admin_page_with_sidebar(); |
|
| 844 | - } |
|
| 845 | - |
|
| 846 | - |
|
| 847 | - /** |
|
| 848 | - * _transaction_details_metaboxes |
|
| 849 | - * |
|
| 850 | - * @access protected |
|
| 851 | - * @return void |
|
| 852 | - * @throws EE_Error |
|
| 853 | - * @throws InvalidArgumentException |
|
| 854 | - * @throws InvalidDataTypeException |
|
| 855 | - * @throws InvalidInterfaceException |
|
| 856 | - * @throws RuntimeException |
|
| 857 | - * @throws ReflectionException |
|
| 858 | - */ |
|
| 859 | - protected function _transaction_details_metaboxes() |
|
| 860 | - { |
|
| 861 | - |
|
| 862 | - $this->_set_transaction_object(); |
|
| 863 | - |
|
| 864 | - if (! $this->_transaction instanceof EE_Transaction) { |
|
| 865 | - return; |
|
| 866 | - } |
|
| 867 | - add_meta_box( |
|
| 868 | - 'edit-txn-details-mbox', |
|
| 869 | - esc_html__('Transaction Details', 'event_espresso'), |
|
| 870 | - array($this, 'txn_details_meta_box'), |
|
| 871 | - $this->_wp_page_slug, |
|
| 872 | - 'normal', |
|
| 873 | - 'high' |
|
| 874 | - ); |
|
| 875 | - add_meta_box( |
|
| 876 | - 'edit-txn-attendees-mbox', |
|
| 877 | - esc_html__('Attendees Registered in this Transaction', 'event_espresso'), |
|
| 878 | - array($this, 'txn_attendees_meta_box'), |
|
| 879 | - $this->_wp_page_slug, |
|
| 880 | - 'normal', |
|
| 881 | - 'high', |
|
| 882 | - array('TXN_ID' => $this->_transaction->ID()) |
|
| 883 | - ); |
|
| 884 | - add_meta_box( |
|
| 885 | - 'edit-txn-registrant-mbox', |
|
| 886 | - esc_html__('Primary Contact', 'event_espresso'), |
|
| 887 | - array($this, 'txn_registrant_side_meta_box'), |
|
| 888 | - $this->_wp_page_slug, |
|
| 889 | - 'side', |
|
| 890 | - 'high' |
|
| 891 | - ); |
|
| 892 | - add_meta_box( |
|
| 893 | - 'edit-txn-billing-info-mbox', |
|
| 894 | - esc_html__('Billing Information', 'event_espresso'), |
|
| 895 | - array($this, 'txn_billing_info_side_meta_box'), |
|
| 896 | - $this->_wp_page_slug, |
|
| 897 | - 'side', |
|
| 898 | - 'high' |
|
| 899 | - ); |
|
| 900 | - } |
|
| 901 | - |
|
| 902 | - |
|
| 903 | - /** |
|
| 904 | - * Callback for transaction actions metabox. |
|
| 905 | - * |
|
| 906 | - * @param EE_Transaction|null $transaction |
|
| 907 | - * @return string |
|
| 908 | - * @throws DomainException |
|
| 909 | - * @throws EE_Error |
|
| 910 | - * @throws InvalidArgumentException |
|
| 911 | - * @throws InvalidDataTypeException |
|
| 912 | - * @throws InvalidInterfaceException |
|
| 913 | - * @throws ReflectionException |
|
| 914 | - * @throws RuntimeException |
|
| 915 | - */ |
|
| 916 | - public function getActionButtons(EE_Transaction $transaction = null) |
|
| 917 | - { |
|
| 918 | - $content = ''; |
|
| 919 | - $actions = array(); |
|
| 920 | - if (! $transaction instanceof EE_Transaction) { |
|
| 921 | - return $content; |
|
| 922 | - } |
|
| 923 | - /** @var EE_Registration $primary_registration */ |
|
| 924 | - $primary_registration = $transaction->primary_registration(); |
|
| 925 | - $attendee = $primary_registration instanceof EE_Registration |
|
| 926 | - ? $primary_registration->attendee() |
|
| 927 | - : null; |
|
| 928 | - |
|
| 929 | - if ($attendee instanceof EE_Attendee |
|
| 930 | - && EE_Registry::instance()->CAP->current_user_can( |
|
| 931 | - 'ee_send_message', |
|
| 932 | - 'espresso_transactions_send_payment_reminder' |
|
| 933 | - ) |
|
| 934 | - ) { |
|
| 935 | - $actions['payment_reminder'] = |
|
| 936 | - EEH_MSG_Template::is_mt_active('payment_reminder') |
|
| 937 | - && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code |
|
| 938 | - && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code |
|
| 939 | - ? EEH_Template::get_button_or_link( |
|
| 940 | - EE_Admin_Page::add_query_args_and_nonce( |
|
| 941 | - array( |
|
| 942 | - 'action' => 'send_payment_reminder', |
|
| 943 | - 'TXN_ID' => $this->_transaction->ID(), |
|
| 944 | - 'redirect_to' => 'view_transaction', |
|
| 945 | - ), |
|
| 946 | - TXN_ADMIN_URL |
|
| 947 | - ), |
|
| 948 | - esc_html__(' Send Payment Reminder', 'event_espresso'), |
|
| 949 | - 'button secondary-button', |
|
| 950 | - 'dashicons dashicons-email-alt' |
|
| 951 | - ) |
|
| 952 | - : ''; |
|
| 953 | - } |
|
| 954 | - |
|
| 955 | - if (EE_Registry::instance()->CAP->current_user_can( |
|
| 956 | - 'ee_edit_payments', |
|
| 957 | - 'espresso_transactions_recalculate_line_items' |
|
| 958 | - ) |
|
| 959 | - ) { |
|
| 960 | - $actions['recalculate_line_items'] = EEH_Template::get_button_or_link( |
|
| 961 | - EE_Admin_Page::add_query_args_and_nonce( |
|
| 962 | - array( |
|
| 963 | - 'action' => 'espresso_recalculate_line_items', |
|
| 964 | - 'TXN_ID' => $this->_transaction->ID(), |
|
| 965 | - 'redirect_to' => 'view_transaction', |
|
| 966 | - ), |
|
| 967 | - TXN_ADMIN_URL |
|
| 968 | - ), |
|
| 969 | - esc_html__(' Recalculate Taxes and Total', 'event_espresso'), |
|
| 970 | - 'button secondary-button', |
|
| 971 | - 'dashicons dashicons-update' |
|
| 972 | - ); |
|
| 973 | - } |
|
| 974 | - |
|
| 975 | - if ($primary_registration instanceof EE_Registration |
|
| 976 | - && EEH_MSG_Template::is_mt_active('receipt') |
|
| 977 | - ) { |
|
| 978 | - $actions['receipt'] = EEH_Template::get_button_or_link( |
|
| 979 | - $primary_registration->receipt_url(), |
|
| 980 | - esc_html__('View Receipt', 'event_espresso'), |
|
| 981 | - 'button secondary-button', |
|
| 982 | - 'dashicons dashicons-media-default' |
|
| 983 | - ); |
|
| 984 | - } |
|
| 985 | - |
|
| 986 | - if ($primary_registration instanceof EE_Registration |
|
| 987 | - && EEH_MSG_Template::is_mt_active('invoice') |
|
| 988 | - ) { |
|
| 989 | - $actions['invoice'] = EEH_Template::get_button_or_link( |
|
| 990 | - $primary_registration->invoice_url(), |
|
| 991 | - esc_html__('View Invoice', 'event_espresso'), |
|
| 992 | - 'button secondary-button', |
|
| 993 | - 'dashicons dashicons-media-spreadsheet' |
|
| 994 | - ); |
|
| 995 | - } |
|
| 996 | - $actions = array_filter( |
|
| 997 | - apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction) |
|
| 998 | - ); |
|
| 999 | - if ($actions) { |
|
| 1000 | - $content = '<ul>'; |
|
| 1001 | - $content .= '<li>' . implode('</li><li>', $actions) . '</li>'; |
|
| 1002 | - $content .= '</uL>'; |
|
| 1003 | - } |
|
| 1004 | - return $content; |
|
| 1005 | - } |
|
| 1006 | - |
|
| 1007 | - |
|
| 1008 | - /** |
|
| 1009 | - * txn_details_meta_box |
|
| 1010 | - * generates HTML for the Transaction main meta box |
|
| 1011 | - * |
|
| 1012 | - * @return void |
|
| 1013 | - * @throws DomainException |
|
| 1014 | - * @throws EE_Error |
|
| 1015 | - * @throws InvalidArgumentException |
|
| 1016 | - * @throws InvalidDataTypeException |
|
| 1017 | - * @throws InvalidInterfaceException |
|
| 1018 | - * @throws RuntimeException |
|
| 1019 | - * @throws ReflectionException |
|
| 1020 | - */ |
|
| 1021 | - public function txn_details_meta_box() |
|
| 1022 | - { |
|
| 1023 | - $this->_set_transaction_object(); |
|
| 1024 | - $this->_template_args['TXN_ID'] = $this->_transaction->ID(); |
|
| 1025 | - $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration |
|
| 1026 | - ? $this->_transaction->primary_registration()->attendee() |
|
| 1027 | - : null; |
|
| 1028 | - $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can( |
|
| 1029 | - 'ee_edit_payments', |
|
| 1030 | - 'apply_payment_or_refund_from_registration_details' |
|
| 1031 | - ); |
|
| 1032 | - $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can( |
|
| 1033 | - 'ee_delete_payments', |
|
| 1034 | - 'delete_payment_from_registration_details' |
|
| 1035 | - ); |
|
| 1036 | - |
|
| 1037 | - // get line table |
|
| 1038 | - EEH_Autoloader::register_line_item_display_autoloaders(); |
|
| 1039 | - $Line_Item_Display = new EE_Line_Item_Display( |
|
| 1040 | - 'admin_table', |
|
| 1041 | - 'EE_Admin_Table_Line_Item_Display_Strategy' |
|
| 1042 | - ); |
|
| 1043 | - $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item( |
|
| 1044 | - $this->_transaction->total_line_item() |
|
| 1045 | - ); |
|
| 1046 | - $this->_template_args['REG_code'] = $this->_transaction->primary_registration()->reg_code(); |
|
| 1047 | - |
|
| 1048 | - // process taxes |
|
| 1049 | - $taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax))); |
|
| 1050 | - $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false; |
|
| 1051 | - |
|
| 1052 | - $this->_template_args['grand_total'] = EEH_Template::format_currency( |
|
| 1053 | - $this->_transaction->total(), |
|
| 1054 | - false, |
|
| 1055 | - false |
|
| 1056 | - ); |
|
| 1057 | - $this->_template_args['grand_raw_total'] = $this->_transaction->total(); |
|
| 1058 | - $this->_template_args['TXN_status'] = $this->_transaction->status_ID(); |
|
| 1059 | - |
|
| 1060 | - // process payment details |
|
| 1061 | - $payments = $this->_transaction->payments(); |
|
| 1062 | - if (! empty($payments)) { |
|
| 1063 | - $this->_template_args['payments'] = $payments; |
|
| 1064 | - $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments); |
|
| 1065 | - } else { |
|
| 1066 | - $this->_template_args['payments'] = false; |
|
| 1067 | - $this->_template_args['existing_reg_payments'] = array(); |
|
| 1068 | - } |
|
| 1069 | - |
|
| 1070 | - $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL); |
|
| 1071 | - $this->_template_args['delete_payment_url'] = add_query_arg( |
|
| 1072 | - array('action' => 'espresso_delete_payment'), |
|
| 1073 | - TXN_ADMIN_URL |
|
| 1074 | - ); |
|
| 1075 | - |
|
| 1076 | - if (isset($txn_details['invoice_number'])) { |
|
| 1077 | - $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code']; |
|
| 1078 | - $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__( |
|
| 1079 | - 'Invoice Number', |
|
| 1080 | - 'event_espresso' |
|
| 1081 | - ); |
|
| 1082 | - } |
|
| 1083 | - |
|
| 1084 | - $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction |
|
| 1085 | - ->primary_registration() |
|
| 1086 | - ->session_ID(); |
|
| 1087 | - $this->_template_args['txn_details']['registration_session']['label'] = esc_html__( |
|
| 1088 | - 'Registration Session', |
|
| 1089 | - 'event_espresso' |
|
| 1090 | - ); |
|
| 1091 | - |
|
| 1092 | - $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address']) |
|
| 1093 | - ? $this->_session['ip_address'] |
|
| 1094 | - : ''; |
|
| 1095 | - $this->_template_args['txn_details']['ip_address']['label'] = esc_html__( |
|
| 1096 | - 'Transaction placed from IP', |
|
| 1097 | - 'event_espresso' |
|
| 1098 | - ); |
|
| 1099 | - |
|
| 1100 | - $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent']) |
|
| 1101 | - ? $this->_session['user_agent'] |
|
| 1102 | - : ''; |
|
| 1103 | - $this->_template_args['txn_details']['user_agent']['label'] = esc_html__( |
|
| 1104 | - 'Registrant User Agent', |
|
| 1105 | - 'event_espresso' |
|
| 1106 | - ); |
|
| 1107 | - |
|
| 1108 | - $reg_steps = '<ul>'; |
|
| 1109 | - foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) { |
|
| 1110 | - if ($reg_step_status === true) { |
|
| 1111 | - $reg_steps .= '<li style="color:#70cc50">' |
|
| 1112 | - . sprintf( |
|
| 1113 | - esc_html__('%1$s : Completed', 'event_espresso'), |
|
| 1114 | - ucwords(str_replace('_', ' ', $reg_step)) |
|
| 1115 | - ) |
|
| 1116 | - . '</li>'; |
|
| 1117 | - } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) { |
|
| 1118 | - $reg_steps .= '<li style="color:#2EA2CC">' |
|
| 1119 | - . sprintf( |
|
| 1120 | - esc_html__('%1$s : Initiated %2$s', 'event_espresso'), |
|
| 1121 | - ucwords(str_replace('_', ' ', $reg_step)), |
|
| 1122 | - date( |
|
| 1123 | - get_option('date_format') . ' ' . get_option('time_format'), |
|
| 1124 | - $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS) |
|
| 1125 | - ) |
|
| 1126 | - ) |
|
| 1127 | - . '</li>'; |
|
| 1128 | - } else { |
|
| 1129 | - $reg_steps .= '<li style="color:#E76700">' |
|
| 1130 | - . sprintf( |
|
| 1131 | - esc_html__('%1$s : Never Initiated', 'event_espresso'), |
|
| 1132 | - ucwords(str_replace('_', ' ', $reg_step)) |
|
| 1133 | - ) |
|
| 1134 | - . '</li>'; |
|
| 1135 | - } |
|
| 1136 | - } |
|
| 1137 | - $reg_steps .= '</ul>'; |
|
| 1138 | - $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps; |
|
| 1139 | - $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__( |
|
| 1140 | - 'Registration Step Progress', |
|
| 1141 | - 'event_espresso' |
|
| 1142 | - ); |
|
| 1143 | - |
|
| 1144 | - |
|
| 1145 | - $this->_get_registrations_to_apply_payment_to(); |
|
| 1146 | - $this->_get_payment_methods($payments); |
|
| 1147 | - $this->_get_payment_status_array(); |
|
| 1148 | - $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction. |
|
| 1149 | - |
|
| 1150 | - $this->_template_args['transaction_form_url'] = add_query_arg( |
|
| 1151 | - array( |
|
| 1152 | - 'action' => 'edit_transaction', |
|
| 1153 | - 'process' => 'transaction', |
|
| 1154 | - ), |
|
| 1155 | - TXN_ADMIN_URL |
|
| 1156 | - ); |
|
| 1157 | - $this->_template_args['apply_payment_form_url'] = add_query_arg( |
|
| 1158 | - array( |
|
| 1159 | - 'page' => 'espresso_transactions', |
|
| 1160 | - 'action' => 'espresso_apply_payment', |
|
| 1161 | - ), |
|
| 1162 | - WP_AJAX_URL |
|
| 1163 | - ); |
|
| 1164 | - $this->_template_args['delete_payment_form_url'] = add_query_arg( |
|
| 1165 | - array( |
|
| 1166 | - 'page' => 'espresso_transactions', |
|
| 1167 | - 'action' => 'espresso_delete_payment', |
|
| 1168 | - ), |
|
| 1169 | - WP_AJAX_URL |
|
| 1170 | - ); |
|
| 1171 | - |
|
| 1172 | - $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction); |
|
| 1173 | - |
|
| 1174 | - // 'espresso_delete_payment_nonce' |
|
| 1175 | - |
|
| 1176 | - $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php'; |
|
| 1177 | - echo EEH_Template::display_template($template_path, $this->_template_args, true); |
|
| 1178 | - } |
|
| 1179 | - |
|
| 1180 | - |
|
| 1181 | - /** |
|
| 1182 | - * _get_registration_payment_IDs |
|
| 1183 | - * generates an array of Payment IDs and their corresponding Registration IDs |
|
| 1184 | - * |
|
| 1185 | - * @access protected |
|
| 1186 | - * @param EE_Payment[] $payments |
|
| 1187 | - * @return array |
|
| 1188 | - * @throws EE_Error |
|
| 1189 | - * @throws InvalidArgumentException |
|
| 1190 | - * @throws InvalidDataTypeException |
|
| 1191 | - * @throws InvalidInterfaceException |
|
| 1192 | - * @throws ReflectionException |
|
| 1193 | - */ |
|
| 1194 | - protected function _get_registration_payment_IDs($payments = array()) |
|
| 1195 | - { |
|
| 1196 | - $existing_reg_payments = array(); |
|
| 1197 | - // get all reg payments for these payments |
|
| 1198 | - $reg_payments = EEM_Registration_Payment::instance()->get_all( |
|
| 1199 | - array( |
|
| 1200 | - array( |
|
| 1201 | - 'PAY_ID' => array( |
|
| 1202 | - 'IN', |
|
| 1203 | - array_keys($payments), |
|
| 1204 | - ), |
|
| 1205 | - ), |
|
| 1206 | - ) |
|
| 1207 | - ); |
|
| 1208 | - if (! empty($reg_payments)) { |
|
| 1209 | - foreach ($payments as $payment) { |
|
| 1210 | - if (! $payment instanceof EE_Payment) { |
|
| 1211 | - continue; |
|
| 1212 | - } elseif (! isset($existing_reg_payments[ $payment->ID() ])) { |
|
| 1213 | - $existing_reg_payments[ $payment->ID() ] = array(); |
|
| 1214 | - } |
|
| 1215 | - foreach ($reg_payments as $reg_payment) { |
|
| 1216 | - if ($reg_payment instanceof EE_Registration_Payment |
|
| 1217 | - && $reg_payment->payment_ID() === $payment->ID() |
|
| 1218 | - ) { |
|
| 1219 | - $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID(); |
|
| 1220 | - } |
|
| 1221 | - } |
|
| 1222 | - } |
|
| 1223 | - } |
|
| 1224 | - |
|
| 1225 | - return $existing_reg_payments; |
|
| 1226 | - } |
|
| 1227 | - |
|
| 1228 | - |
|
| 1229 | - /** |
|
| 1230 | - * _get_registrations_to_apply_payment_to |
|
| 1231 | - * generates HTML for displaying a series of checkboxes in the admin payment modal window |
|
| 1232 | - * which allows the admin to only apply the payment to the specific registrations |
|
| 1233 | - * |
|
| 1234 | - * @access protected |
|
| 1235 | - * @return void |
|
| 1236 | - * @throws EE_Error |
|
| 1237 | - * @throws InvalidArgumentException |
|
| 1238 | - * @throws InvalidDataTypeException |
|
| 1239 | - * @throws InvalidInterfaceException |
|
| 1240 | - * @throws ReflectionException |
|
| 1241 | - */ |
|
| 1242 | - protected function _get_registrations_to_apply_payment_to() |
|
| 1243 | - { |
|
| 1244 | - // we want any registration with an active status (ie: not deleted or cancelled) |
|
| 1245 | - $query_params = array( |
|
| 1246 | - array( |
|
| 1247 | - 'STS_ID' => array( |
|
| 1248 | - 'IN', |
|
| 1249 | - array( |
|
| 1250 | - EEM_Registration::status_id_approved, |
|
| 1251 | - EEM_Registration::status_id_pending_payment, |
|
| 1252 | - EEM_Registration::status_id_not_approved, |
|
| 1253 | - ), |
|
| 1254 | - ), |
|
| 1255 | - ), |
|
| 1256 | - ); |
|
| 1257 | - $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div( |
|
| 1258 | - '', |
|
| 1259 | - 'txn-admin-apply-payment-to-registrations-dv', |
|
| 1260 | - '', |
|
| 1261 | - 'clear: both; margin: 1.5em 0 0; display: none;' |
|
| 1262 | - ); |
|
| 1263 | - $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap'); |
|
| 1264 | - $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl'); |
|
| 1265 | - $registrations_to_apply_payment_to .= EEH_HTML::thead( |
|
| 1266 | - EEH_HTML::tr( |
|
| 1267 | - EEH_HTML::th(esc_html__('ID', 'event_espresso')) . |
|
| 1268 | - EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) . |
|
| 1269 | - EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) . |
|
| 1270 | - EEH_HTML::th(esc_html__('Event', 'event_espresso')) . |
|
| 1271 | - EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') . |
|
| 1272 | - EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') . |
|
| 1273 | - EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr') |
|
| 1274 | - ) |
|
| 1275 | - ); |
|
| 1276 | - $registrations_to_apply_payment_to .= EEH_HTML::tbody(); |
|
| 1277 | - // get registrations for TXN |
|
| 1278 | - $registrations = $this->_transaction->registrations($query_params); |
|
| 1279 | - $existing_reg_payments = $this->_template_args['existing_reg_payments']; |
|
| 1280 | - foreach ($registrations as $registration) { |
|
| 1281 | - if ($registration instanceof EE_Registration) { |
|
| 1282 | - $attendee_name = $registration->attendee() instanceof EE_Attendee |
|
| 1283 | - ? $registration->attendee()->full_name() |
|
| 1284 | - : esc_html__('Unknown Attendee', 'event_espresso'); |
|
| 1285 | - $owing = $registration->final_price() - $registration->paid(); |
|
| 1286 | - $taxable = $registration->ticket()->taxable() |
|
| 1287 | - ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>' |
|
| 1288 | - : ''; |
|
| 1289 | - $checked = empty($existing_reg_payments) |
|
| 1290 | - || in_array($registration->ID(), $existing_reg_payments, true) |
|
| 1291 | - ? ' checked="checked"' |
|
| 1292 | - : ''; |
|
| 1293 | - $disabled = $registration->final_price() > 0 ? '' : ' disabled'; |
|
| 1294 | - $registrations_to_apply_payment_to .= EEH_HTML::tr( |
|
| 1295 | - EEH_HTML::td($registration->ID()) . |
|
| 1296 | - EEH_HTML::td($attendee_name) . |
|
| 1297 | - EEH_HTML::td( |
|
| 1298 | - $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable |
|
| 1299 | - ) . |
|
| 1300 | - EEH_HTML::td($registration->event_name()) . |
|
| 1301 | - EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') . |
|
| 1302 | - EEH_HTML::td( |
|
| 1303 | - EEH_Template::format_currency($owing), |
|
| 1304 | - '', |
|
| 1305 | - 'txn-admin-payment-owing-td jst-cntr' |
|
| 1306 | - ) . |
|
| 1307 | - EEH_HTML::td( |
|
| 1308 | - '<input type="checkbox" value="' . $registration->ID() |
|
| 1309 | - . '" name="txn_admin_payment[registrations]"' |
|
| 1310 | - . $checked . $disabled . '>', |
|
| 1311 | - '', |
|
| 1312 | - 'jst-cntr' |
|
| 1313 | - ), |
|
| 1314 | - 'apply-payment-registration-row-' . $registration->ID() |
|
| 1315 | - ); |
|
| 1316 | - } |
|
| 1317 | - } |
|
| 1318 | - $registrations_to_apply_payment_to .= EEH_HTML::tbodyx(); |
|
| 1319 | - $registrations_to_apply_payment_to .= EEH_HTML::tablex(); |
|
| 1320 | - $registrations_to_apply_payment_to .= EEH_HTML::divx(); |
|
| 1321 | - $registrations_to_apply_payment_to .= EEH_HTML::p( |
|
| 1322 | - esc_html__( |
|
| 1323 | - 'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.', |
|
| 1324 | - 'event_espresso' |
|
| 1325 | - ), |
|
| 1326 | - '', |
|
| 1327 | - 'clear description' |
|
| 1328 | - ); |
|
| 1329 | - $registrations_to_apply_payment_to .= EEH_HTML::divx(); |
|
| 1330 | - $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to; |
|
| 1331 | - } |
|
| 1332 | - |
|
| 1333 | - |
|
| 1334 | - /** |
|
| 1335 | - * _get_reg_status_selection |
|
| 1336 | - * |
|
| 1337 | - * @todo this will need to be adjusted either once MER comes along OR we move default reg status to tickets |
|
| 1338 | - * instead of events. |
|
| 1339 | - * @access protected |
|
| 1340 | - * @return void |
|
| 1341 | - * @throws EE_Error |
|
| 1342 | - */ |
|
| 1343 | - protected function _get_reg_status_selection() |
|
| 1344 | - { |
|
| 1345 | - // first get all possible statuses |
|
| 1346 | - $statuses = EEM_Registration::reg_status_array(array(), true); |
|
| 1347 | - // let's add a "don't change" option. |
|
| 1348 | - $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso'); |
|
| 1349 | - $status_array = array_merge($status_array, $statuses); |
|
| 1350 | - $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input( |
|
| 1351 | - 'txn_reg_status_change[reg_status]', |
|
| 1352 | - $status_array, |
|
| 1353 | - 'NAN', |
|
| 1354 | - 'id="txn-admin-payment-reg-status-inp"', |
|
| 1355 | - 'txn-reg-status-change-reg-status' |
|
| 1356 | - ); |
|
| 1357 | - $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input( |
|
| 1358 | - 'delete_txn_reg_status_change[reg_status]', |
|
| 1359 | - $status_array, |
|
| 1360 | - 'NAN', |
|
| 1361 | - 'delete-txn-admin-payment-reg-status-inp', |
|
| 1362 | - 'delete-txn-reg-status-change-reg-status' |
|
| 1363 | - ); |
|
| 1364 | - } |
|
| 1365 | - |
|
| 1366 | - |
|
| 1367 | - /** |
|
| 1368 | - * _get_payment_methods |
|
| 1369 | - * Gets all the payment methods available generally, or the ones that are already |
|
| 1370 | - * selected on these payments (in case their payment methods are no longer active). |
|
| 1371 | - * Has the side-effect of updating the template args' payment_methods item |
|
| 1372 | - * |
|
| 1373 | - * @access private |
|
| 1374 | - * @param EE_Payment[] to show on this page |
|
| 1375 | - * @return void |
|
| 1376 | - * @throws EE_Error |
|
| 1377 | - * @throws InvalidArgumentException |
|
| 1378 | - * @throws InvalidDataTypeException |
|
| 1379 | - * @throws InvalidInterfaceException |
|
| 1380 | - * @throws ReflectionException |
|
| 1381 | - */ |
|
| 1382 | - private function _get_payment_methods($payments = array()) |
|
| 1383 | - { |
|
| 1384 | - $payment_methods_of_payments = array(); |
|
| 1385 | - foreach ($payments as $payment) { |
|
| 1386 | - if ($payment instanceof EE_Payment) { |
|
| 1387 | - $payment_methods_of_payments[] = $payment->ID(); |
|
| 1388 | - } |
|
| 1389 | - } |
|
| 1390 | - if ($payment_methods_of_payments) { |
|
| 1391 | - $query_args = array( |
|
| 1392 | - array( |
|
| 1393 | - 'OR*payment_method_for_payment' => array( |
|
| 1394 | - 'PMD_ID' => array('IN', $payment_methods_of_payments), |
|
| 1395 | - 'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'), |
|
| 1396 | - ), |
|
| 1397 | - ), |
|
| 1398 | - ); |
|
| 1399 | - } else { |
|
| 1400 | - $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'))); |
|
| 1401 | - } |
|
| 1402 | - $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args); |
|
| 1403 | - } |
|
| 1404 | - |
|
| 1405 | - |
|
| 1406 | - /** |
|
| 1407 | - * txn_attendees_meta_box |
|
| 1408 | - * generates HTML for the Attendees Transaction main meta box |
|
| 1409 | - * |
|
| 1410 | - * @access public |
|
| 1411 | - * @param WP_Post $post |
|
| 1412 | - * @param array $metabox |
|
| 1413 | - * @return void |
|
| 1414 | - * @throws DomainException |
|
| 1415 | - * @throws EE_Error |
|
| 1416 | - * @throws InvalidArgumentException |
|
| 1417 | - * @throws InvalidDataTypeException |
|
| 1418 | - * @throws InvalidInterfaceException |
|
| 1419 | - * @throws ReflectionException |
|
| 1420 | - */ |
|
| 1421 | - public function txn_attendees_meta_box($post, $metabox = array('args' => array())) |
|
| 1422 | - { |
|
| 1423 | - |
|
| 1424 | - /** @noinspection NonSecureExtractUsageInspection */ |
|
| 1425 | - extract($metabox['args']); |
|
| 1426 | - $this->_template_args['post'] = $post; |
|
| 1427 | - $this->_template_args['event_attendees'] = array(); |
|
| 1428 | - // process items in cart |
|
| 1429 | - $line_items = $this->_transaction->get_many_related( |
|
| 1430 | - 'Line_Item', |
|
| 1431 | - array(array('LIN_type' => 'line-item')) |
|
| 1432 | - ); |
|
| 1433 | - if (! empty($line_items)) { |
|
| 1434 | - foreach ($line_items as $item) { |
|
| 1435 | - if ($item instanceof EE_Line_Item) { |
|
| 1436 | - switch ($item->OBJ_type()) { |
|
| 1437 | - case 'Event': |
|
| 1438 | - break; |
|
| 1439 | - case 'Ticket': |
|
| 1440 | - $ticket = $item->ticket(); |
|
| 1441 | - // right now we're only handling tickets here. |
|
| 1442 | - // Cause its expected that only tickets will have attendees right? |
|
| 1443 | - if (! $ticket instanceof EE_Ticket) { |
|
| 1444 | - break; |
|
| 1445 | - } |
|
| 1446 | - try { |
|
| 1447 | - $event_name = $ticket->get_event_name(); |
|
| 1448 | - } catch (Exception $e) { |
|
| 1449 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
| 1450 | - $event_name = esc_html__('Unknown Event', 'event_espresso'); |
|
| 1451 | - } |
|
| 1452 | - $event_name .= ' - ' . $item->name(); |
|
| 1453 | - $ticket_price = EEH_Template::format_currency($item->unit_price()); |
|
| 1454 | - // now get all of the registrations for this transaction that use this ticket |
|
| 1455 | - $registrations = $ticket->registrations( |
|
| 1456 | - array(array('TXN_ID' => $this->_transaction->ID())) |
|
| 1457 | - ); |
|
| 1458 | - foreach ($registrations as $registration) { |
|
| 1459 | - if (! $registration instanceof EE_Registration) { |
|
| 1460 | - break; |
|
| 1461 | - } |
|
| 1462 | - $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID'] |
|
| 1463 | - = $registration->status_ID(); |
|
| 1464 | - $this->_template_args['event_attendees'][ $registration->ID() ]['att_num'] |
|
| 1465 | - = $registration->count(); |
|
| 1466 | - $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name'] |
|
| 1467 | - = $event_name; |
|
| 1468 | - $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price'] |
|
| 1469 | - = $ticket_price; |
|
| 1470 | - // attendee info |
|
| 1471 | - $attendee = $registration->get_first_related('Attendee'); |
|
| 1472 | - if ($attendee instanceof EE_Attendee) { |
|
| 1473 | - $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] |
|
| 1474 | - = $attendee->ID(); |
|
| 1475 | - $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] |
|
| 1476 | - = $attendee->full_name(); |
|
| 1477 | - $this->_template_args['event_attendees'][ $registration->ID() ]['email'] |
|
| 1478 | - = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name |
|
| 1479 | - . esc_html__( |
|
| 1480 | - ' Event', |
|
| 1481 | - 'event_espresso' |
|
| 1482 | - ) |
|
| 1483 | - . '">' . $attendee->email() . '</a>'; |
|
| 1484 | - $this->_template_args['event_attendees'][ $registration->ID() ]['address'] |
|
| 1485 | - = EEH_Address::format($attendee, 'inline', false, false); |
|
| 1486 | - } else { |
|
| 1487 | - $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = ''; |
|
| 1488 | - $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = ''; |
|
| 1489 | - $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = ''; |
|
| 1490 | - $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = ''; |
|
| 1491 | - } |
|
| 1492 | - } |
|
| 1493 | - break; |
|
| 1494 | - } |
|
| 1495 | - } |
|
| 1496 | - } |
|
| 1497 | - |
|
| 1498 | - $this->_template_args['transaction_form_url'] = add_query_arg( |
|
| 1499 | - array( |
|
| 1500 | - 'action' => 'edit_transaction', |
|
| 1501 | - 'process' => 'attendees', |
|
| 1502 | - ), |
|
| 1503 | - TXN_ADMIN_URL |
|
| 1504 | - ); |
|
| 1505 | - echo EEH_Template::display_template( |
|
| 1506 | - TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php', |
|
| 1507 | - $this->_template_args, |
|
| 1508 | - true |
|
| 1509 | - ); |
|
| 1510 | - } else { |
|
| 1511 | - echo sprintf( |
|
| 1512 | - esc_html__( |
|
| 1513 | - '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s', |
|
| 1514 | - 'event_espresso' |
|
| 1515 | - ), |
|
| 1516 | - '<p class="important-notice">', |
|
| 1517 | - '</p>' |
|
| 1518 | - ); |
|
| 1519 | - } |
|
| 1520 | - } |
|
| 1521 | - |
|
| 1522 | - |
|
| 1523 | - /** |
|
| 1524 | - * txn_registrant_side_meta_box |
|
| 1525 | - * generates HTML for the Edit Transaction side meta box |
|
| 1526 | - * |
|
| 1527 | - * @access public |
|
| 1528 | - * @return void |
|
| 1529 | - * @throws DomainException |
|
| 1530 | - * @throws EE_Error |
|
| 1531 | - * @throws InvalidArgumentException |
|
| 1532 | - * @throws InvalidDataTypeException |
|
| 1533 | - * @throws InvalidInterfaceException |
|
| 1534 | - * @throws ReflectionException |
|
| 1535 | - */ |
|
| 1536 | - public function txn_registrant_side_meta_box() |
|
| 1537 | - { |
|
| 1538 | - $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration |
|
| 1539 | - ? $this->_transaction->primary_registration()->get_first_related('Attendee') |
|
| 1540 | - : null; |
|
| 1541 | - if (! $primary_att instanceof EE_Attendee) { |
|
| 1542 | - $this->_template_args['no_attendee_message'] = esc_html__( |
|
| 1543 | - 'There is no attached contact for this transaction. The transaction either failed due to an error or was abandoned.', |
|
| 1544 | - 'event_espresso' |
|
| 1545 | - ); |
|
| 1546 | - $primary_att = EEM_Attendee::instance()->create_default_object(); |
|
| 1547 | - } |
|
| 1548 | - $this->_template_args['ATT_ID'] = $primary_att->ID(); |
|
| 1549 | - $this->_template_args['prime_reg_fname'] = $primary_att->fname(); |
|
| 1550 | - $this->_template_args['prime_reg_lname'] = $primary_att->lname(); |
|
| 1551 | - $this->_template_args['prime_reg_email'] = $primary_att->email(); |
|
| 1552 | - $this->_template_args['prime_reg_phone'] = $primary_att->phone(); |
|
| 1553 | - $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
| 1554 | - array( |
|
| 1555 | - 'action' => 'edit_attendee', |
|
| 1556 | - 'post' => $primary_att->ID(), |
|
| 1557 | - ), |
|
| 1558 | - REG_ADMIN_URL |
|
| 1559 | - ); |
|
| 1560 | - // get formatted address for registrant |
|
| 1561 | - $this->_template_args['formatted_address'] = EEH_Address::format($primary_att); |
|
| 1562 | - echo EEH_Template::display_template( |
|
| 1563 | - TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php', |
|
| 1564 | - $this->_template_args, |
|
| 1565 | - true |
|
| 1566 | - ); |
|
| 1567 | - } |
|
| 1568 | - |
|
| 1569 | - |
|
| 1570 | - /** |
|
| 1571 | - * txn_billing_info_side_meta_box |
|
| 1572 | - * generates HTML for the Edit Transaction side meta box |
|
| 1573 | - * |
|
| 1574 | - * @access public |
|
| 1575 | - * @return void |
|
| 1576 | - * @throws DomainException |
|
| 1577 | - * @throws EE_Error |
|
| 1578 | - */ |
|
| 1579 | - public function txn_billing_info_side_meta_box() |
|
| 1580 | - { |
|
| 1581 | - |
|
| 1582 | - $this->_template_args['billing_form'] = $this->_transaction->billing_info(); |
|
| 1583 | - $this->_template_args['billing_form_url'] = add_query_arg( |
|
| 1584 | - array('action' => 'edit_transaction', 'process' => 'billing'), |
|
| 1585 | - TXN_ADMIN_URL |
|
| 1586 | - ); |
|
| 1587 | - |
|
| 1588 | - $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php'; |
|
| 1589 | - echo EEH_Template::display_template($template_path, $this->_template_args, true); |
|
| 1590 | - } |
|
| 1591 | - |
|
| 1592 | - |
|
| 1593 | - /** |
|
| 1594 | - * apply_payments_or_refunds |
|
| 1595 | - * registers a payment or refund made towards a transaction |
|
| 1596 | - * |
|
| 1597 | - * @access public |
|
| 1598 | - * @return void |
|
| 1599 | - * @throws EE_Error |
|
| 1600 | - * @throws InvalidArgumentException |
|
| 1601 | - * @throws ReflectionException |
|
| 1602 | - * @throws RuntimeException |
|
| 1603 | - * @throws InvalidDataTypeException |
|
| 1604 | - * @throws InvalidInterfaceException |
|
| 1605 | - */ |
|
| 1606 | - public function apply_payments_or_refunds() |
|
| 1607 | - { |
|
| 1608 | - $json_response_data = array('return_data' => false); |
|
| 1609 | - $valid_data = $this->_validate_payment_request_data(); |
|
| 1610 | - $has_access = EE_Registry::instance()->CAP->current_user_can( |
|
| 1611 | - 'ee_edit_payments', |
|
| 1612 | - 'apply_payment_or_refund_from_registration_details' |
|
| 1613 | - ); |
|
| 1614 | - if (! empty($valid_data) && $has_access) { |
|
| 1615 | - $PAY_ID = $valid_data['PAY_ID']; |
|
| 1616 | - // save the new payment |
|
| 1617 | - $payment = $this->_create_payment_from_request_data($valid_data); |
|
| 1618 | - // get the TXN for this payment |
|
| 1619 | - $transaction = $payment->transaction(); |
|
| 1620 | - // verify transaction |
|
| 1621 | - if ($transaction instanceof EE_Transaction) { |
|
| 1622 | - // calculate_total_payments_and_update_status |
|
| 1623 | - $this->_process_transaction_payments($transaction); |
|
| 1624 | - $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment); |
|
| 1625 | - $this->_remove_existing_registration_payments($payment, $PAY_ID); |
|
| 1626 | - // apply payment to registrations (if applicable) |
|
| 1627 | - if (! empty($REG_IDs)) { |
|
| 1628 | - $this->_update_registration_payments($transaction, $payment, $REG_IDs); |
|
| 1629 | - $this->_maybe_send_notifications(); |
|
| 1630 | - // now process status changes for the same registrations |
|
| 1631 | - $this->_process_registration_status_change($transaction, $REG_IDs); |
|
| 1632 | - } |
|
| 1633 | - $this->_maybe_send_notifications($payment); |
|
| 1634 | - // prepare to render page |
|
| 1635 | - $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs); |
|
| 1636 | - do_action( |
|
| 1637 | - 'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', |
|
| 1638 | - $transaction, |
|
| 1639 | - $payment |
|
| 1640 | - ); |
|
| 1641 | - } else { |
|
| 1642 | - EE_Error::add_error( |
|
| 1643 | - esc_html__( |
|
| 1644 | - 'A valid Transaction for this payment could not be retrieved.', |
|
| 1645 | - 'event_espresso' |
|
| 1646 | - ), |
|
| 1647 | - __FILE__, |
|
| 1648 | - __FUNCTION__, |
|
| 1649 | - __LINE__ |
|
| 1650 | - ); |
|
| 1651 | - } |
|
| 1652 | - } elseif ($has_access) { |
|
| 1653 | - EE_Error::add_error( |
|
| 1654 | - esc_html__( |
|
| 1655 | - 'The payment form data could not be processed. Please try again.', |
|
| 1656 | - 'event_espresso' |
|
| 1657 | - ), |
|
| 1658 | - __FILE__, |
|
| 1659 | - __FUNCTION__, |
|
| 1660 | - __LINE__ |
|
| 1661 | - ); |
|
| 1662 | - } else { |
|
| 1663 | - EE_Error::add_error( |
|
| 1664 | - esc_html__( |
|
| 1665 | - 'You do not have access to apply payments or refunds to a registration.', |
|
| 1666 | - 'event_espresso' |
|
| 1667 | - ), |
|
| 1668 | - __FILE__, |
|
| 1669 | - __FUNCTION__, |
|
| 1670 | - __LINE__ |
|
| 1671 | - ); |
|
| 1672 | - } |
|
| 1673 | - $notices = EE_Error::get_notices( |
|
| 1674 | - false, |
|
| 1675 | - false, |
|
| 1676 | - false |
|
| 1677 | - ); |
|
| 1678 | - $this->_template_args = array( |
|
| 1679 | - 'data' => $json_response_data, |
|
| 1680 | - 'error' => $notices['errors'], |
|
| 1681 | - 'success' => $notices['success'], |
|
| 1682 | - ); |
|
| 1683 | - $this->_return_json(); |
|
| 1684 | - } |
|
| 1685 | - |
|
| 1686 | - |
|
| 1687 | - /** |
|
| 1688 | - * _validate_payment_request_data |
|
| 1689 | - * |
|
| 1690 | - * @return array |
|
| 1691 | - * @throws EE_Error |
|
| 1692 | - * @throws InvalidArgumentException |
|
| 1693 | - * @throws InvalidDataTypeException |
|
| 1694 | - * @throws InvalidInterfaceException |
|
| 1695 | - */ |
|
| 1696 | - protected function _validate_payment_request_data() |
|
| 1697 | - { |
|
| 1698 | - if (! isset($this->_req_data['txn_admin_payment'])) { |
|
| 1699 | - return array(); |
|
| 1700 | - } |
|
| 1701 | - $payment_form = $this->_generate_payment_form_section(); |
|
| 1702 | - try { |
|
| 1703 | - if ($payment_form->was_submitted()) { |
|
| 1704 | - $payment_form->receive_form_submission(); |
|
| 1705 | - if (! $payment_form->is_valid()) { |
|
| 1706 | - $submission_error_messages = array(); |
|
| 1707 | - foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) { |
|
| 1708 | - if ($validation_error instanceof EE_Validation_Error) { |
|
| 1709 | - $submission_error_messages[] = sprintf( |
|
| 1710 | - _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'), |
|
| 1711 | - $validation_error->get_form_section()->html_label_text(), |
|
| 1712 | - $validation_error->getMessage() |
|
| 1713 | - ); |
|
| 1714 | - } |
|
| 1715 | - } |
|
| 1716 | - EE_Error::add_error( |
|
| 1717 | - implode('<br />', $submission_error_messages), |
|
| 1718 | - __FILE__, |
|
| 1719 | - __FUNCTION__, |
|
| 1720 | - __LINE__ |
|
| 1721 | - ); |
|
| 1722 | - return array(); |
|
| 1723 | - } |
|
| 1724 | - } |
|
| 1725 | - } catch (EE_Error $e) { |
|
| 1726 | - EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
| 1727 | - return array(); |
|
| 1728 | - } |
|
| 1729 | - |
|
| 1730 | - return $payment_form->valid_data(); |
|
| 1731 | - } |
|
| 1732 | - |
|
| 1733 | - |
|
| 1734 | - /** |
|
| 1735 | - * _generate_payment_form_section |
|
| 1736 | - * |
|
| 1737 | - * @return EE_Form_Section_Proper |
|
| 1738 | - * @throws EE_Error |
|
| 1739 | - */ |
|
| 1740 | - protected function _generate_payment_form_section() |
|
| 1741 | - { |
|
| 1742 | - return new EE_Form_Section_Proper( |
|
| 1743 | - array( |
|
| 1744 | - 'name' => 'txn_admin_payment', |
|
| 1745 | - 'subsections' => array( |
|
| 1746 | - 'PAY_ID' => new EE_Text_Input( |
|
| 1747 | - array( |
|
| 1748 | - 'default' => 0, |
|
| 1749 | - 'required' => false, |
|
| 1750 | - 'html_label_text' => esc_html__('Payment ID', 'event_espresso'), |
|
| 1751 | - 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1752 | - ) |
|
| 1753 | - ), |
|
| 1754 | - 'TXN_ID' => new EE_Text_Input( |
|
| 1755 | - array( |
|
| 1756 | - 'default' => 0, |
|
| 1757 | - 'required' => true, |
|
| 1758 | - 'html_label_text' => esc_html__('Transaction ID', 'event_espresso'), |
|
| 1759 | - 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1760 | - ) |
|
| 1761 | - ), |
|
| 1762 | - 'type' => new EE_Text_Input( |
|
| 1763 | - array( |
|
| 1764 | - 'default' => 1, |
|
| 1765 | - 'required' => true, |
|
| 1766 | - 'html_label_text' => esc_html__('Payment or Refund', 'event_espresso'), |
|
| 1767 | - 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1768 | - ) |
|
| 1769 | - ), |
|
| 1770 | - 'amount' => new EE_Text_Input( |
|
| 1771 | - array( |
|
| 1772 | - 'default' => 0, |
|
| 1773 | - 'required' => true, |
|
| 1774 | - 'html_label_text' => esc_html__('Payment amount', 'event_espresso'), |
|
| 1775 | - 'validation_strategies' => array(new EE_Float_Normalization()), |
|
| 1776 | - ) |
|
| 1777 | - ), |
|
| 1778 | - 'status' => new EE_Text_Input( |
|
| 1779 | - array( |
|
| 1780 | - 'default' => EEM_Payment::status_id_approved, |
|
| 1781 | - 'required' => true, |
|
| 1782 | - 'html_label_text' => esc_html__('Payment status', 'event_espresso'), |
|
| 1783 | - ) |
|
| 1784 | - ), |
|
| 1785 | - 'PMD_ID' => new EE_Text_Input( |
|
| 1786 | - array( |
|
| 1787 | - 'default' => 2, |
|
| 1788 | - 'required' => true, |
|
| 1789 | - 'html_label_text' => esc_html__('Payment Method', 'event_espresso'), |
|
| 1790 | - 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1791 | - ) |
|
| 1792 | - ), |
|
| 1793 | - 'date' => new EE_Text_Input( |
|
| 1794 | - array( |
|
| 1795 | - 'default' => time(), |
|
| 1796 | - 'required' => true, |
|
| 1797 | - 'html_label_text' => esc_html__('Payment date', 'event_espresso'), |
|
| 1798 | - ) |
|
| 1799 | - ), |
|
| 1800 | - 'txn_id_chq_nmbr' => new EE_Text_Input( |
|
| 1801 | - array( |
|
| 1802 | - 'default' => '', |
|
| 1803 | - 'required' => false, |
|
| 1804 | - 'html_label_text' => esc_html__('Transaction or Cheque Number', 'event_espresso'), |
|
| 1805 | - 'validation_strategies' => array( |
|
| 1806 | - new EE_Max_Length_Validation_Strategy( |
|
| 1807 | - esc_html__('Input too long', 'event_espresso'), |
|
| 1808 | - 100 |
|
| 1809 | - ), |
|
| 1810 | - ), |
|
| 1811 | - ) |
|
| 1812 | - ), |
|
| 1813 | - 'po_number' => new EE_Text_Input( |
|
| 1814 | - array( |
|
| 1815 | - 'default' => '', |
|
| 1816 | - 'required' => false, |
|
| 1817 | - 'html_label_text' => esc_html__('Purchase Order Number', 'event_espresso'), |
|
| 1818 | - 'validation_strategies' => array( |
|
| 1819 | - new EE_Max_Length_Validation_Strategy( |
|
| 1820 | - esc_html__('Input too long', 'event_espresso'), |
|
| 1821 | - 100 |
|
| 1822 | - ), |
|
| 1823 | - ), |
|
| 1824 | - ) |
|
| 1825 | - ), |
|
| 1826 | - 'accounting' => new EE_Text_Input( |
|
| 1827 | - array( |
|
| 1828 | - 'default' => '', |
|
| 1829 | - 'required' => false, |
|
| 1830 | - 'html_label_text' => esc_html__('Extra Field for Accounting', 'event_espresso'), |
|
| 1831 | - 'validation_strategies' => array( |
|
| 1832 | - new EE_Max_Length_Validation_Strategy( |
|
| 1833 | - esc_html__('Input too long', 'event_espresso'), |
|
| 1834 | - 100 |
|
| 1835 | - ), |
|
| 1836 | - ), |
|
| 1837 | - ) |
|
| 1838 | - ), |
|
| 1839 | - ), |
|
| 1840 | - ) |
|
| 1841 | - ); |
|
| 1842 | - } |
|
| 1843 | - |
|
| 1844 | - |
|
| 1845 | - /** |
|
| 1846 | - * _create_payment_from_request_data |
|
| 1847 | - * |
|
| 1848 | - * @param array $valid_data |
|
| 1849 | - * @return EE_Payment |
|
| 1850 | - * @throws EE_Error |
|
| 1851 | - * @throws InvalidArgumentException |
|
| 1852 | - * @throws InvalidDataTypeException |
|
| 1853 | - * @throws InvalidInterfaceException |
|
| 1854 | - * @throws ReflectionException |
|
| 1855 | - */ |
|
| 1856 | - protected function _create_payment_from_request_data($valid_data) |
|
| 1857 | - { |
|
| 1858 | - $PAY_ID = $valid_data['PAY_ID']; |
|
| 1859 | - // get payment amount |
|
| 1860 | - $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0; |
|
| 1861 | - // payments have a type value of 1 and refunds have a type value of -1 |
|
| 1862 | - // so multiplying amount by type will give a positive value for payments, and negative values for refunds |
|
| 1863 | - $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount; |
|
| 1864 | - // for some reason the date string coming in has extra spaces between the date and time. This fixes that. |
|
| 1865 | - $date = $valid_data['date'] |
|
| 1866 | - ? preg_replace('/\s+/', ' ', $valid_data['date']) |
|
| 1867 | - : date('Y-m-d g:i a', current_time('timestamp')); |
|
| 1868 | - $payment = EE_Payment::new_instance( |
|
| 1869 | - array( |
|
| 1870 | - 'TXN_ID' => $valid_data['TXN_ID'], |
|
| 1871 | - 'STS_ID' => $valid_data['status'], |
|
| 1872 | - 'PAY_timestamp' => $date, |
|
| 1873 | - 'PAY_source' => EEM_Payment_Method::scope_admin, |
|
| 1874 | - 'PMD_ID' => $valid_data['PMD_ID'], |
|
| 1875 | - 'PAY_amount' => $amount, |
|
| 1876 | - 'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'], |
|
| 1877 | - 'PAY_po_number' => $valid_data['po_number'], |
|
| 1878 | - 'PAY_extra_accntng' => $valid_data['accounting'], |
|
| 1879 | - 'PAY_details' => $valid_data, |
|
| 1880 | - 'PAY_ID' => $PAY_ID, |
|
| 1881 | - ), |
|
| 1882 | - '', |
|
| 1883 | - array('Y-m-d', 'g:i a') |
|
| 1884 | - ); |
|
| 1885 | - |
|
| 1886 | - if (! $payment->save()) { |
|
| 1887 | - EE_Error::add_error( |
|
| 1888 | - sprintf( |
|
| 1889 | - esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'), |
|
| 1890 | - $payment->ID() |
|
| 1891 | - ), |
|
| 1892 | - __FILE__, |
|
| 1893 | - __FUNCTION__, |
|
| 1894 | - __LINE__ |
|
| 1895 | - ); |
|
| 1896 | - } |
|
| 1897 | - |
|
| 1898 | - return $payment; |
|
| 1899 | - } |
|
| 1900 | - |
|
| 1901 | - |
|
| 1902 | - /** |
|
| 1903 | - * _process_transaction_payments |
|
| 1904 | - * |
|
| 1905 | - * @param \EE_Transaction $transaction |
|
| 1906 | - * @return void |
|
| 1907 | - * @throws EE_Error |
|
| 1908 | - * @throws InvalidArgumentException |
|
| 1909 | - * @throws ReflectionException |
|
| 1910 | - * @throws InvalidDataTypeException |
|
| 1911 | - * @throws InvalidInterfaceException |
|
| 1912 | - */ |
|
| 1913 | - protected function _process_transaction_payments(EE_Transaction $transaction) |
|
| 1914 | - { |
|
| 1915 | - /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 1916 | - $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 1917 | - // update the transaction with this payment |
|
| 1918 | - if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) { |
|
| 1919 | - EE_Error::add_success( |
|
| 1920 | - esc_html__( |
|
| 1921 | - 'The payment has been processed successfully.', |
|
| 1922 | - 'event_espresso' |
|
| 1923 | - ), |
|
| 1924 | - __FILE__, |
|
| 1925 | - __FUNCTION__, |
|
| 1926 | - __LINE__ |
|
| 1927 | - ); |
|
| 1928 | - } else { |
|
| 1929 | - EE_Error::add_error( |
|
| 1930 | - esc_html__( |
|
| 1931 | - 'The payment was processed successfully but the amount paid for the transaction was not updated.', |
|
| 1932 | - 'event_espresso' |
|
| 1933 | - ), |
|
| 1934 | - __FILE__, |
|
| 1935 | - __FUNCTION__, |
|
| 1936 | - __LINE__ |
|
| 1937 | - ); |
|
| 1938 | - } |
|
| 1939 | - } |
|
| 1940 | - |
|
| 1941 | - |
|
| 1942 | - /** |
|
| 1943 | - * _get_REG_IDs_to_apply_payment_to |
|
| 1944 | - * returns a list of registration IDs that the payment will apply to |
|
| 1945 | - * |
|
| 1946 | - * @param \EE_Payment $payment |
|
| 1947 | - * @return array |
|
| 1948 | - * @throws EE_Error |
|
| 1949 | - * @throws InvalidArgumentException |
|
| 1950 | - * @throws InvalidDataTypeException |
|
| 1951 | - * @throws InvalidInterfaceException |
|
| 1952 | - * @throws ReflectionException |
|
| 1953 | - */ |
|
| 1954 | - protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment) |
|
| 1955 | - { |
|
| 1956 | - $REG_IDs = array(); |
|
| 1957 | - // grab array of IDs for specific registrations to apply changes to |
|
| 1958 | - if (isset($this->_req_data['txn_admin_payment']['registrations'])) { |
|
| 1959 | - $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations']; |
|
| 1960 | - } |
|
| 1961 | - // nothing specified ? then get all reg IDs |
|
| 1962 | - if (empty($REG_IDs)) { |
|
| 1963 | - $registrations = $payment->transaction()->registrations(); |
|
| 1964 | - $REG_IDs = ! empty($registrations) |
|
| 1965 | - ? array_keys($registrations) |
|
| 1966 | - : $this->_get_existing_reg_payment_REG_IDs($payment); |
|
| 1967 | - } |
|
| 1968 | - |
|
| 1969 | - // ensure that REG_IDs are integers and NOT strings |
|
| 1970 | - return array_map('intval', $REG_IDs); |
|
| 1971 | - } |
|
| 1972 | - |
|
| 1973 | - |
|
| 1974 | - /** |
|
| 1975 | - * @return array |
|
| 1976 | - */ |
|
| 1977 | - public function existing_reg_payment_REG_IDs() |
|
| 1978 | - { |
|
| 1979 | - return $this->_existing_reg_payment_REG_IDs; |
|
| 1980 | - } |
|
| 1981 | - |
|
| 1982 | - |
|
| 1983 | - /** |
|
| 1984 | - * @param array $existing_reg_payment_REG_IDs |
|
| 1985 | - */ |
|
| 1986 | - public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null) |
|
| 1987 | - { |
|
| 1988 | - $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs; |
|
| 1989 | - } |
|
| 1990 | - |
|
| 1991 | - |
|
| 1992 | - /** |
|
| 1993 | - * _get_existing_reg_payment_REG_IDs |
|
| 1994 | - * returns a list of registration IDs that the payment is currently related to |
|
| 1995 | - * as recorded in the database |
|
| 1996 | - * |
|
| 1997 | - * @param \EE_Payment $payment |
|
| 1998 | - * @return array |
|
| 1999 | - * @throws EE_Error |
|
| 2000 | - * @throws InvalidArgumentException |
|
| 2001 | - * @throws InvalidDataTypeException |
|
| 2002 | - * @throws InvalidInterfaceException |
|
| 2003 | - * @throws ReflectionException |
|
| 2004 | - */ |
|
| 2005 | - protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment) |
|
| 2006 | - { |
|
| 2007 | - if ($this->existing_reg_payment_REG_IDs() === null) { |
|
| 2008 | - // let's get any existing reg payment records for this payment |
|
| 2009 | - $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration'); |
|
| 2010 | - // but we only want the REG IDs, so grab the array keys |
|
| 2011 | - $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs) |
|
| 2012 | - ? array_keys($existing_reg_payment_REG_IDs) |
|
| 2013 | - : array(); |
|
| 2014 | - $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs); |
|
| 2015 | - } |
|
| 2016 | - |
|
| 2017 | - return $this->existing_reg_payment_REG_IDs(); |
|
| 2018 | - } |
|
| 2019 | - |
|
| 2020 | - |
|
| 2021 | - /** |
|
| 2022 | - * _remove_existing_registration_payments |
|
| 2023 | - * this calculates the difference between existing relations |
|
| 2024 | - * to the supplied payment and the new list registration IDs, |
|
| 2025 | - * removes any related registrations that no longer apply, |
|
| 2026 | - * and then updates the registration paid fields |
|
| 2027 | - * |
|
| 2028 | - * @param \EE_Payment $payment |
|
| 2029 | - * @param int $PAY_ID |
|
| 2030 | - * @return bool; |
|
| 2031 | - * @throws EE_Error |
|
| 2032 | - * @throws InvalidArgumentException |
|
| 2033 | - * @throws ReflectionException |
|
| 2034 | - * @throws InvalidDataTypeException |
|
| 2035 | - * @throws InvalidInterfaceException |
|
| 2036 | - */ |
|
| 2037 | - protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0) |
|
| 2038 | - { |
|
| 2039 | - // newly created payments will have nothing recorded for $PAY_ID |
|
| 2040 | - if (absint($PAY_ID) === 0) { |
|
| 2041 | - return false; |
|
| 2042 | - } |
|
| 2043 | - $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment); |
|
| 2044 | - if (empty($existing_reg_payment_REG_IDs)) { |
|
| 2045 | - return false; |
|
| 2046 | - } |
|
| 2047 | - /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 2048 | - $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 2049 | - |
|
| 2050 | - return $transaction_payments->delete_registration_payments_and_update_registrations( |
|
| 2051 | - $payment, |
|
| 2052 | - array( |
|
| 2053 | - array( |
|
| 2054 | - 'PAY_ID' => $payment->ID(), |
|
| 2055 | - 'REG_ID' => array('IN', $existing_reg_payment_REG_IDs), |
|
| 2056 | - ), |
|
| 2057 | - ) |
|
| 2058 | - ); |
|
| 2059 | - } |
|
| 2060 | - |
|
| 2061 | - |
|
| 2062 | - /** |
|
| 2063 | - * _update_registration_payments |
|
| 2064 | - * this applies the payments to the selected registrations |
|
| 2065 | - * but only if they have not already been paid for |
|
| 2066 | - * |
|
| 2067 | - * @param EE_Transaction $transaction |
|
| 2068 | - * @param \EE_Payment $payment |
|
| 2069 | - * @param array $REG_IDs |
|
| 2070 | - * @return void |
|
| 2071 | - * @throws EE_Error |
|
| 2072 | - * @throws InvalidArgumentException |
|
| 2073 | - * @throws ReflectionException |
|
| 2074 | - * @throws RuntimeException |
|
| 2075 | - * @throws InvalidDataTypeException |
|
| 2076 | - * @throws InvalidInterfaceException |
|
| 2077 | - */ |
|
| 2078 | - protected function _update_registration_payments( |
|
| 2079 | - EE_Transaction $transaction, |
|
| 2080 | - EE_Payment $payment, |
|
| 2081 | - $REG_IDs = array() |
|
| 2082 | - ) { |
|
| 2083 | - // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments() |
|
| 2084 | - // so let's do that using our set of REG_IDs from the form |
|
| 2085 | - $registration_query_where_params = array( |
|
| 2086 | - 'REG_ID' => array('IN', $REG_IDs), |
|
| 2087 | - ); |
|
| 2088 | - // but add in some conditions regarding payment, |
|
| 2089 | - // so that we don't apply payments to registrations that are free or have already been paid for |
|
| 2090 | - // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative ) |
|
| 2091 | - if (! $payment->is_a_refund()) { |
|
| 2092 | - $registration_query_where_params['REG_final_price'] = array('!=', 0); |
|
| 2093 | - $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true); |
|
| 2094 | - } |
|
| 2095 | - $registrations = $transaction->registrations(array($registration_query_where_params)); |
|
| 2096 | - if (! empty($registrations)) { |
|
| 2097 | - /** @type EE_Payment_Processor $payment_processor */ |
|
| 2098 | - $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
|
| 2099 | - $payment_processor->process_registration_payments($transaction, $payment, $registrations); |
|
| 2100 | - } |
|
| 2101 | - } |
|
| 2102 | - |
|
| 2103 | - |
|
| 2104 | - /** |
|
| 2105 | - * _process_registration_status_change |
|
| 2106 | - * This processes requested registration status changes for all the registrations |
|
| 2107 | - * on a given transaction and (optionally) sends out notifications for the changes. |
|
| 2108 | - * |
|
| 2109 | - * @param EE_Transaction $transaction |
|
| 2110 | - * @param array $REG_IDs |
|
| 2111 | - * @return bool |
|
| 2112 | - * @throws EE_Error |
|
| 2113 | - * @throws InvalidArgumentException |
|
| 2114 | - * @throws ReflectionException |
|
| 2115 | - * @throws InvalidDataTypeException |
|
| 2116 | - * @throws InvalidInterfaceException |
|
| 2117 | - */ |
|
| 2118 | - protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array()) |
|
| 2119 | - { |
|
| 2120 | - // first if there is no change in status then we get out. |
|
| 2121 | - if (! isset($this->_req_data['txn_reg_status_change']['reg_status']) |
|
| 2122 | - || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN' |
|
| 2123 | - ) { |
|
| 2124 | - // no error message, no change requested, just nothing to do man. |
|
| 2125 | - return false; |
|
| 2126 | - } |
|
| 2127 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 2128 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 2129 | - |
|
| 2130 | - // made it here dude? Oh WOW. K, let's take care of changing the statuses |
|
| 2131 | - return $transaction_processor->manually_update_registration_statuses( |
|
| 2132 | - $transaction, |
|
| 2133 | - sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']), |
|
| 2134 | - array(array('REG_ID' => array('IN', $REG_IDs))) |
|
| 2135 | - ); |
|
| 2136 | - } |
|
| 2137 | - |
|
| 2138 | - |
|
| 2139 | - /** |
|
| 2140 | - * _build_payment_json_response |
|
| 2141 | - * |
|
| 2142 | - * @access public |
|
| 2143 | - * @param \EE_Payment $payment |
|
| 2144 | - * @param array $REG_IDs |
|
| 2145 | - * @param bool | null $delete_txn_reg_status_change |
|
| 2146 | - * @return array |
|
| 2147 | - * @throws EE_Error |
|
| 2148 | - * @throws InvalidArgumentException |
|
| 2149 | - * @throws InvalidDataTypeException |
|
| 2150 | - * @throws InvalidInterfaceException |
|
| 2151 | - * @throws ReflectionException |
|
| 2152 | - */ |
|
| 2153 | - protected function _build_payment_json_response( |
|
| 2154 | - EE_Payment $payment, |
|
| 2155 | - $REG_IDs = array(), |
|
| 2156 | - $delete_txn_reg_status_change = null |
|
| 2157 | - ) { |
|
| 2158 | - // was the payment deleted ? |
|
| 2159 | - if (is_bool($delete_txn_reg_status_change)) { |
|
| 2160 | - return array( |
|
| 2161 | - 'PAY_ID' => $payment->ID(), |
|
| 2162 | - 'amount' => $payment->amount(), |
|
| 2163 | - 'total_paid' => $payment->transaction()->paid(), |
|
| 2164 | - 'txn_status' => $payment->transaction()->status_ID(), |
|
| 2165 | - 'pay_status' => $payment->STS_ID(), |
|
| 2166 | - 'registrations' => $this->_registration_payment_data_array($REG_IDs), |
|
| 2167 | - 'delete_txn_reg_status_change' => $delete_txn_reg_status_change, |
|
| 2168 | - ); |
|
| 2169 | - } else { |
|
| 2170 | - $this->_get_payment_status_array(); |
|
| 2171 | - |
|
| 2172 | - return array( |
|
| 2173 | - 'amount' => $payment->amount(), |
|
| 2174 | - 'total_paid' => $payment->transaction()->paid(), |
|
| 2175 | - 'txn_status' => $payment->transaction()->status_ID(), |
|
| 2176 | - 'pay_status' => $payment->STS_ID(), |
|
| 2177 | - 'PAY_ID' => $payment->ID(), |
|
| 2178 | - 'STS_ID' => $payment->STS_ID(), |
|
| 2179 | - 'status' => self::$_pay_status[ $payment->STS_ID() ], |
|
| 2180 | - 'date' => $payment->timestamp('Y-m-d', 'h:i a'), |
|
| 2181 | - 'method' => strtoupper($payment->source()), |
|
| 2182 | - 'PM_ID' => $payment->payment_method() ? $payment->payment_method()->ID() : 1, |
|
| 2183 | - 'gateway' => $payment->payment_method() |
|
| 2184 | - ? $payment->payment_method()->admin_name() |
|
| 2185 | - : esc_html__('Unknown', 'event_espresso'), |
|
| 2186 | - 'gateway_response' => $payment->gateway_response(), |
|
| 2187 | - 'txn_id_chq_nmbr' => $payment->txn_id_chq_nmbr(), |
|
| 2188 | - 'po_number' => $payment->po_number(), |
|
| 2189 | - 'extra_accntng' => $payment->extra_accntng(), |
|
| 2190 | - 'registrations' => $this->_registration_payment_data_array($REG_IDs), |
|
| 2191 | - ); |
|
| 2192 | - } |
|
| 2193 | - } |
|
| 2194 | - |
|
| 2195 | - |
|
| 2196 | - /** |
|
| 2197 | - * delete_payment |
|
| 2198 | - * delete a payment or refund made towards a transaction |
|
| 2199 | - * |
|
| 2200 | - * @access public |
|
| 2201 | - * @return void |
|
| 2202 | - * @throws EE_Error |
|
| 2203 | - * @throws InvalidArgumentException |
|
| 2204 | - * @throws ReflectionException |
|
| 2205 | - * @throws InvalidDataTypeException |
|
| 2206 | - * @throws InvalidInterfaceException |
|
| 2207 | - */ |
|
| 2208 | - public function delete_payment() |
|
| 2209 | - { |
|
| 2210 | - $json_response_data = array('return_data' => false); |
|
| 2211 | - $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID']) |
|
| 2212 | - ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) |
|
| 2213 | - : 0; |
|
| 2214 | - $can_delete = EE_Registry::instance()->CAP->current_user_can( |
|
| 2215 | - 'ee_delete_payments', |
|
| 2216 | - 'delete_payment_from_registration_details' |
|
| 2217 | - ); |
|
| 2218 | - if ($PAY_ID && $can_delete) { |
|
| 2219 | - $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) |
|
| 2220 | - ? $this->_req_data['delete_txn_reg_status_change'] |
|
| 2221 | - : false; |
|
| 2222 | - $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); |
|
| 2223 | - if ($payment instanceof EE_Payment) { |
|
| 2224 | - $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment); |
|
| 2225 | - /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 2226 | - $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 2227 | - if ($transaction_payments->delete_payment_and_update_transaction($payment)) { |
|
| 2228 | - $json_response_data['return_data'] = $this->_build_payment_json_response( |
|
| 2229 | - $payment, |
|
| 2230 | - $REG_IDs, |
|
| 2231 | - $delete_txn_reg_status_change |
|
| 2232 | - ); |
|
| 2233 | - if ($delete_txn_reg_status_change) { |
|
| 2234 | - $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change; |
|
| 2235 | - // MAKE sure we also add the delete_txn_req_status_change to the |
|
| 2236 | - // $_REQUEST global because that's how messages will be looking for it. |
|
| 2237 | - $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change; |
|
| 2238 | - $this->_maybe_send_notifications(); |
|
| 2239 | - $this->_process_registration_status_change($payment->transaction(), $REG_IDs); |
|
| 2240 | - } |
|
| 2241 | - } |
|
| 2242 | - } else { |
|
| 2243 | - EE_Error::add_error( |
|
| 2244 | - esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'), |
|
| 2245 | - __FILE__, |
|
| 2246 | - __FUNCTION__, |
|
| 2247 | - __LINE__ |
|
| 2248 | - ); |
|
| 2249 | - } |
|
| 2250 | - } elseif ($can_delete) { |
|
| 2251 | - EE_Error::add_error( |
|
| 2252 | - esc_html__( |
|
| 2253 | - 'A valid Payment ID was not received, therefore payment form data could not be loaded.', |
|
| 2254 | - 'event_espresso' |
|
| 2255 | - ), |
|
| 2256 | - __FILE__, |
|
| 2257 | - __FUNCTION__, |
|
| 2258 | - __LINE__ |
|
| 2259 | - ); |
|
| 2260 | - } else { |
|
| 2261 | - EE_Error::add_error( |
|
| 2262 | - esc_html__( |
|
| 2263 | - 'You do not have access to delete a payment.', |
|
| 2264 | - 'event_espresso' |
|
| 2265 | - ), |
|
| 2266 | - __FILE__, |
|
| 2267 | - __FUNCTION__, |
|
| 2268 | - __LINE__ |
|
| 2269 | - ); |
|
| 2270 | - } |
|
| 2271 | - $notices = EE_Error::get_notices(false, false, false); |
|
| 2272 | - $this->_template_args = array( |
|
| 2273 | - 'data' => $json_response_data, |
|
| 2274 | - 'success' => $notices['success'], |
|
| 2275 | - 'error' => $notices['errors'], |
|
| 2276 | - 'attention' => $notices['attention'], |
|
| 2277 | - ); |
|
| 2278 | - $this->_return_json(); |
|
| 2279 | - } |
|
| 2280 | - |
|
| 2281 | - |
|
| 2282 | - /** |
|
| 2283 | - * _registration_payment_data_array |
|
| 2284 | - * adds info for 'owing' and 'paid' for each registration to the json response |
|
| 2285 | - * |
|
| 2286 | - * @access protected |
|
| 2287 | - * @param array $REG_IDs |
|
| 2288 | - * @return array |
|
| 2289 | - * @throws EE_Error |
|
| 2290 | - * @throws InvalidArgumentException |
|
| 2291 | - * @throws InvalidDataTypeException |
|
| 2292 | - * @throws InvalidInterfaceException |
|
| 2293 | - * @throws ReflectionException |
|
| 2294 | - */ |
|
| 2295 | - protected function _registration_payment_data_array($REG_IDs) |
|
| 2296 | - { |
|
| 2297 | - $registration_payment_data = array(); |
|
| 2298 | - // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows. |
|
| 2299 | - if (! empty($REG_IDs)) { |
|
| 2300 | - $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs)))); |
|
| 2301 | - foreach ($registrations as $registration) { |
|
| 2302 | - if ($registration instanceof EE_Registration) { |
|
| 2303 | - $registration_payment_data[ $registration->ID() ] = array( |
|
| 2304 | - 'paid' => $registration->pretty_paid(), |
|
| 2305 | - 'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()), |
|
| 2306 | - ); |
|
| 2307 | - } |
|
| 2308 | - } |
|
| 2309 | - } |
|
| 2310 | - |
|
| 2311 | - return $registration_payment_data; |
|
| 2312 | - } |
|
| 2313 | - |
|
| 2314 | - |
|
| 2315 | - /** |
|
| 2316 | - * _maybe_send_notifications |
|
| 2317 | - * determines whether or not the admin has indicated that notifications should be sent. |
|
| 2318 | - * If so, will toggle a filter switch for delivering registration notices. |
|
| 2319 | - * If passed an EE_Payment object, then it will trigger payment notifications instead. |
|
| 2320 | - * |
|
| 2321 | - * @access protected |
|
| 2322 | - * @param \EE_Payment | null $payment |
|
| 2323 | - */ |
|
| 2324 | - protected function _maybe_send_notifications($payment = null) |
|
| 2325 | - { |
|
| 2326 | - switch ($payment instanceof EE_Payment) { |
|
| 2327 | - // payment notifications |
|
| 2328 | - case true: |
|
| 2329 | - if (isset($this->_req_data['txn_payments']['send_notifications']) |
|
| 2330 | - && filter_var( |
|
| 2331 | - $this->_req_data['txn_payments']['send_notifications'], |
|
| 2332 | - FILTER_VALIDATE_BOOLEAN |
|
| 2333 | - ) |
|
| 2334 | - ) { |
|
| 2335 | - $this->_process_payment_notification($payment); |
|
| 2336 | - } |
|
| 2337 | - break; |
|
| 2338 | - // registration notifications |
|
| 2339 | - case false: |
|
| 2340 | - if (isset($this->_req_data['txn_reg_status_change']['send_notifications']) |
|
| 2341 | - && filter_var( |
|
| 2342 | - $this->_req_data['txn_reg_status_change']['send_notifications'], |
|
| 2343 | - FILTER_VALIDATE_BOOLEAN |
|
| 2344 | - ) |
|
| 2345 | - ) { |
|
| 2346 | - add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true'); |
|
| 2347 | - } |
|
| 2348 | - break; |
|
| 2349 | - } |
|
| 2350 | - } |
|
| 2351 | - |
|
| 2352 | - |
|
| 2353 | - /** |
|
| 2354 | - * _send_payment_reminder |
|
| 2355 | - * generates HTML for the View Transaction Details Admin page |
|
| 2356 | - * |
|
| 2357 | - * @access protected |
|
| 2358 | - * @return void |
|
| 2359 | - * @throws EE_Error |
|
| 2360 | - * @throws InvalidArgumentException |
|
| 2361 | - * @throws InvalidDataTypeException |
|
| 2362 | - * @throws InvalidInterfaceException |
|
| 2363 | - */ |
|
| 2364 | - protected function _send_payment_reminder() |
|
| 2365 | - { |
|
| 2366 | - $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false; |
|
| 2367 | - $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
| 2368 | - $query_args = isset($this->_req_data['redirect_to']) ? array( |
|
| 2369 | - 'action' => $this->_req_data['redirect_to'], |
|
| 2370 | - 'TXN_ID' => $this->_req_data['TXN_ID'], |
|
| 2371 | - ) : array(); |
|
| 2372 | - do_action( |
|
| 2373 | - 'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', |
|
| 2374 | - $transaction |
|
| 2375 | - ); |
|
| 2376 | - $this->_redirect_after_action( |
|
| 2377 | - false, |
|
| 2378 | - esc_html__('payment reminder', 'event_espresso'), |
|
| 2379 | - esc_html__('sent', 'event_espresso'), |
|
| 2380 | - $query_args, |
|
| 2381 | - true |
|
| 2382 | - ); |
|
| 2383 | - } |
|
| 2384 | - |
|
| 2385 | - |
|
| 2386 | - /** |
|
| 2387 | - * get_transactions |
|
| 2388 | - * get transactions for given parameters (used by list table) |
|
| 2389 | - * |
|
| 2390 | - * @param int $perpage how many transactions displayed per page |
|
| 2391 | - * @param boolean $count return the count or objects |
|
| 2392 | - * @param string $view |
|
| 2393 | - * @return mixed int = count || array of transaction objects |
|
| 2394 | - * @throws EE_Error |
|
| 2395 | - * @throws InvalidArgumentException |
|
| 2396 | - * @throws InvalidDataTypeException |
|
| 2397 | - * @throws InvalidInterfaceException |
|
| 2398 | - */ |
|
| 2399 | - public function get_transactions($perpage, $count = false, $view = '') |
|
| 2400 | - { |
|
| 2401 | - |
|
| 2402 | - $TXN = EEM_Transaction::instance(); |
|
| 2403 | - |
|
| 2404 | - $start_date = isset($this->_req_data['txn-filter-start-date']) |
|
| 2405 | - ? wp_strip_all_tags($this->_req_data['txn-filter-start-date']) |
|
| 2406 | - : date( |
|
| 2407 | - 'm/d/Y', |
|
| 2408 | - strtotime('-10 year') |
|
| 2409 | - ); |
|
| 2410 | - $end_date = isset($this->_req_data['txn-filter-end-date']) |
|
| 2411 | - ? wp_strip_all_tags($this->_req_data['txn-filter-end-date']) |
|
| 2412 | - : date('m/d/Y'); |
|
| 2413 | - |
|
| 2414 | - // make sure our timestamps start and end right at the boundaries for each day |
|
| 2415 | - $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00'; |
|
| 2416 | - $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59'; |
|
| 2417 | - |
|
| 2418 | - |
|
| 2419 | - // convert to timestamps |
|
| 2420 | - $start_date = strtotime($start_date); |
|
| 2421 | - $end_date = strtotime($end_date); |
|
| 2422 | - |
|
| 2423 | - // makes sure start date is the lowest value and vice versa |
|
| 2424 | - $start_date = min($start_date, $end_date); |
|
| 2425 | - $end_date = max($start_date, $end_date); |
|
| 2426 | - |
|
| 2427 | - // convert to correct format for query |
|
| 2428 | - $start_date = EEM_Transaction::instance()->convert_datetime_for_query( |
|
| 2429 | - 'TXN_timestamp', |
|
| 2430 | - date('Y-m-d H:i:s', $start_date), |
|
| 2431 | - 'Y-m-d H:i:s' |
|
| 2432 | - ); |
|
| 2433 | - $end_date = EEM_Transaction::instance()->convert_datetime_for_query( |
|
| 2434 | - 'TXN_timestamp', |
|
| 2435 | - date('Y-m-d H:i:s', $end_date), |
|
| 2436 | - 'Y-m-d H:i:s' |
|
| 2437 | - ); |
|
| 2438 | - |
|
| 2439 | - |
|
| 2440 | - // set orderby |
|
| 2441 | - $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : ''; |
|
| 2442 | - |
|
| 2443 | - switch ($this->_req_data['orderby']) { |
|
| 2444 | - case 'TXN_ID': |
|
| 2445 | - $orderby = 'TXN_ID'; |
|
| 2446 | - break; |
|
| 2447 | - case 'ATT_fname': |
|
| 2448 | - $orderby = 'Registration.Attendee.ATT_fname'; |
|
| 2449 | - break; |
|
| 2450 | - case 'event_name': |
|
| 2451 | - $orderby = 'Registration.Event.EVT_name'; |
|
| 2452 | - break; |
|
| 2453 | - default: // 'TXN_timestamp' |
|
| 2454 | - $orderby = 'TXN_timestamp'; |
|
| 2455 | - } |
|
| 2456 | - |
|
| 2457 | - $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC'; |
|
| 2458 | - $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1; |
|
| 2459 | - $per_page = ! empty($perpage) ? $perpage : 10; |
|
| 2460 | - $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page; |
|
| 2461 | - |
|
| 2462 | - $offset = ($current_page - 1) * $per_page; |
|
| 2463 | - $limit = array($offset, $per_page); |
|
| 2464 | - |
|
| 2465 | - $_where = array( |
|
| 2466 | - 'TXN_timestamp' => array('BETWEEN', array($start_date, $end_date)), |
|
| 2467 | - 'Registration.REG_count' => 1, |
|
| 2468 | - ); |
|
| 2469 | - |
|
| 2470 | - if (isset($this->_req_data['EVT_ID'])) { |
|
| 2471 | - $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID']; |
|
| 2472 | - } |
|
| 2473 | - |
|
| 2474 | - if (isset($this->_req_data['s'])) { |
|
| 2475 | - $search_string = '%' . $this->_req_data['s'] . '%'; |
|
| 2476 | - $_where['OR'] = array( |
|
| 2477 | - 'Registration.Event.EVT_name' => array('LIKE', $search_string), |
|
| 2478 | - 'Registration.Event.EVT_desc' => array('LIKE', $search_string), |
|
| 2479 | - 'Registration.Event.EVT_short_desc' => array('LIKE', $search_string), |
|
| 2480 | - 'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string), |
|
| 2481 | - 'Registration.Attendee.ATT_fname' => array('LIKE', $search_string), |
|
| 2482 | - 'Registration.Attendee.ATT_lname' => array('LIKE', $search_string), |
|
| 2483 | - 'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string), |
|
| 2484 | - 'Registration.Attendee.ATT_email' => array('LIKE', $search_string), |
|
| 2485 | - 'Registration.Attendee.ATT_address' => array('LIKE', $search_string), |
|
| 2486 | - 'Registration.Attendee.ATT_address2' => array('LIKE', $search_string), |
|
| 2487 | - 'Registration.Attendee.ATT_city' => array('LIKE', $search_string), |
|
| 2488 | - 'Registration.REG_final_price' => array('LIKE', $search_string), |
|
| 2489 | - 'Registration.REG_code' => array('LIKE', $search_string), |
|
| 2490 | - 'Registration.REG_count' => array('LIKE', $search_string), |
|
| 2491 | - 'Registration.REG_group_size' => array('LIKE', $search_string), |
|
| 2492 | - 'Registration.Ticket.TKT_name' => array('LIKE', $search_string), |
|
| 2493 | - 'Registration.Ticket.TKT_description' => array('LIKE', $search_string), |
|
| 2494 | - 'Payment.PAY_source' => array('LIKE', $search_string), |
|
| 2495 | - 'Payment.Payment_Method.PMD_name' => array('LIKE', $search_string), |
|
| 2496 | - 'TXN_session_data' => array('LIKE', $search_string), |
|
| 2497 | - 'Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string), |
|
| 2498 | - ); |
|
| 2499 | - } |
|
| 2500 | - |
|
| 2501 | - // failed transactions |
|
| 2502 | - $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count) |
|
| 2503 | - || ($count && $view === 'failed'); |
|
| 2504 | - $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count) |
|
| 2505 | - || ($count && $view === 'abandoned'); |
|
| 2506 | - $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count) |
|
| 2507 | - || ($count && $view === 'incomplete'); |
|
| 2508 | - |
|
| 2509 | - if ($failed) { |
|
| 2510 | - $_where['STS_ID'] = EEM_Transaction::failed_status_code; |
|
| 2511 | - } elseif ($abandoned) { |
|
| 2512 | - $_where['STS_ID'] = EEM_Transaction::abandoned_status_code; |
|
| 2513 | - } elseif ($incomplete) { |
|
| 2514 | - $_where['STS_ID'] = EEM_Transaction::incomplete_status_code; |
|
| 2515 | - } else { |
|
| 2516 | - $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code); |
|
| 2517 | - $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code); |
|
| 2518 | - } |
|
| 2519 | - |
|
| 2520 | - $query_params = apply_filters( |
|
| 2521 | - 'FHEE__Transactions_Admin_Page___get_transactions_query_params', |
|
| 2522 | - array( |
|
| 2523 | - $_where, |
|
| 2524 | - 'order_by' => array($orderby => $sort), |
|
| 2525 | - 'limit' => $limit, |
|
| 2526 | - 'default_where_conditions' => EEM_Base::default_where_conditions_this_only, |
|
| 2527 | - ), |
|
| 2528 | - $this->_req_data, |
|
| 2529 | - $view, |
|
| 2530 | - $count |
|
| 2531 | - ); |
|
| 2532 | - |
|
| 2533 | - $transactions = $count |
|
| 2534 | - ? $TXN->count(array($query_params[0]), 'TXN_ID', true) |
|
| 2535 | - : $TXN->get_all($query_params); |
|
| 2536 | - |
|
| 2537 | - return $transactions; |
|
| 2538 | - } |
|
| 2539 | - |
|
| 2540 | - |
|
| 2541 | - /** |
|
| 2542 | - * @since 4.9.79.p |
|
| 2543 | - * @throws EE_Error |
|
| 2544 | - * @throws InvalidArgumentException |
|
| 2545 | - * @throws InvalidDataTypeException |
|
| 2546 | - * @throws InvalidInterfaceException |
|
| 2547 | - * @throws ReflectionException |
|
| 2548 | - * @throws RuntimeException |
|
| 2549 | - */ |
|
| 2550 | - public function recalculateLineItems() |
|
| 2551 | - { |
|
| 2552 | - $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false; |
|
| 2553 | - /** @var EE_Transaction $transaction */ |
|
| 2554 | - $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
| 2555 | - $total_line_item = $transaction->total_line_item(false); |
|
| 2556 | - $success = false; |
|
| 2557 | - if ($total_line_item instanceof EE_Line_Item) { |
|
| 2558 | - EEH_Line_Item::resetIsTaxableForTickets($total_line_item); |
|
| 2559 | - $success = EEH_Line_Item::apply_taxes($total_line_item, true); |
|
| 2560 | - } |
|
| 2561 | - $this->_redirect_after_action( |
|
| 2562 | - (bool) $success, |
|
| 2563 | - esc_html__('Transaction taxes and totals', 'event_espresso'), |
|
| 2564 | - esc_html__('recalculated', 'event_espresso'), |
|
| 2565 | - isset($this->_req_data['redirect_to']) |
|
| 2566 | - ? array( |
|
| 2567 | - 'action' => $this->_req_data['redirect_to'], |
|
| 2568 | - 'TXN_ID' => $this->_req_data['TXN_ID'], |
|
| 2569 | - ) |
|
| 2570 | - : array(), |
|
| 2571 | - true |
|
| 2572 | - ); |
|
| 2573 | - } |
|
| 16 | + /** |
|
| 17 | + * @var EE_Transaction |
|
| 18 | + */ |
|
| 19 | + private $_transaction; |
|
| 20 | + |
|
| 21 | + /** |
|
| 22 | + * @var EE_Session |
|
| 23 | + */ |
|
| 24 | + private $_session; |
|
| 25 | + |
|
| 26 | + /** |
|
| 27 | + * @var array $_txn_status |
|
| 28 | + */ |
|
| 29 | + private static $_txn_status; |
|
| 30 | + |
|
| 31 | + /** |
|
| 32 | + * @var array $_pay_status |
|
| 33 | + */ |
|
| 34 | + private static $_pay_status; |
|
| 35 | + |
|
| 36 | + /** |
|
| 37 | + * @var array $_existing_reg_payment_REG_IDs |
|
| 38 | + */ |
|
| 39 | + protected $_existing_reg_payment_REG_IDs; |
|
| 40 | + |
|
| 41 | + |
|
| 42 | + /** |
|
| 43 | + * _init_page_props |
|
| 44 | + * |
|
| 45 | + * @return void |
|
| 46 | + */ |
|
| 47 | + protected function _init_page_props() |
|
| 48 | + { |
|
| 49 | + $this->page_slug = TXN_PG_SLUG; |
|
| 50 | + $this->page_label = esc_html__('Transactions', 'event_espresso'); |
|
| 51 | + $this->_admin_base_url = TXN_ADMIN_URL; |
|
| 52 | + $this->_admin_base_path = TXN_ADMIN; |
|
| 53 | + } |
|
| 54 | + |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * _ajax_hooks |
|
| 58 | + * |
|
| 59 | + * @return void |
|
| 60 | + */ |
|
| 61 | + protected function _ajax_hooks() |
|
| 62 | + { |
|
| 63 | + add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds')); |
|
| 64 | + add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds')); |
|
| 65 | + add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment')); |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + |
|
| 69 | + /** |
|
| 70 | + * _define_page_props |
|
| 71 | + * |
|
| 72 | + * @return void |
|
| 73 | + */ |
|
| 74 | + protected function _define_page_props() |
|
| 75 | + { |
|
| 76 | + $this->_admin_page_title = $this->page_label; |
|
| 77 | + $this->_labels = array( |
|
| 78 | + 'buttons' => array( |
|
| 79 | + 'add' => esc_html__('Add New Transaction', 'event_espresso'), |
|
| 80 | + 'edit' => esc_html__('Edit Transaction', 'event_espresso'), |
|
| 81 | + 'delete' => esc_html__('Delete Transaction', 'event_espresso'), |
|
| 82 | + ), |
|
| 83 | + ); |
|
| 84 | + } |
|
| 85 | + |
|
| 86 | + |
|
| 87 | + /** |
|
| 88 | + * grab url requests and route them |
|
| 89 | + * |
|
| 90 | + * @access private |
|
| 91 | + * @return void |
|
| 92 | + * @throws EE_Error |
|
| 93 | + * @throws InvalidArgumentException |
|
| 94 | + * @throws InvalidDataTypeException |
|
| 95 | + * @throws InvalidInterfaceException |
|
| 96 | + */ |
|
| 97 | + public function _set_page_routes() |
|
| 98 | + { |
|
| 99 | + |
|
| 100 | + $this->_set_transaction_status_array(); |
|
| 101 | + |
|
| 102 | + $txn_id = ! empty($this->_req_data['TXN_ID']) |
|
| 103 | + && ! is_array($this->_req_data['TXN_ID']) |
|
| 104 | + ? $this->_req_data['TXN_ID'] |
|
| 105 | + : 0; |
|
| 106 | + |
|
| 107 | + $this->_page_routes = array( |
|
| 108 | + |
|
| 109 | + 'default' => array( |
|
| 110 | + 'func' => '_transactions_overview_list_table', |
|
| 111 | + 'capability' => 'ee_read_transactions', |
|
| 112 | + ), |
|
| 113 | + |
|
| 114 | + 'view_transaction' => array( |
|
| 115 | + 'func' => '_transaction_details', |
|
| 116 | + 'capability' => 'ee_read_transaction', |
|
| 117 | + 'obj_id' => $txn_id, |
|
| 118 | + ), |
|
| 119 | + |
|
| 120 | + 'send_payment_reminder' => array( |
|
| 121 | + 'func' => '_send_payment_reminder', |
|
| 122 | + 'noheader' => true, |
|
| 123 | + 'capability' => 'ee_send_message', |
|
| 124 | + ), |
|
| 125 | + |
|
| 126 | + 'espresso_apply_payment' => array( |
|
| 127 | + 'func' => 'apply_payments_or_refunds', |
|
| 128 | + 'noheader' => true, |
|
| 129 | + 'capability' => 'ee_edit_payments', |
|
| 130 | + ), |
|
| 131 | + |
|
| 132 | + 'espresso_apply_refund' => array( |
|
| 133 | + 'func' => 'apply_payments_or_refunds', |
|
| 134 | + 'noheader' => true, |
|
| 135 | + 'capability' => 'ee_edit_payments', |
|
| 136 | + ), |
|
| 137 | + |
|
| 138 | + 'espresso_delete_payment' => array( |
|
| 139 | + 'func' => 'delete_payment', |
|
| 140 | + 'noheader' => true, |
|
| 141 | + 'capability' => 'ee_delete_payments', |
|
| 142 | + ), |
|
| 143 | + |
|
| 144 | + 'espresso_recalculate_line_items' => array( |
|
| 145 | + 'func' => 'recalculateLineItems', |
|
| 146 | + 'noheader' => true, |
|
| 147 | + 'capability' => 'ee_edit_payments', |
|
| 148 | + ), |
|
| 149 | + |
|
| 150 | + ); |
|
| 151 | + } |
|
| 152 | + |
|
| 153 | + |
|
| 154 | + protected function _set_page_config() |
|
| 155 | + { |
|
| 156 | + $this->_page_config = array( |
|
| 157 | + 'default' => array( |
|
| 158 | + 'nav' => array( |
|
| 159 | + 'label' => esc_html__('Overview', 'event_espresso'), |
|
| 160 | + 'order' => 10, |
|
| 161 | + ), |
|
| 162 | + 'list_table' => 'EE_Admin_Transactions_List_Table', |
|
| 163 | + 'help_tabs' => array( |
|
| 164 | + 'transactions_overview_help_tab' => array( |
|
| 165 | + 'title' => esc_html__('Transactions Overview', 'event_espresso'), |
|
| 166 | + 'filename' => 'transactions_overview', |
|
| 167 | + ), |
|
| 168 | + 'transactions_overview_table_column_headings_help_tab' => array( |
|
| 169 | + 'title' => esc_html__('Transactions Table Column Headings', 'event_espresso'), |
|
| 170 | + 'filename' => 'transactions_overview_table_column_headings', |
|
| 171 | + ), |
|
| 172 | + 'transactions_overview_views_filters_help_tab' => array( |
|
| 173 | + 'title' => esc_html__('Transaction Views & Filters & Search', 'event_espresso'), |
|
| 174 | + 'filename' => 'transactions_overview_views_filters_search', |
|
| 175 | + ), |
|
| 176 | + ), |
|
| 177 | + 'help_tour' => array('Transactions_Overview_Help_Tour'), |
|
| 178 | + /** |
|
| 179 | + * commented out because currently we are not displaying tips for transaction list table status but this |
|
| 180 | + * may change in a later iteration so want to keep the code for then. |
|
| 181 | + */ |
|
| 182 | + // 'qtips' => array( 'Transactions_List_Table_Tips' ), |
|
| 183 | + 'require_nonce' => false, |
|
| 184 | + ), |
|
| 185 | + 'view_transaction' => array( |
|
| 186 | + 'nav' => array( |
|
| 187 | + 'label' => esc_html__('View Transaction', 'event_espresso'), |
|
| 188 | + 'order' => 5, |
|
| 189 | + 'url' => isset($this->_req_data['TXN_ID']) |
|
| 190 | + ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url) |
|
| 191 | + : $this->_admin_base_url, |
|
| 192 | + 'persistent' => false, |
|
| 193 | + ), |
|
| 194 | + 'help_tabs' => array( |
|
| 195 | + 'transactions_view_transaction_help_tab' => array( |
|
| 196 | + 'title' => esc_html__('View Transaction', 'event_espresso'), |
|
| 197 | + 'filename' => 'transactions_view_transaction', |
|
| 198 | + ), |
|
| 199 | + 'transactions_view_transaction_transaction_details_table_help_tab' => array( |
|
| 200 | + 'title' => esc_html__('Transaction Details Table', 'event_espresso'), |
|
| 201 | + 'filename' => 'transactions_view_transaction_transaction_details_table', |
|
| 202 | + ), |
|
| 203 | + 'transactions_view_transaction_attendees_registered_help_tab' => array( |
|
| 204 | + 'title' => esc_html__('Attendees Registered', 'event_espresso'), |
|
| 205 | + 'filename' => 'transactions_view_transaction_attendees_registered', |
|
| 206 | + ), |
|
| 207 | + 'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array( |
|
| 208 | + 'title' => esc_html__('Primary Registrant & Billing Information', 'event_espresso'), |
|
| 209 | + 'filename' => 'transactions_view_transaction_primary_registrant_billing_information', |
|
| 210 | + ), |
|
| 211 | + ), |
|
| 212 | + 'qtips' => array('Transaction_Details_Tips'), |
|
| 213 | + 'help_tour' => array('Transaction_Details_Help_Tour'), |
|
| 214 | + 'metaboxes' => array('_transaction_details_metaboxes'), |
|
| 215 | + |
|
| 216 | + 'require_nonce' => false, |
|
| 217 | + ), |
|
| 218 | + ); |
|
| 219 | + } |
|
| 220 | + |
|
| 221 | + |
|
| 222 | + /** |
|
| 223 | + * The below methods aren't used by this class currently |
|
| 224 | + */ |
|
| 225 | + protected function _add_screen_options() |
|
| 226 | + { |
|
| 227 | + // noop |
|
| 228 | + } |
|
| 229 | + |
|
| 230 | + |
|
| 231 | + protected function _add_feature_pointers() |
|
| 232 | + { |
|
| 233 | + // noop |
|
| 234 | + } |
|
| 235 | + |
|
| 236 | + |
|
| 237 | + public function admin_init() |
|
| 238 | + { |
|
| 239 | + // IF a registration was JUST added via the admin... |
|
| 240 | + if (isset( |
|
| 241 | + $this->_req_data['redirect_from'], |
|
| 242 | + $this->_req_data['EVT_ID'], |
|
| 243 | + $this->_req_data['event_name'] |
|
| 244 | + )) { |
|
| 245 | + // then set a cookie so that we can block any attempts to use |
|
| 246 | + // the back button as a way to enter another registration. |
|
| 247 | + setcookie( |
|
| 248 | + 'ee_registration_added', |
|
| 249 | + $this->_req_data['EVT_ID'], |
|
| 250 | + time() + WEEK_IN_SECONDS, |
|
| 251 | + '/' |
|
| 252 | + ); |
|
| 253 | + // and update the global |
|
| 254 | + $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID']; |
|
| 255 | + } |
|
| 256 | + EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__( |
|
| 257 | + 'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.', |
|
| 258 | + 'event_espresso' |
|
| 259 | + ); |
|
| 260 | + EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__( |
|
| 261 | + 'An error occurred! Please refresh the page and try again.', |
|
| 262 | + 'event_espresso' |
|
| 263 | + ); |
|
| 264 | + EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status; |
|
| 265 | + EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status; |
|
| 266 | + EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso'); |
|
| 267 | + EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__( |
|
| 268 | + 'This transaction has been overpaid ! Payments Total', |
|
| 269 | + 'event_espresso' |
|
| 270 | + ); |
|
| 271 | + } |
|
| 272 | + |
|
| 273 | + |
|
| 274 | + public function admin_notices() |
|
| 275 | + { |
|
| 276 | + // noop |
|
| 277 | + } |
|
| 278 | + |
|
| 279 | + |
|
| 280 | + public function admin_footer_scripts() |
|
| 281 | + { |
|
| 282 | + // noop |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + |
|
| 286 | + /** |
|
| 287 | + * _set_transaction_status_array |
|
| 288 | + * sets list of transaction statuses |
|
| 289 | + * |
|
| 290 | + * @access private |
|
| 291 | + * @return void |
|
| 292 | + * @throws EE_Error |
|
| 293 | + * @throws InvalidArgumentException |
|
| 294 | + * @throws InvalidDataTypeException |
|
| 295 | + * @throws InvalidInterfaceException |
|
| 296 | + */ |
|
| 297 | + private function _set_transaction_status_array() |
|
| 298 | + { |
|
| 299 | + self::$_txn_status = EEM_Transaction::instance()->status_array(true); |
|
| 300 | + } |
|
| 301 | + |
|
| 302 | + |
|
| 303 | + /** |
|
| 304 | + * get_transaction_status_array |
|
| 305 | + * return the transaction status array for wp_list_table |
|
| 306 | + * |
|
| 307 | + * @access public |
|
| 308 | + * @return array |
|
| 309 | + */ |
|
| 310 | + public function get_transaction_status_array() |
|
| 311 | + { |
|
| 312 | + return self::$_txn_status; |
|
| 313 | + } |
|
| 314 | + |
|
| 315 | + |
|
| 316 | + /** |
|
| 317 | + * get list of payment statuses |
|
| 318 | + * |
|
| 319 | + * @access private |
|
| 320 | + * @return void |
|
| 321 | + * @throws EE_Error |
|
| 322 | + * @throws InvalidArgumentException |
|
| 323 | + * @throws InvalidDataTypeException |
|
| 324 | + * @throws InvalidInterfaceException |
|
| 325 | + */ |
|
| 326 | + private function _get_payment_status_array() |
|
| 327 | + { |
|
| 328 | + self::$_pay_status = EEM_Payment::instance()->status_array(true); |
|
| 329 | + $this->_template_args['payment_status'] = self::$_pay_status; |
|
| 330 | + } |
|
| 331 | + |
|
| 332 | + |
|
| 333 | + /** |
|
| 334 | + * _add_screen_options_default |
|
| 335 | + * |
|
| 336 | + * @access protected |
|
| 337 | + * @return void |
|
| 338 | + * @throws InvalidArgumentException |
|
| 339 | + * @throws InvalidDataTypeException |
|
| 340 | + * @throws InvalidInterfaceException |
|
| 341 | + */ |
|
| 342 | + protected function _add_screen_options_default() |
|
| 343 | + { |
|
| 344 | + $this->_per_page_screen_option(); |
|
| 345 | + } |
|
| 346 | + |
|
| 347 | + |
|
| 348 | + /** |
|
| 349 | + * load_scripts_styles |
|
| 350 | + * |
|
| 351 | + * @access public |
|
| 352 | + * @return void |
|
| 353 | + */ |
|
| 354 | + public function load_scripts_styles() |
|
| 355 | + { |
|
| 356 | + // enqueue style |
|
| 357 | + wp_register_style( |
|
| 358 | + 'espresso_txn', |
|
| 359 | + TXN_ASSETS_URL . 'espresso_transactions_admin.css', |
|
| 360 | + array(), |
|
| 361 | + EVENT_ESPRESSO_VERSION |
|
| 362 | + ); |
|
| 363 | + wp_enqueue_style('espresso_txn'); |
|
| 364 | + // scripts |
|
| 365 | + wp_register_script( |
|
| 366 | + 'espresso_txn', |
|
| 367 | + TXN_ASSETS_URL . 'espresso_transactions_admin.js', |
|
| 368 | + array( |
|
| 369 | + 'ee_admin_js', |
|
| 370 | + 'ee-datepicker', |
|
| 371 | + 'jquery-ui-datepicker', |
|
| 372 | + 'jquery-ui-draggable', |
|
| 373 | + 'ee-dialog', |
|
| 374 | + 'ee-accounting', |
|
| 375 | + 'ee-serialize-full-array', |
|
| 376 | + ), |
|
| 377 | + EVENT_ESPRESSO_VERSION, |
|
| 378 | + true |
|
| 379 | + ); |
|
| 380 | + wp_enqueue_script('espresso_txn'); |
|
| 381 | + } |
|
| 382 | + |
|
| 383 | + |
|
| 384 | + /** |
|
| 385 | + * load_scripts_styles_view_transaction |
|
| 386 | + * |
|
| 387 | + * @access public |
|
| 388 | + * @return void |
|
| 389 | + */ |
|
| 390 | + public function load_scripts_styles_view_transaction() |
|
| 391 | + { |
|
| 392 | + // styles |
|
| 393 | + wp_enqueue_style('espresso-ui-theme'); |
|
| 394 | + } |
|
| 395 | + |
|
| 396 | + |
|
| 397 | + /** |
|
| 398 | + * load_scripts_styles_default |
|
| 399 | + * |
|
| 400 | + * @access public |
|
| 401 | + * @return void |
|
| 402 | + */ |
|
| 403 | + public function load_scripts_styles_default() |
|
| 404 | + { |
|
| 405 | + // styles |
|
| 406 | + wp_enqueue_style('espresso-ui-theme'); |
|
| 407 | + } |
|
| 408 | + |
|
| 409 | + |
|
| 410 | + /** |
|
| 411 | + * _set_list_table_views_default |
|
| 412 | + * |
|
| 413 | + * @access protected |
|
| 414 | + * @return void |
|
| 415 | + */ |
|
| 416 | + protected function _set_list_table_views_default() |
|
| 417 | + { |
|
| 418 | + $this->_views = array( |
|
| 419 | + 'all' => array( |
|
| 420 | + 'slug' => 'all', |
|
| 421 | + 'label' => esc_html__('View All Transactions', 'event_espresso'), |
|
| 422 | + 'count' => 0, |
|
| 423 | + ), |
|
| 424 | + 'abandoned' => array( |
|
| 425 | + 'slug' => 'abandoned', |
|
| 426 | + 'label' => esc_html__('Abandoned Transactions', 'event_espresso'), |
|
| 427 | + 'count' => 0, |
|
| 428 | + ), |
|
| 429 | + 'incomplete' => array( |
|
| 430 | + 'slug' => 'incomplete', |
|
| 431 | + 'label' => esc_html__('Incomplete Transactions', 'event_espresso'), |
|
| 432 | + 'count' => 0, |
|
| 433 | + ), |
|
| 434 | + ); |
|
| 435 | + if (/** |
|
| 436 | + * Filters whether a link to the "Failed Transactions" list table |
|
| 437 | + * appears on the Transactions Admin Page list table. |
|
| 438 | + * List display can be turned back on via the following: |
|
| 439 | + * add_filter( |
|
| 440 | + * 'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list', |
|
| 441 | + * '__return_true' |
|
| 442 | + * ); |
|
| 443 | + * |
|
| 444 | + * @since 4.9.70.p |
|
| 445 | + * @param boolean $display_failed_txns_list |
|
| 446 | + * @param Transactions_Admin_Page $this |
|
| 447 | + */ |
|
| 448 | + apply_filters( |
|
| 449 | + 'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list', |
|
| 450 | + false, |
|
| 451 | + $this |
|
| 452 | + ) |
|
| 453 | + ) { |
|
| 454 | + $this->_views['failed'] = array( |
|
| 455 | + 'slug' => 'failed', |
|
| 456 | + 'label' => esc_html__('Failed Transactions', 'event_espresso'), |
|
| 457 | + 'count' => 0, |
|
| 458 | + ); |
|
| 459 | + } |
|
| 460 | + } |
|
| 461 | + |
|
| 462 | + |
|
| 463 | + /** |
|
| 464 | + * _set_transaction_object |
|
| 465 | + * This sets the _transaction property for the transaction details screen |
|
| 466 | + * |
|
| 467 | + * @access private |
|
| 468 | + * @return void |
|
| 469 | + * @throws EE_Error |
|
| 470 | + * @throws InvalidArgumentException |
|
| 471 | + * @throws RuntimeException |
|
| 472 | + * @throws InvalidDataTypeException |
|
| 473 | + * @throws InvalidInterfaceException |
|
| 474 | + * @throws ReflectionException |
|
| 475 | + */ |
|
| 476 | + private function _set_transaction_object() |
|
| 477 | + { |
|
| 478 | + if ($this->_transaction instanceof EE_Transaction) { |
|
| 479 | + return; |
|
| 480 | + } //get out we've already set the object |
|
| 481 | + |
|
| 482 | + $TXN_ID = ! empty($this->_req_data['TXN_ID']) |
|
| 483 | + ? absint($this->_req_data['TXN_ID']) |
|
| 484 | + : false; |
|
| 485 | + |
|
| 486 | + // get transaction object |
|
| 487 | + $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
| 488 | + $this->_session = $this->_transaction instanceof EE_Transaction |
|
| 489 | + ? $this->_transaction->session_data() |
|
| 490 | + : null; |
|
| 491 | + if ($this->_transaction instanceof EE_Transaction) { |
|
| 492 | + $this->_transaction->verify_abandoned_transaction_status(); |
|
| 493 | + } |
|
| 494 | + |
|
| 495 | + if (! $this->_transaction instanceof EE_Transaction) { |
|
| 496 | + $error_msg = sprintf( |
|
| 497 | + esc_html__( |
|
| 498 | + 'An error occurred and the details for the transaction with the ID # %d could not be retrieved.', |
|
| 499 | + 'event_espresso' |
|
| 500 | + ), |
|
| 501 | + $TXN_ID |
|
| 502 | + ); |
|
| 503 | + EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 504 | + } |
|
| 505 | + } |
|
| 506 | + |
|
| 507 | + |
|
| 508 | + /** |
|
| 509 | + * _transaction_legend_items |
|
| 510 | + * |
|
| 511 | + * @access protected |
|
| 512 | + * @return array |
|
| 513 | + * @throws EE_Error |
|
| 514 | + * @throws InvalidArgumentException |
|
| 515 | + * @throws ReflectionException |
|
| 516 | + * @throws InvalidDataTypeException |
|
| 517 | + * @throws InvalidInterfaceException |
|
| 518 | + */ |
|
| 519 | + protected function _transaction_legend_items() |
|
| 520 | + { |
|
| 521 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
| 522 | + $items = array(); |
|
| 523 | + |
|
| 524 | + if (EE_Registry::instance()->CAP->current_user_can( |
|
| 525 | + 'ee_read_global_messages', |
|
| 526 | + 'view_filtered_messages' |
|
| 527 | + )) { |
|
| 528 | + $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for'); |
|
| 529 | + if (is_array($related_for_icon) |
|
| 530 | + && isset($related_for_icon['css_class'], $related_for_icon['label']) |
|
| 531 | + ) { |
|
| 532 | + $items['view_related_messages'] = array( |
|
| 533 | + 'class' => $related_for_icon['css_class'], |
|
| 534 | + 'desc' => $related_for_icon['label'], |
|
| 535 | + ); |
|
| 536 | + } |
|
| 537 | + } |
|
| 538 | + |
|
| 539 | + $items = apply_filters( |
|
| 540 | + 'FHEE__Transactions_Admin_Page___transaction_legend_items__items', |
|
| 541 | + array_merge( |
|
| 542 | + $items, |
|
| 543 | + array( |
|
| 544 | + 'view_details' => array( |
|
| 545 | + 'class' => 'dashicons dashicons-cart', |
|
| 546 | + 'desc' => esc_html__('View Transaction Details', 'event_espresso'), |
|
| 547 | + ), |
|
| 548 | + 'view_invoice' => array( |
|
| 549 | + 'class' => 'dashicons dashicons-media-spreadsheet', |
|
| 550 | + 'desc' => esc_html__('View Transaction Invoice', 'event_espresso'), |
|
| 551 | + ), |
|
| 552 | + 'view_receipt' => array( |
|
| 553 | + 'class' => 'dashicons dashicons-media-default', |
|
| 554 | + 'desc' => esc_html__('View Transaction Receipt', 'event_espresso'), |
|
| 555 | + ), |
|
| 556 | + 'view_registration' => array( |
|
| 557 | + 'class' => 'dashicons dashicons-clipboard', |
|
| 558 | + 'desc' => esc_html__('View Registration Details', 'event_espresso'), |
|
| 559 | + ), |
|
| 560 | + 'payment_overview_link' => array( |
|
| 561 | + 'class' => 'dashicons dashicons-money', |
|
| 562 | + 'desc' => esc_html__('Make Payment on Frontend', 'event_espresso'), |
|
| 563 | + ), |
|
| 564 | + ) |
|
| 565 | + ) |
|
| 566 | + ); |
|
| 567 | + |
|
| 568 | + if (EEH_MSG_Template::is_mt_active('payment_reminder') |
|
| 569 | + && EE_Registry::instance()->CAP->current_user_can( |
|
| 570 | + 'ee_send_message', |
|
| 571 | + 'espresso_transactions_send_payment_reminder' |
|
| 572 | + ) |
|
| 573 | + ) { |
|
| 574 | + $items['send_payment_reminder'] = array( |
|
| 575 | + 'class' => 'dashicons dashicons-email-alt', |
|
| 576 | + 'desc' => esc_html__('Send Payment Reminder', 'event_espresso'), |
|
| 577 | + ); |
|
| 578 | + } else { |
|
| 579 | + $items['blank*'] = array( |
|
| 580 | + 'class' => '', |
|
| 581 | + 'desc' => '', |
|
| 582 | + ); |
|
| 583 | + } |
|
| 584 | + $more_items = apply_filters( |
|
| 585 | + 'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items', |
|
| 586 | + array( |
|
| 587 | + 'overpaid' => array( |
|
| 588 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code, |
|
| 589 | + 'desc' => EEH_Template::pretty_status( |
|
| 590 | + EEM_Transaction::overpaid_status_code, |
|
| 591 | + false, |
|
| 592 | + 'sentence' |
|
| 593 | + ), |
|
| 594 | + ), |
|
| 595 | + 'complete' => array( |
|
| 596 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code, |
|
| 597 | + 'desc' => EEH_Template::pretty_status( |
|
| 598 | + EEM_Transaction::complete_status_code, |
|
| 599 | + false, |
|
| 600 | + 'sentence' |
|
| 601 | + ), |
|
| 602 | + ), |
|
| 603 | + 'incomplete' => array( |
|
| 604 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code, |
|
| 605 | + 'desc' => EEH_Template::pretty_status( |
|
| 606 | + EEM_Transaction::incomplete_status_code, |
|
| 607 | + false, |
|
| 608 | + 'sentence' |
|
| 609 | + ), |
|
| 610 | + ), |
|
| 611 | + 'abandoned' => array( |
|
| 612 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code, |
|
| 613 | + 'desc' => EEH_Template::pretty_status( |
|
| 614 | + EEM_Transaction::abandoned_status_code, |
|
| 615 | + false, |
|
| 616 | + 'sentence' |
|
| 617 | + ), |
|
| 618 | + ), |
|
| 619 | + 'failed' => array( |
|
| 620 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code, |
|
| 621 | + 'desc' => EEH_Template::pretty_status( |
|
| 622 | + EEM_Transaction::failed_status_code, |
|
| 623 | + false, |
|
| 624 | + 'sentence' |
|
| 625 | + ), |
|
| 626 | + ), |
|
| 627 | + ) |
|
| 628 | + ); |
|
| 629 | + |
|
| 630 | + return array_merge($items, $more_items); |
|
| 631 | + } |
|
| 632 | + |
|
| 633 | + |
|
| 634 | + /** |
|
| 635 | + * _transactions_overview_list_table |
|
| 636 | + * |
|
| 637 | + * @access protected |
|
| 638 | + * @return void |
|
| 639 | + * @throws DomainException |
|
| 640 | + * @throws EE_Error |
|
| 641 | + * @throws InvalidArgumentException |
|
| 642 | + * @throws InvalidDataTypeException |
|
| 643 | + * @throws InvalidInterfaceException |
|
| 644 | + * @throws ReflectionException |
|
| 645 | + */ |
|
| 646 | + protected function _transactions_overview_list_table() |
|
| 647 | + { |
|
| 648 | + $this->_admin_page_title = esc_html__('Transactions', 'event_espresso'); |
|
| 649 | + $event = isset($this->_req_data['EVT_ID']) |
|
| 650 | + ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']) |
|
| 651 | + : null; |
|
| 652 | + $this->_template_args['admin_page_header'] = $event instanceof EE_Event |
|
| 653 | + ? sprintf( |
|
| 654 | + esc_html__( |
|
| 655 | + '%sViewing Transactions for the Event: %s%s', |
|
| 656 | + 'event_espresso' |
|
| 657 | + ), |
|
| 658 | + '<h3>', |
|
| 659 | + '<a href="' |
|
| 660 | + . EE_Admin_Page::add_query_args_and_nonce( |
|
| 661 | + array('action' => 'edit', 'post' => $event->ID()), |
|
| 662 | + EVENTS_ADMIN_URL |
|
| 663 | + ) |
|
| 664 | + . '" title="' |
|
| 665 | + . esc_attr__( |
|
| 666 | + 'Click to Edit event', |
|
| 667 | + 'event_espresso' |
|
| 668 | + ) |
|
| 669 | + . '">' . $event->name() . '</a>', |
|
| 670 | + '</h3>' |
|
| 671 | + ) |
|
| 672 | + : ''; |
|
| 673 | + $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items()); |
|
| 674 | + $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 675 | + } |
|
| 676 | + |
|
| 677 | + |
|
| 678 | + /** |
|
| 679 | + * _transaction_details |
|
| 680 | + * generates HTML for the View Transaction Details Admin page |
|
| 681 | + * |
|
| 682 | + * @access protected |
|
| 683 | + * @return void |
|
| 684 | + * @throws DomainException |
|
| 685 | + * @throws EE_Error |
|
| 686 | + * @throws InvalidArgumentException |
|
| 687 | + * @throws InvalidDataTypeException |
|
| 688 | + * @throws InvalidInterfaceException |
|
| 689 | + * @throws RuntimeException |
|
| 690 | + * @throws ReflectionException |
|
| 691 | + */ |
|
| 692 | + protected function _transaction_details() |
|
| 693 | + { |
|
| 694 | + do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction); |
|
| 695 | + |
|
| 696 | + $this->_set_transaction_status_array(); |
|
| 697 | + |
|
| 698 | + $this->_template_args = array(); |
|
| 699 | + $this->_template_args['transactions_page'] = $this->_wp_page_slug; |
|
| 700 | + |
|
| 701 | + $this->_set_transaction_object(); |
|
| 702 | + |
|
| 703 | + if (! $this->_transaction instanceof EE_Transaction) { |
|
| 704 | + return; |
|
| 705 | + } |
|
| 706 | + $primary_registration = $this->_transaction->primary_registration(); |
|
| 707 | + $attendee = $primary_registration instanceof EE_Registration |
|
| 708 | + ? $primary_registration->attendee() |
|
| 709 | + : null; |
|
| 710 | + |
|
| 711 | + $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID(); |
|
| 712 | + $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso'); |
|
| 713 | + |
|
| 714 | + $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp'); |
|
| 715 | + $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso'); |
|
| 716 | + |
|
| 717 | + $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ]; |
|
| 718 | + $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso'); |
|
| 719 | + $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID(); |
|
| 720 | + |
|
| 721 | + $this->_template_args['grand_total'] = $this->_transaction->total(); |
|
| 722 | + $this->_template_args['total_paid'] = $this->_transaction->paid(); |
|
| 723 | + |
|
| 724 | + $amount_due = $this->_transaction->total() - $this->_transaction->paid(); |
|
| 725 | + $this->_template_args['amount_due'] = EEH_Template::format_currency( |
|
| 726 | + $amount_due, |
|
| 727 | + true |
|
| 728 | + ); |
|
| 729 | + if (EE_Registry::instance()->CFG->currency->sign_b4) { |
|
| 730 | + $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign |
|
| 731 | + . $this->_template_args['amount_due']; |
|
| 732 | + } else { |
|
| 733 | + $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign; |
|
| 734 | + } |
|
| 735 | + $this->_template_args['amount_due_class'] = ''; |
|
| 736 | + |
|
| 737 | + if ($this->_transaction->paid() === $this->_transaction->total()) { |
|
| 738 | + // paid in full |
|
| 739 | + $this->_template_args['amount_due'] = false; |
|
| 740 | + } elseif ($this->_transaction->paid() > $this->_transaction->total()) { |
|
| 741 | + // overpaid |
|
| 742 | + $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn'; |
|
| 743 | + } elseif ($this->_transaction->total() > (float) 0) { |
|
| 744 | + if ($this->_transaction->paid() > (float) 0) { |
|
| 745 | + // monies owing |
|
| 746 | + $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn'; |
|
| 747 | + } elseif ($this->_transaction->paid() === (float) 0) { |
|
| 748 | + // no payments made yet |
|
| 749 | + $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn'; |
|
| 750 | + } |
|
| 751 | + } elseif ($this->_transaction->total() === (float) 0) { |
|
| 752 | + // free event |
|
| 753 | + $this->_template_args['amount_due'] = false; |
|
| 754 | + } |
|
| 755 | + |
|
| 756 | + $payment_method = $this->_transaction->payment_method(); |
|
| 757 | + |
|
| 758 | + $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method |
|
| 759 | + ? $payment_method->admin_name() |
|
| 760 | + : esc_html__('Unknown', 'event_espresso'); |
|
| 761 | + |
|
| 762 | + $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign; |
|
| 763 | + // link back to overview |
|
| 764 | + $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER']) |
|
| 765 | + ? $_SERVER['HTTP_REFERER'] |
|
| 766 | + : TXN_ADMIN_URL; |
|
| 767 | + |
|
| 768 | + |
|
| 769 | + // next link |
|
| 770 | + $next_txn = $this->_transaction->next( |
|
| 771 | + null, |
|
| 772 | + array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))), |
|
| 773 | + 'TXN_ID' |
|
| 774 | + ); |
|
| 775 | + $this->_template_args['next_transaction'] = $next_txn |
|
| 776 | + ? $this->_next_link( |
|
| 777 | + EE_Admin_Page::add_query_args_and_nonce( |
|
| 778 | + array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']), |
|
| 779 | + TXN_ADMIN_URL |
|
| 780 | + ), |
|
| 781 | + 'dashicons dashicons-arrow-right ee-icon-size-22' |
|
| 782 | + ) |
|
| 783 | + : ''; |
|
| 784 | + // previous link |
|
| 785 | + $previous_txn = $this->_transaction->previous( |
|
| 786 | + null, |
|
| 787 | + array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))), |
|
| 788 | + 'TXN_ID' |
|
| 789 | + ); |
|
| 790 | + $this->_template_args['previous_transaction'] = $previous_txn |
|
| 791 | + ? $this->_previous_link( |
|
| 792 | + EE_Admin_Page::add_query_args_and_nonce( |
|
| 793 | + array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']), |
|
| 794 | + TXN_ADMIN_URL |
|
| 795 | + ), |
|
| 796 | + 'dashicons dashicons-arrow-left ee-icon-size-22' |
|
| 797 | + ) |
|
| 798 | + : ''; |
|
| 799 | + |
|
| 800 | + // were we just redirected here after adding a new registration ??? |
|
| 801 | + if (isset( |
|
| 802 | + $this->_req_data['redirect_from'], |
|
| 803 | + $this->_req_data['EVT_ID'], |
|
| 804 | + $this->_req_data['event_name'] |
|
| 805 | + )) { |
|
| 806 | + if (EE_Registry::instance()->CAP->current_user_can( |
|
| 807 | + 'ee_edit_registrations', |
|
| 808 | + 'espresso_registrations_new_registration', |
|
| 809 | + $this->_req_data['EVT_ID'] |
|
| 810 | + )) { |
|
| 811 | + $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="'; |
|
| 812 | + $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce( |
|
| 813 | + array( |
|
| 814 | + 'page' => 'espresso_registrations', |
|
| 815 | + 'action' => 'new_registration', |
|
| 816 | + 'return' => 'default', |
|
| 817 | + 'TXN_ID' => $this->_transaction->ID(), |
|
| 818 | + 'event_id' => $this->_req_data['EVT_ID'], |
|
| 819 | + ), |
|
| 820 | + REG_ADMIN_URL |
|
| 821 | + ); |
|
| 822 | + $this->_admin_page_title .= '">'; |
|
| 823 | + |
|
| 824 | + $this->_admin_page_title .= sprintf( |
|
| 825 | + esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'), |
|
| 826 | + htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8') |
|
| 827 | + ); |
|
| 828 | + $this->_admin_page_title .= '</a>'; |
|
| 829 | + } |
|
| 830 | + EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__); |
|
| 831 | + } |
|
| 832 | + // grab messages at the last second |
|
| 833 | + $this->_template_args['notices'] = EE_Error::get_notices(); |
|
| 834 | + // path to template |
|
| 835 | + $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php'; |
|
| 836 | + $this->_template_args['admin_page_header'] = EEH_Template::display_template( |
|
| 837 | + $template_path, |
|
| 838 | + $this->_template_args, |
|
| 839 | + true |
|
| 840 | + ); |
|
| 841 | + |
|
| 842 | + // the details template wrapper |
|
| 843 | + $this->display_admin_page_with_sidebar(); |
|
| 844 | + } |
|
| 845 | + |
|
| 846 | + |
|
| 847 | + /** |
|
| 848 | + * _transaction_details_metaboxes |
|
| 849 | + * |
|
| 850 | + * @access protected |
|
| 851 | + * @return void |
|
| 852 | + * @throws EE_Error |
|
| 853 | + * @throws InvalidArgumentException |
|
| 854 | + * @throws InvalidDataTypeException |
|
| 855 | + * @throws InvalidInterfaceException |
|
| 856 | + * @throws RuntimeException |
|
| 857 | + * @throws ReflectionException |
|
| 858 | + */ |
|
| 859 | + protected function _transaction_details_metaboxes() |
|
| 860 | + { |
|
| 861 | + |
|
| 862 | + $this->_set_transaction_object(); |
|
| 863 | + |
|
| 864 | + if (! $this->_transaction instanceof EE_Transaction) { |
|
| 865 | + return; |
|
| 866 | + } |
|
| 867 | + add_meta_box( |
|
| 868 | + 'edit-txn-details-mbox', |
|
| 869 | + esc_html__('Transaction Details', 'event_espresso'), |
|
| 870 | + array($this, 'txn_details_meta_box'), |
|
| 871 | + $this->_wp_page_slug, |
|
| 872 | + 'normal', |
|
| 873 | + 'high' |
|
| 874 | + ); |
|
| 875 | + add_meta_box( |
|
| 876 | + 'edit-txn-attendees-mbox', |
|
| 877 | + esc_html__('Attendees Registered in this Transaction', 'event_espresso'), |
|
| 878 | + array($this, 'txn_attendees_meta_box'), |
|
| 879 | + $this->_wp_page_slug, |
|
| 880 | + 'normal', |
|
| 881 | + 'high', |
|
| 882 | + array('TXN_ID' => $this->_transaction->ID()) |
|
| 883 | + ); |
|
| 884 | + add_meta_box( |
|
| 885 | + 'edit-txn-registrant-mbox', |
|
| 886 | + esc_html__('Primary Contact', 'event_espresso'), |
|
| 887 | + array($this, 'txn_registrant_side_meta_box'), |
|
| 888 | + $this->_wp_page_slug, |
|
| 889 | + 'side', |
|
| 890 | + 'high' |
|
| 891 | + ); |
|
| 892 | + add_meta_box( |
|
| 893 | + 'edit-txn-billing-info-mbox', |
|
| 894 | + esc_html__('Billing Information', 'event_espresso'), |
|
| 895 | + array($this, 'txn_billing_info_side_meta_box'), |
|
| 896 | + $this->_wp_page_slug, |
|
| 897 | + 'side', |
|
| 898 | + 'high' |
|
| 899 | + ); |
|
| 900 | + } |
|
| 901 | + |
|
| 902 | + |
|
| 903 | + /** |
|
| 904 | + * Callback for transaction actions metabox. |
|
| 905 | + * |
|
| 906 | + * @param EE_Transaction|null $transaction |
|
| 907 | + * @return string |
|
| 908 | + * @throws DomainException |
|
| 909 | + * @throws EE_Error |
|
| 910 | + * @throws InvalidArgumentException |
|
| 911 | + * @throws InvalidDataTypeException |
|
| 912 | + * @throws InvalidInterfaceException |
|
| 913 | + * @throws ReflectionException |
|
| 914 | + * @throws RuntimeException |
|
| 915 | + */ |
|
| 916 | + public function getActionButtons(EE_Transaction $transaction = null) |
|
| 917 | + { |
|
| 918 | + $content = ''; |
|
| 919 | + $actions = array(); |
|
| 920 | + if (! $transaction instanceof EE_Transaction) { |
|
| 921 | + return $content; |
|
| 922 | + } |
|
| 923 | + /** @var EE_Registration $primary_registration */ |
|
| 924 | + $primary_registration = $transaction->primary_registration(); |
|
| 925 | + $attendee = $primary_registration instanceof EE_Registration |
|
| 926 | + ? $primary_registration->attendee() |
|
| 927 | + : null; |
|
| 928 | + |
|
| 929 | + if ($attendee instanceof EE_Attendee |
|
| 930 | + && EE_Registry::instance()->CAP->current_user_can( |
|
| 931 | + 'ee_send_message', |
|
| 932 | + 'espresso_transactions_send_payment_reminder' |
|
| 933 | + ) |
|
| 934 | + ) { |
|
| 935 | + $actions['payment_reminder'] = |
|
| 936 | + EEH_MSG_Template::is_mt_active('payment_reminder') |
|
| 937 | + && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code |
|
| 938 | + && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code |
|
| 939 | + ? EEH_Template::get_button_or_link( |
|
| 940 | + EE_Admin_Page::add_query_args_and_nonce( |
|
| 941 | + array( |
|
| 942 | + 'action' => 'send_payment_reminder', |
|
| 943 | + 'TXN_ID' => $this->_transaction->ID(), |
|
| 944 | + 'redirect_to' => 'view_transaction', |
|
| 945 | + ), |
|
| 946 | + TXN_ADMIN_URL |
|
| 947 | + ), |
|
| 948 | + esc_html__(' Send Payment Reminder', 'event_espresso'), |
|
| 949 | + 'button secondary-button', |
|
| 950 | + 'dashicons dashicons-email-alt' |
|
| 951 | + ) |
|
| 952 | + : ''; |
|
| 953 | + } |
|
| 954 | + |
|
| 955 | + if (EE_Registry::instance()->CAP->current_user_can( |
|
| 956 | + 'ee_edit_payments', |
|
| 957 | + 'espresso_transactions_recalculate_line_items' |
|
| 958 | + ) |
|
| 959 | + ) { |
|
| 960 | + $actions['recalculate_line_items'] = EEH_Template::get_button_or_link( |
|
| 961 | + EE_Admin_Page::add_query_args_and_nonce( |
|
| 962 | + array( |
|
| 963 | + 'action' => 'espresso_recalculate_line_items', |
|
| 964 | + 'TXN_ID' => $this->_transaction->ID(), |
|
| 965 | + 'redirect_to' => 'view_transaction', |
|
| 966 | + ), |
|
| 967 | + TXN_ADMIN_URL |
|
| 968 | + ), |
|
| 969 | + esc_html__(' Recalculate Taxes and Total', 'event_espresso'), |
|
| 970 | + 'button secondary-button', |
|
| 971 | + 'dashicons dashicons-update' |
|
| 972 | + ); |
|
| 973 | + } |
|
| 974 | + |
|
| 975 | + if ($primary_registration instanceof EE_Registration |
|
| 976 | + && EEH_MSG_Template::is_mt_active('receipt') |
|
| 977 | + ) { |
|
| 978 | + $actions['receipt'] = EEH_Template::get_button_or_link( |
|
| 979 | + $primary_registration->receipt_url(), |
|
| 980 | + esc_html__('View Receipt', 'event_espresso'), |
|
| 981 | + 'button secondary-button', |
|
| 982 | + 'dashicons dashicons-media-default' |
|
| 983 | + ); |
|
| 984 | + } |
|
| 985 | + |
|
| 986 | + if ($primary_registration instanceof EE_Registration |
|
| 987 | + && EEH_MSG_Template::is_mt_active('invoice') |
|
| 988 | + ) { |
|
| 989 | + $actions['invoice'] = EEH_Template::get_button_or_link( |
|
| 990 | + $primary_registration->invoice_url(), |
|
| 991 | + esc_html__('View Invoice', 'event_espresso'), |
|
| 992 | + 'button secondary-button', |
|
| 993 | + 'dashicons dashicons-media-spreadsheet' |
|
| 994 | + ); |
|
| 995 | + } |
|
| 996 | + $actions = array_filter( |
|
| 997 | + apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction) |
|
| 998 | + ); |
|
| 999 | + if ($actions) { |
|
| 1000 | + $content = '<ul>'; |
|
| 1001 | + $content .= '<li>' . implode('</li><li>', $actions) . '</li>'; |
|
| 1002 | + $content .= '</uL>'; |
|
| 1003 | + } |
|
| 1004 | + return $content; |
|
| 1005 | + } |
|
| 1006 | + |
|
| 1007 | + |
|
| 1008 | + /** |
|
| 1009 | + * txn_details_meta_box |
|
| 1010 | + * generates HTML for the Transaction main meta box |
|
| 1011 | + * |
|
| 1012 | + * @return void |
|
| 1013 | + * @throws DomainException |
|
| 1014 | + * @throws EE_Error |
|
| 1015 | + * @throws InvalidArgumentException |
|
| 1016 | + * @throws InvalidDataTypeException |
|
| 1017 | + * @throws InvalidInterfaceException |
|
| 1018 | + * @throws RuntimeException |
|
| 1019 | + * @throws ReflectionException |
|
| 1020 | + */ |
|
| 1021 | + public function txn_details_meta_box() |
|
| 1022 | + { |
|
| 1023 | + $this->_set_transaction_object(); |
|
| 1024 | + $this->_template_args['TXN_ID'] = $this->_transaction->ID(); |
|
| 1025 | + $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration |
|
| 1026 | + ? $this->_transaction->primary_registration()->attendee() |
|
| 1027 | + : null; |
|
| 1028 | + $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can( |
|
| 1029 | + 'ee_edit_payments', |
|
| 1030 | + 'apply_payment_or_refund_from_registration_details' |
|
| 1031 | + ); |
|
| 1032 | + $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can( |
|
| 1033 | + 'ee_delete_payments', |
|
| 1034 | + 'delete_payment_from_registration_details' |
|
| 1035 | + ); |
|
| 1036 | + |
|
| 1037 | + // get line table |
|
| 1038 | + EEH_Autoloader::register_line_item_display_autoloaders(); |
|
| 1039 | + $Line_Item_Display = new EE_Line_Item_Display( |
|
| 1040 | + 'admin_table', |
|
| 1041 | + 'EE_Admin_Table_Line_Item_Display_Strategy' |
|
| 1042 | + ); |
|
| 1043 | + $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item( |
|
| 1044 | + $this->_transaction->total_line_item() |
|
| 1045 | + ); |
|
| 1046 | + $this->_template_args['REG_code'] = $this->_transaction->primary_registration()->reg_code(); |
|
| 1047 | + |
|
| 1048 | + // process taxes |
|
| 1049 | + $taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax))); |
|
| 1050 | + $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false; |
|
| 1051 | + |
|
| 1052 | + $this->_template_args['grand_total'] = EEH_Template::format_currency( |
|
| 1053 | + $this->_transaction->total(), |
|
| 1054 | + false, |
|
| 1055 | + false |
|
| 1056 | + ); |
|
| 1057 | + $this->_template_args['grand_raw_total'] = $this->_transaction->total(); |
|
| 1058 | + $this->_template_args['TXN_status'] = $this->_transaction->status_ID(); |
|
| 1059 | + |
|
| 1060 | + // process payment details |
|
| 1061 | + $payments = $this->_transaction->payments(); |
|
| 1062 | + if (! empty($payments)) { |
|
| 1063 | + $this->_template_args['payments'] = $payments; |
|
| 1064 | + $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments); |
|
| 1065 | + } else { |
|
| 1066 | + $this->_template_args['payments'] = false; |
|
| 1067 | + $this->_template_args['existing_reg_payments'] = array(); |
|
| 1068 | + } |
|
| 1069 | + |
|
| 1070 | + $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL); |
|
| 1071 | + $this->_template_args['delete_payment_url'] = add_query_arg( |
|
| 1072 | + array('action' => 'espresso_delete_payment'), |
|
| 1073 | + TXN_ADMIN_URL |
|
| 1074 | + ); |
|
| 1075 | + |
|
| 1076 | + if (isset($txn_details['invoice_number'])) { |
|
| 1077 | + $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code']; |
|
| 1078 | + $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__( |
|
| 1079 | + 'Invoice Number', |
|
| 1080 | + 'event_espresso' |
|
| 1081 | + ); |
|
| 1082 | + } |
|
| 1083 | + |
|
| 1084 | + $this->_template_args['txn_details']['registration_session']['value'] = $this->_transaction |
|
| 1085 | + ->primary_registration() |
|
| 1086 | + ->session_ID(); |
|
| 1087 | + $this->_template_args['txn_details']['registration_session']['label'] = esc_html__( |
|
| 1088 | + 'Registration Session', |
|
| 1089 | + 'event_espresso' |
|
| 1090 | + ); |
|
| 1091 | + |
|
| 1092 | + $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address']) |
|
| 1093 | + ? $this->_session['ip_address'] |
|
| 1094 | + : ''; |
|
| 1095 | + $this->_template_args['txn_details']['ip_address']['label'] = esc_html__( |
|
| 1096 | + 'Transaction placed from IP', |
|
| 1097 | + 'event_espresso' |
|
| 1098 | + ); |
|
| 1099 | + |
|
| 1100 | + $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent']) |
|
| 1101 | + ? $this->_session['user_agent'] |
|
| 1102 | + : ''; |
|
| 1103 | + $this->_template_args['txn_details']['user_agent']['label'] = esc_html__( |
|
| 1104 | + 'Registrant User Agent', |
|
| 1105 | + 'event_espresso' |
|
| 1106 | + ); |
|
| 1107 | + |
|
| 1108 | + $reg_steps = '<ul>'; |
|
| 1109 | + foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) { |
|
| 1110 | + if ($reg_step_status === true) { |
|
| 1111 | + $reg_steps .= '<li style="color:#70cc50">' |
|
| 1112 | + . sprintf( |
|
| 1113 | + esc_html__('%1$s : Completed', 'event_espresso'), |
|
| 1114 | + ucwords(str_replace('_', ' ', $reg_step)) |
|
| 1115 | + ) |
|
| 1116 | + . '</li>'; |
|
| 1117 | + } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) { |
|
| 1118 | + $reg_steps .= '<li style="color:#2EA2CC">' |
|
| 1119 | + . sprintf( |
|
| 1120 | + esc_html__('%1$s : Initiated %2$s', 'event_espresso'), |
|
| 1121 | + ucwords(str_replace('_', ' ', $reg_step)), |
|
| 1122 | + date( |
|
| 1123 | + get_option('date_format') . ' ' . get_option('time_format'), |
|
| 1124 | + $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS) |
|
| 1125 | + ) |
|
| 1126 | + ) |
|
| 1127 | + . '</li>'; |
|
| 1128 | + } else { |
|
| 1129 | + $reg_steps .= '<li style="color:#E76700">' |
|
| 1130 | + . sprintf( |
|
| 1131 | + esc_html__('%1$s : Never Initiated', 'event_espresso'), |
|
| 1132 | + ucwords(str_replace('_', ' ', $reg_step)) |
|
| 1133 | + ) |
|
| 1134 | + . '</li>'; |
|
| 1135 | + } |
|
| 1136 | + } |
|
| 1137 | + $reg_steps .= '</ul>'; |
|
| 1138 | + $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps; |
|
| 1139 | + $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__( |
|
| 1140 | + 'Registration Step Progress', |
|
| 1141 | + 'event_espresso' |
|
| 1142 | + ); |
|
| 1143 | + |
|
| 1144 | + |
|
| 1145 | + $this->_get_registrations_to_apply_payment_to(); |
|
| 1146 | + $this->_get_payment_methods($payments); |
|
| 1147 | + $this->_get_payment_status_array(); |
|
| 1148 | + $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction. |
|
| 1149 | + |
|
| 1150 | + $this->_template_args['transaction_form_url'] = add_query_arg( |
|
| 1151 | + array( |
|
| 1152 | + 'action' => 'edit_transaction', |
|
| 1153 | + 'process' => 'transaction', |
|
| 1154 | + ), |
|
| 1155 | + TXN_ADMIN_URL |
|
| 1156 | + ); |
|
| 1157 | + $this->_template_args['apply_payment_form_url'] = add_query_arg( |
|
| 1158 | + array( |
|
| 1159 | + 'page' => 'espresso_transactions', |
|
| 1160 | + 'action' => 'espresso_apply_payment', |
|
| 1161 | + ), |
|
| 1162 | + WP_AJAX_URL |
|
| 1163 | + ); |
|
| 1164 | + $this->_template_args['delete_payment_form_url'] = add_query_arg( |
|
| 1165 | + array( |
|
| 1166 | + 'page' => 'espresso_transactions', |
|
| 1167 | + 'action' => 'espresso_delete_payment', |
|
| 1168 | + ), |
|
| 1169 | + WP_AJAX_URL |
|
| 1170 | + ); |
|
| 1171 | + |
|
| 1172 | + $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction); |
|
| 1173 | + |
|
| 1174 | + // 'espresso_delete_payment_nonce' |
|
| 1175 | + |
|
| 1176 | + $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php'; |
|
| 1177 | + echo EEH_Template::display_template($template_path, $this->_template_args, true); |
|
| 1178 | + } |
|
| 1179 | + |
|
| 1180 | + |
|
| 1181 | + /** |
|
| 1182 | + * _get_registration_payment_IDs |
|
| 1183 | + * generates an array of Payment IDs and their corresponding Registration IDs |
|
| 1184 | + * |
|
| 1185 | + * @access protected |
|
| 1186 | + * @param EE_Payment[] $payments |
|
| 1187 | + * @return array |
|
| 1188 | + * @throws EE_Error |
|
| 1189 | + * @throws InvalidArgumentException |
|
| 1190 | + * @throws InvalidDataTypeException |
|
| 1191 | + * @throws InvalidInterfaceException |
|
| 1192 | + * @throws ReflectionException |
|
| 1193 | + */ |
|
| 1194 | + protected function _get_registration_payment_IDs($payments = array()) |
|
| 1195 | + { |
|
| 1196 | + $existing_reg_payments = array(); |
|
| 1197 | + // get all reg payments for these payments |
|
| 1198 | + $reg_payments = EEM_Registration_Payment::instance()->get_all( |
|
| 1199 | + array( |
|
| 1200 | + array( |
|
| 1201 | + 'PAY_ID' => array( |
|
| 1202 | + 'IN', |
|
| 1203 | + array_keys($payments), |
|
| 1204 | + ), |
|
| 1205 | + ), |
|
| 1206 | + ) |
|
| 1207 | + ); |
|
| 1208 | + if (! empty($reg_payments)) { |
|
| 1209 | + foreach ($payments as $payment) { |
|
| 1210 | + if (! $payment instanceof EE_Payment) { |
|
| 1211 | + continue; |
|
| 1212 | + } elseif (! isset($existing_reg_payments[ $payment->ID() ])) { |
|
| 1213 | + $existing_reg_payments[ $payment->ID() ] = array(); |
|
| 1214 | + } |
|
| 1215 | + foreach ($reg_payments as $reg_payment) { |
|
| 1216 | + if ($reg_payment instanceof EE_Registration_Payment |
|
| 1217 | + && $reg_payment->payment_ID() === $payment->ID() |
|
| 1218 | + ) { |
|
| 1219 | + $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID(); |
|
| 1220 | + } |
|
| 1221 | + } |
|
| 1222 | + } |
|
| 1223 | + } |
|
| 1224 | + |
|
| 1225 | + return $existing_reg_payments; |
|
| 1226 | + } |
|
| 1227 | + |
|
| 1228 | + |
|
| 1229 | + /** |
|
| 1230 | + * _get_registrations_to_apply_payment_to |
|
| 1231 | + * generates HTML for displaying a series of checkboxes in the admin payment modal window |
|
| 1232 | + * which allows the admin to only apply the payment to the specific registrations |
|
| 1233 | + * |
|
| 1234 | + * @access protected |
|
| 1235 | + * @return void |
|
| 1236 | + * @throws EE_Error |
|
| 1237 | + * @throws InvalidArgumentException |
|
| 1238 | + * @throws InvalidDataTypeException |
|
| 1239 | + * @throws InvalidInterfaceException |
|
| 1240 | + * @throws ReflectionException |
|
| 1241 | + */ |
|
| 1242 | + protected function _get_registrations_to_apply_payment_to() |
|
| 1243 | + { |
|
| 1244 | + // we want any registration with an active status (ie: not deleted or cancelled) |
|
| 1245 | + $query_params = array( |
|
| 1246 | + array( |
|
| 1247 | + 'STS_ID' => array( |
|
| 1248 | + 'IN', |
|
| 1249 | + array( |
|
| 1250 | + EEM_Registration::status_id_approved, |
|
| 1251 | + EEM_Registration::status_id_pending_payment, |
|
| 1252 | + EEM_Registration::status_id_not_approved, |
|
| 1253 | + ), |
|
| 1254 | + ), |
|
| 1255 | + ), |
|
| 1256 | + ); |
|
| 1257 | + $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div( |
|
| 1258 | + '', |
|
| 1259 | + 'txn-admin-apply-payment-to-registrations-dv', |
|
| 1260 | + '', |
|
| 1261 | + 'clear: both; margin: 1.5em 0 0; display: none;' |
|
| 1262 | + ); |
|
| 1263 | + $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap'); |
|
| 1264 | + $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl'); |
|
| 1265 | + $registrations_to_apply_payment_to .= EEH_HTML::thead( |
|
| 1266 | + EEH_HTML::tr( |
|
| 1267 | + EEH_HTML::th(esc_html__('ID', 'event_espresso')) . |
|
| 1268 | + EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) . |
|
| 1269 | + EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) . |
|
| 1270 | + EEH_HTML::th(esc_html__('Event', 'event_espresso')) . |
|
| 1271 | + EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') . |
|
| 1272 | + EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') . |
|
| 1273 | + EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr') |
|
| 1274 | + ) |
|
| 1275 | + ); |
|
| 1276 | + $registrations_to_apply_payment_to .= EEH_HTML::tbody(); |
|
| 1277 | + // get registrations for TXN |
|
| 1278 | + $registrations = $this->_transaction->registrations($query_params); |
|
| 1279 | + $existing_reg_payments = $this->_template_args['existing_reg_payments']; |
|
| 1280 | + foreach ($registrations as $registration) { |
|
| 1281 | + if ($registration instanceof EE_Registration) { |
|
| 1282 | + $attendee_name = $registration->attendee() instanceof EE_Attendee |
|
| 1283 | + ? $registration->attendee()->full_name() |
|
| 1284 | + : esc_html__('Unknown Attendee', 'event_espresso'); |
|
| 1285 | + $owing = $registration->final_price() - $registration->paid(); |
|
| 1286 | + $taxable = $registration->ticket()->taxable() |
|
| 1287 | + ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>' |
|
| 1288 | + : ''; |
|
| 1289 | + $checked = empty($existing_reg_payments) |
|
| 1290 | + || in_array($registration->ID(), $existing_reg_payments, true) |
|
| 1291 | + ? ' checked="checked"' |
|
| 1292 | + : ''; |
|
| 1293 | + $disabled = $registration->final_price() > 0 ? '' : ' disabled'; |
|
| 1294 | + $registrations_to_apply_payment_to .= EEH_HTML::tr( |
|
| 1295 | + EEH_HTML::td($registration->ID()) . |
|
| 1296 | + EEH_HTML::td($attendee_name) . |
|
| 1297 | + EEH_HTML::td( |
|
| 1298 | + $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable |
|
| 1299 | + ) . |
|
| 1300 | + EEH_HTML::td($registration->event_name()) . |
|
| 1301 | + EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') . |
|
| 1302 | + EEH_HTML::td( |
|
| 1303 | + EEH_Template::format_currency($owing), |
|
| 1304 | + '', |
|
| 1305 | + 'txn-admin-payment-owing-td jst-cntr' |
|
| 1306 | + ) . |
|
| 1307 | + EEH_HTML::td( |
|
| 1308 | + '<input type="checkbox" value="' . $registration->ID() |
|
| 1309 | + . '" name="txn_admin_payment[registrations]"' |
|
| 1310 | + . $checked . $disabled . '>', |
|
| 1311 | + '', |
|
| 1312 | + 'jst-cntr' |
|
| 1313 | + ), |
|
| 1314 | + 'apply-payment-registration-row-' . $registration->ID() |
|
| 1315 | + ); |
|
| 1316 | + } |
|
| 1317 | + } |
|
| 1318 | + $registrations_to_apply_payment_to .= EEH_HTML::tbodyx(); |
|
| 1319 | + $registrations_to_apply_payment_to .= EEH_HTML::tablex(); |
|
| 1320 | + $registrations_to_apply_payment_to .= EEH_HTML::divx(); |
|
| 1321 | + $registrations_to_apply_payment_to .= EEH_HTML::p( |
|
| 1322 | + esc_html__( |
|
| 1323 | + 'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.', |
|
| 1324 | + 'event_espresso' |
|
| 1325 | + ), |
|
| 1326 | + '', |
|
| 1327 | + 'clear description' |
|
| 1328 | + ); |
|
| 1329 | + $registrations_to_apply_payment_to .= EEH_HTML::divx(); |
|
| 1330 | + $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to; |
|
| 1331 | + } |
|
| 1332 | + |
|
| 1333 | + |
|
| 1334 | + /** |
|
| 1335 | + * _get_reg_status_selection |
|
| 1336 | + * |
|
| 1337 | + * @todo this will need to be adjusted either once MER comes along OR we move default reg status to tickets |
|
| 1338 | + * instead of events. |
|
| 1339 | + * @access protected |
|
| 1340 | + * @return void |
|
| 1341 | + * @throws EE_Error |
|
| 1342 | + */ |
|
| 1343 | + protected function _get_reg_status_selection() |
|
| 1344 | + { |
|
| 1345 | + // first get all possible statuses |
|
| 1346 | + $statuses = EEM_Registration::reg_status_array(array(), true); |
|
| 1347 | + // let's add a "don't change" option. |
|
| 1348 | + $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso'); |
|
| 1349 | + $status_array = array_merge($status_array, $statuses); |
|
| 1350 | + $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input( |
|
| 1351 | + 'txn_reg_status_change[reg_status]', |
|
| 1352 | + $status_array, |
|
| 1353 | + 'NAN', |
|
| 1354 | + 'id="txn-admin-payment-reg-status-inp"', |
|
| 1355 | + 'txn-reg-status-change-reg-status' |
|
| 1356 | + ); |
|
| 1357 | + $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input( |
|
| 1358 | + 'delete_txn_reg_status_change[reg_status]', |
|
| 1359 | + $status_array, |
|
| 1360 | + 'NAN', |
|
| 1361 | + 'delete-txn-admin-payment-reg-status-inp', |
|
| 1362 | + 'delete-txn-reg-status-change-reg-status' |
|
| 1363 | + ); |
|
| 1364 | + } |
|
| 1365 | + |
|
| 1366 | + |
|
| 1367 | + /** |
|
| 1368 | + * _get_payment_methods |
|
| 1369 | + * Gets all the payment methods available generally, or the ones that are already |
|
| 1370 | + * selected on these payments (in case their payment methods are no longer active). |
|
| 1371 | + * Has the side-effect of updating the template args' payment_methods item |
|
| 1372 | + * |
|
| 1373 | + * @access private |
|
| 1374 | + * @param EE_Payment[] to show on this page |
|
| 1375 | + * @return void |
|
| 1376 | + * @throws EE_Error |
|
| 1377 | + * @throws InvalidArgumentException |
|
| 1378 | + * @throws InvalidDataTypeException |
|
| 1379 | + * @throws InvalidInterfaceException |
|
| 1380 | + * @throws ReflectionException |
|
| 1381 | + */ |
|
| 1382 | + private function _get_payment_methods($payments = array()) |
|
| 1383 | + { |
|
| 1384 | + $payment_methods_of_payments = array(); |
|
| 1385 | + foreach ($payments as $payment) { |
|
| 1386 | + if ($payment instanceof EE_Payment) { |
|
| 1387 | + $payment_methods_of_payments[] = $payment->ID(); |
|
| 1388 | + } |
|
| 1389 | + } |
|
| 1390 | + if ($payment_methods_of_payments) { |
|
| 1391 | + $query_args = array( |
|
| 1392 | + array( |
|
| 1393 | + 'OR*payment_method_for_payment' => array( |
|
| 1394 | + 'PMD_ID' => array('IN', $payment_methods_of_payments), |
|
| 1395 | + 'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'), |
|
| 1396 | + ), |
|
| 1397 | + ), |
|
| 1398 | + ); |
|
| 1399 | + } else { |
|
| 1400 | + $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'))); |
|
| 1401 | + } |
|
| 1402 | + $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args); |
|
| 1403 | + } |
|
| 1404 | + |
|
| 1405 | + |
|
| 1406 | + /** |
|
| 1407 | + * txn_attendees_meta_box |
|
| 1408 | + * generates HTML for the Attendees Transaction main meta box |
|
| 1409 | + * |
|
| 1410 | + * @access public |
|
| 1411 | + * @param WP_Post $post |
|
| 1412 | + * @param array $metabox |
|
| 1413 | + * @return void |
|
| 1414 | + * @throws DomainException |
|
| 1415 | + * @throws EE_Error |
|
| 1416 | + * @throws InvalidArgumentException |
|
| 1417 | + * @throws InvalidDataTypeException |
|
| 1418 | + * @throws InvalidInterfaceException |
|
| 1419 | + * @throws ReflectionException |
|
| 1420 | + */ |
|
| 1421 | + public function txn_attendees_meta_box($post, $metabox = array('args' => array())) |
|
| 1422 | + { |
|
| 1423 | + |
|
| 1424 | + /** @noinspection NonSecureExtractUsageInspection */ |
|
| 1425 | + extract($metabox['args']); |
|
| 1426 | + $this->_template_args['post'] = $post; |
|
| 1427 | + $this->_template_args['event_attendees'] = array(); |
|
| 1428 | + // process items in cart |
|
| 1429 | + $line_items = $this->_transaction->get_many_related( |
|
| 1430 | + 'Line_Item', |
|
| 1431 | + array(array('LIN_type' => 'line-item')) |
|
| 1432 | + ); |
|
| 1433 | + if (! empty($line_items)) { |
|
| 1434 | + foreach ($line_items as $item) { |
|
| 1435 | + if ($item instanceof EE_Line_Item) { |
|
| 1436 | + switch ($item->OBJ_type()) { |
|
| 1437 | + case 'Event': |
|
| 1438 | + break; |
|
| 1439 | + case 'Ticket': |
|
| 1440 | + $ticket = $item->ticket(); |
|
| 1441 | + // right now we're only handling tickets here. |
|
| 1442 | + // Cause its expected that only tickets will have attendees right? |
|
| 1443 | + if (! $ticket instanceof EE_Ticket) { |
|
| 1444 | + break; |
|
| 1445 | + } |
|
| 1446 | + try { |
|
| 1447 | + $event_name = $ticket->get_event_name(); |
|
| 1448 | + } catch (Exception $e) { |
|
| 1449 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
| 1450 | + $event_name = esc_html__('Unknown Event', 'event_espresso'); |
|
| 1451 | + } |
|
| 1452 | + $event_name .= ' - ' . $item->name(); |
|
| 1453 | + $ticket_price = EEH_Template::format_currency($item->unit_price()); |
|
| 1454 | + // now get all of the registrations for this transaction that use this ticket |
|
| 1455 | + $registrations = $ticket->registrations( |
|
| 1456 | + array(array('TXN_ID' => $this->_transaction->ID())) |
|
| 1457 | + ); |
|
| 1458 | + foreach ($registrations as $registration) { |
|
| 1459 | + if (! $registration instanceof EE_Registration) { |
|
| 1460 | + break; |
|
| 1461 | + } |
|
| 1462 | + $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID'] |
|
| 1463 | + = $registration->status_ID(); |
|
| 1464 | + $this->_template_args['event_attendees'][ $registration->ID() ]['att_num'] |
|
| 1465 | + = $registration->count(); |
|
| 1466 | + $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name'] |
|
| 1467 | + = $event_name; |
|
| 1468 | + $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price'] |
|
| 1469 | + = $ticket_price; |
|
| 1470 | + // attendee info |
|
| 1471 | + $attendee = $registration->get_first_related('Attendee'); |
|
| 1472 | + if ($attendee instanceof EE_Attendee) { |
|
| 1473 | + $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] |
|
| 1474 | + = $attendee->ID(); |
|
| 1475 | + $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] |
|
| 1476 | + = $attendee->full_name(); |
|
| 1477 | + $this->_template_args['event_attendees'][ $registration->ID() ]['email'] |
|
| 1478 | + = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name |
|
| 1479 | + . esc_html__( |
|
| 1480 | + ' Event', |
|
| 1481 | + 'event_espresso' |
|
| 1482 | + ) |
|
| 1483 | + . '">' . $attendee->email() . '</a>'; |
|
| 1484 | + $this->_template_args['event_attendees'][ $registration->ID() ]['address'] |
|
| 1485 | + = EEH_Address::format($attendee, 'inline', false, false); |
|
| 1486 | + } else { |
|
| 1487 | + $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = ''; |
|
| 1488 | + $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = ''; |
|
| 1489 | + $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = ''; |
|
| 1490 | + $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = ''; |
|
| 1491 | + } |
|
| 1492 | + } |
|
| 1493 | + break; |
|
| 1494 | + } |
|
| 1495 | + } |
|
| 1496 | + } |
|
| 1497 | + |
|
| 1498 | + $this->_template_args['transaction_form_url'] = add_query_arg( |
|
| 1499 | + array( |
|
| 1500 | + 'action' => 'edit_transaction', |
|
| 1501 | + 'process' => 'attendees', |
|
| 1502 | + ), |
|
| 1503 | + TXN_ADMIN_URL |
|
| 1504 | + ); |
|
| 1505 | + echo EEH_Template::display_template( |
|
| 1506 | + TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php', |
|
| 1507 | + $this->_template_args, |
|
| 1508 | + true |
|
| 1509 | + ); |
|
| 1510 | + } else { |
|
| 1511 | + echo sprintf( |
|
| 1512 | + esc_html__( |
|
| 1513 | + '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s', |
|
| 1514 | + 'event_espresso' |
|
| 1515 | + ), |
|
| 1516 | + '<p class="important-notice">', |
|
| 1517 | + '</p>' |
|
| 1518 | + ); |
|
| 1519 | + } |
|
| 1520 | + } |
|
| 1521 | + |
|
| 1522 | + |
|
| 1523 | + /** |
|
| 1524 | + * txn_registrant_side_meta_box |
|
| 1525 | + * generates HTML for the Edit Transaction side meta box |
|
| 1526 | + * |
|
| 1527 | + * @access public |
|
| 1528 | + * @return void |
|
| 1529 | + * @throws DomainException |
|
| 1530 | + * @throws EE_Error |
|
| 1531 | + * @throws InvalidArgumentException |
|
| 1532 | + * @throws InvalidDataTypeException |
|
| 1533 | + * @throws InvalidInterfaceException |
|
| 1534 | + * @throws ReflectionException |
|
| 1535 | + */ |
|
| 1536 | + public function txn_registrant_side_meta_box() |
|
| 1537 | + { |
|
| 1538 | + $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration |
|
| 1539 | + ? $this->_transaction->primary_registration()->get_first_related('Attendee') |
|
| 1540 | + : null; |
|
| 1541 | + if (! $primary_att instanceof EE_Attendee) { |
|
| 1542 | + $this->_template_args['no_attendee_message'] = esc_html__( |
|
| 1543 | + 'There is no attached contact for this transaction. The transaction either failed due to an error or was abandoned.', |
|
| 1544 | + 'event_espresso' |
|
| 1545 | + ); |
|
| 1546 | + $primary_att = EEM_Attendee::instance()->create_default_object(); |
|
| 1547 | + } |
|
| 1548 | + $this->_template_args['ATT_ID'] = $primary_att->ID(); |
|
| 1549 | + $this->_template_args['prime_reg_fname'] = $primary_att->fname(); |
|
| 1550 | + $this->_template_args['prime_reg_lname'] = $primary_att->lname(); |
|
| 1551 | + $this->_template_args['prime_reg_email'] = $primary_att->email(); |
|
| 1552 | + $this->_template_args['prime_reg_phone'] = $primary_att->phone(); |
|
| 1553 | + $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
| 1554 | + array( |
|
| 1555 | + 'action' => 'edit_attendee', |
|
| 1556 | + 'post' => $primary_att->ID(), |
|
| 1557 | + ), |
|
| 1558 | + REG_ADMIN_URL |
|
| 1559 | + ); |
|
| 1560 | + // get formatted address for registrant |
|
| 1561 | + $this->_template_args['formatted_address'] = EEH_Address::format($primary_att); |
|
| 1562 | + echo EEH_Template::display_template( |
|
| 1563 | + TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php', |
|
| 1564 | + $this->_template_args, |
|
| 1565 | + true |
|
| 1566 | + ); |
|
| 1567 | + } |
|
| 1568 | + |
|
| 1569 | + |
|
| 1570 | + /** |
|
| 1571 | + * txn_billing_info_side_meta_box |
|
| 1572 | + * generates HTML for the Edit Transaction side meta box |
|
| 1573 | + * |
|
| 1574 | + * @access public |
|
| 1575 | + * @return void |
|
| 1576 | + * @throws DomainException |
|
| 1577 | + * @throws EE_Error |
|
| 1578 | + */ |
|
| 1579 | + public function txn_billing_info_side_meta_box() |
|
| 1580 | + { |
|
| 1581 | + |
|
| 1582 | + $this->_template_args['billing_form'] = $this->_transaction->billing_info(); |
|
| 1583 | + $this->_template_args['billing_form_url'] = add_query_arg( |
|
| 1584 | + array('action' => 'edit_transaction', 'process' => 'billing'), |
|
| 1585 | + TXN_ADMIN_URL |
|
| 1586 | + ); |
|
| 1587 | + |
|
| 1588 | + $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php'; |
|
| 1589 | + echo EEH_Template::display_template($template_path, $this->_template_args, true); |
|
| 1590 | + } |
|
| 1591 | + |
|
| 1592 | + |
|
| 1593 | + /** |
|
| 1594 | + * apply_payments_or_refunds |
|
| 1595 | + * registers a payment or refund made towards a transaction |
|
| 1596 | + * |
|
| 1597 | + * @access public |
|
| 1598 | + * @return void |
|
| 1599 | + * @throws EE_Error |
|
| 1600 | + * @throws InvalidArgumentException |
|
| 1601 | + * @throws ReflectionException |
|
| 1602 | + * @throws RuntimeException |
|
| 1603 | + * @throws InvalidDataTypeException |
|
| 1604 | + * @throws InvalidInterfaceException |
|
| 1605 | + */ |
|
| 1606 | + public function apply_payments_or_refunds() |
|
| 1607 | + { |
|
| 1608 | + $json_response_data = array('return_data' => false); |
|
| 1609 | + $valid_data = $this->_validate_payment_request_data(); |
|
| 1610 | + $has_access = EE_Registry::instance()->CAP->current_user_can( |
|
| 1611 | + 'ee_edit_payments', |
|
| 1612 | + 'apply_payment_or_refund_from_registration_details' |
|
| 1613 | + ); |
|
| 1614 | + if (! empty($valid_data) && $has_access) { |
|
| 1615 | + $PAY_ID = $valid_data['PAY_ID']; |
|
| 1616 | + // save the new payment |
|
| 1617 | + $payment = $this->_create_payment_from_request_data($valid_data); |
|
| 1618 | + // get the TXN for this payment |
|
| 1619 | + $transaction = $payment->transaction(); |
|
| 1620 | + // verify transaction |
|
| 1621 | + if ($transaction instanceof EE_Transaction) { |
|
| 1622 | + // calculate_total_payments_and_update_status |
|
| 1623 | + $this->_process_transaction_payments($transaction); |
|
| 1624 | + $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment); |
|
| 1625 | + $this->_remove_existing_registration_payments($payment, $PAY_ID); |
|
| 1626 | + // apply payment to registrations (if applicable) |
|
| 1627 | + if (! empty($REG_IDs)) { |
|
| 1628 | + $this->_update_registration_payments($transaction, $payment, $REG_IDs); |
|
| 1629 | + $this->_maybe_send_notifications(); |
|
| 1630 | + // now process status changes for the same registrations |
|
| 1631 | + $this->_process_registration_status_change($transaction, $REG_IDs); |
|
| 1632 | + } |
|
| 1633 | + $this->_maybe_send_notifications($payment); |
|
| 1634 | + // prepare to render page |
|
| 1635 | + $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs); |
|
| 1636 | + do_action( |
|
| 1637 | + 'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording', |
|
| 1638 | + $transaction, |
|
| 1639 | + $payment |
|
| 1640 | + ); |
|
| 1641 | + } else { |
|
| 1642 | + EE_Error::add_error( |
|
| 1643 | + esc_html__( |
|
| 1644 | + 'A valid Transaction for this payment could not be retrieved.', |
|
| 1645 | + 'event_espresso' |
|
| 1646 | + ), |
|
| 1647 | + __FILE__, |
|
| 1648 | + __FUNCTION__, |
|
| 1649 | + __LINE__ |
|
| 1650 | + ); |
|
| 1651 | + } |
|
| 1652 | + } elseif ($has_access) { |
|
| 1653 | + EE_Error::add_error( |
|
| 1654 | + esc_html__( |
|
| 1655 | + 'The payment form data could not be processed. Please try again.', |
|
| 1656 | + 'event_espresso' |
|
| 1657 | + ), |
|
| 1658 | + __FILE__, |
|
| 1659 | + __FUNCTION__, |
|
| 1660 | + __LINE__ |
|
| 1661 | + ); |
|
| 1662 | + } else { |
|
| 1663 | + EE_Error::add_error( |
|
| 1664 | + esc_html__( |
|
| 1665 | + 'You do not have access to apply payments or refunds to a registration.', |
|
| 1666 | + 'event_espresso' |
|
| 1667 | + ), |
|
| 1668 | + __FILE__, |
|
| 1669 | + __FUNCTION__, |
|
| 1670 | + __LINE__ |
|
| 1671 | + ); |
|
| 1672 | + } |
|
| 1673 | + $notices = EE_Error::get_notices( |
|
| 1674 | + false, |
|
| 1675 | + false, |
|
| 1676 | + false |
|
| 1677 | + ); |
|
| 1678 | + $this->_template_args = array( |
|
| 1679 | + 'data' => $json_response_data, |
|
| 1680 | + 'error' => $notices['errors'], |
|
| 1681 | + 'success' => $notices['success'], |
|
| 1682 | + ); |
|
| 1683 | + $this->_return_json(); |
|
| 1684 | + } |
|
| 1685 | + |
|
| 1686 | + |
|
| 1687 | + /** |
|
| 1688 | + * _validate_payment_request_data |
|
| 1689 | + * |
|
| 1690 | + * @return array |
|
| 1691 | + * @throws EE_Error |
|
| 1692 | + * @throws InvalidArgumentException |
|
| 1693 | + * @throws InvalidDataTypeException |
|
| 1694 | + * @throws InvalidInterfaceException |
|
| 1695 | + */ |
|
| 1696 | + protected function _validate_payment_request_data() |
|
| 1697 | + { |
|
| 1698 | + if (! isset($this->_req_data['txn_admin_payment'])) { |
|
| 1699 | + return array(); |
|
| 1700 | + } |
|
| 1701 | + $payment_form = $this->_generate_payment_form_section(); |
|
| 1702 | + try { |
|
| 1703 | + if ($payment_form->was_submitted()) { |
|
| 1704 | + $payment_form->receive_form_submission(); |
|
| 1705 | + if (! $payment_form->is_valid()) { |
|
| 1706 | + $submission_error_messages = array(); |
|
| 1707 | + foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) { |
|
| 1708 | + if ($validation_error instanceof EE_Validation_Error) { |
|
| 1709 | + $submission_error_messages[] = sprintf( |
|
| 1710 | + _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'), |
|
| 1711 | + $validation_error->get_form_section()->html_label_text(), |
|
| 1712 | + $validation_error->getMessage() |
|
| 1713 | + ); |
|
| 1714 | + } |
|
| 1715 | + } |
|
| 1716 | + EE_Error::add_error( |
|
| 1717 | + implode('<br />', $submission_error_messages), |
|
| 1718 | + __FILE__, |
|
| 1719 | + __FUNCTION__, |
|
| 1720 | + __LINE__ |
|
| 1721 | + ); |
|
| 1722 | + return array(); |
|
| 1723 | + } |
|
| 1724 | + } |
|
| 1725 | + } catch (EE_Error $e) { |
|
| 1726 | + EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__); |
|
| 1727 | + return array(); |
|
| 1728 | + } |
|
| 1729 | + |
|
| 1730 | + return $payment_form->valid_data(); |
|
| 1731 | + } |
|
| 1732 | + |
|
| 1733 | + |
|
| 1734 | + /** |
|
| 1735 | + * _generate_payment_form_section |
|
| 1736 | + * |
|
| 1737 | + * @return EE_Form_Section_Proper |
|
| 1738 | + * @throws EE_Error |
|
| 1739 | + */ |
|
| 1740 | + protected function _generate_payment_form_section() |
|
| 1741 | + { |
|
| 1742 | + return new EE_Form_Section_Proper( |
|
| 1743 | + array( |
|
| 1744 | + 'name' => 'txn_admin_payment', |
|
| 1745 | + 'subsections' => array( |
|
| 1746 | + 'PAY_ID' => new EE_Text_Input( |
|
| 1747 | + array( |
|
| 1748 | + 'default' => 0, |
|
| 1749 | + 'required' => false, |
|
| 1750 | + 'html_label_text' => esc_html__('Payment ID', 'event_espresso'), |
|
| 1751 | + 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1752 | + ) |
|
| 1753 | + ), |
|
| 1754 | + 'TXN_ID' => new EE_Text_Input( |
|
| 1755 | + array( |
|
| 1756 | + 'default' => 0, |
|
| 1757 | + 'required' => true, |
|
| 1758 | + 'html_label_text' => esc_html__('Transaction ID', 'event_espresso'), |
|
| 1759 | + 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1760 | + ) |
|
| 1761 | + ), |
|
| 1762 | + 'type' => new EE_Text_Input( |
|
| 1763 | + array( |
|
| 1764 | + 'default' => 1, |
|
| 1765 | + 'required' => true, |
|
| 1766 | + 'html_label_text' => esc_html__('Payment or Refund', 'event_espresso'), |
|
| 1767 | + 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1768 | + ) |
|
| 1769 | + ), |
|
| 1770 | + 'amount' => new EE_Text_Input( |
|
| 1771 | + array( |
|
| 1772 | + 'default' => 0, |
|
| 1773 | + 'required' => true, |
|
| 1774 | + 'html_label_text' => esc_html__('Payment amount', 'event_espresso'), |
|
| 1775 | + 'validation_strategies' => array(new EE_Float_Normalization()), |
|
| 1776 | + ) |
|
| 1777 | + ), |
|
| 1778 | + 'status' => new EE_Text_Input( |
|
| 1779 | + array( |
|
| 1780 | + 'default' => EEM_Payment::status_id_approved, |
|
| 1781 | + 'required' => true, |
|
| 1782 | + 'html_label_text' => esc_html__('Payment status', 'event_espresso'), |
|
| 1783 | + ) |
|
| 1784 | + ), |
|
| 1785 | + 'PMD_ID' => new EE_Text_Input( |
|
| 1786 | + array( |
|
| 1787 | + 'default' => 2, |
|
| 1788 | + 'required' => true, |
|
| 1789 | + 'html_label_text' => esc_html__('Payment Method', 'event_espresso'), |
|
| 1790 | + 'validation_strategies' => array(new EE_Int_Normalization()), |
|
| 1791 | + ) |
|
| 1792 | + ), |
|
| 1793 | + 'date' => new EE_Text_Input( |
|
| 1794 | + array( |
|
| 1795 | + 'default' => time(), |
|
| 1796 | + 'required' => true, |
|
| 1797 | + 'html_label_text' => esc_html__('Payment date', 'event_espresso'), |
|
| 1798 | + ) |
|
| 1799 | + ), |
|
| 1800 | + 'txn_id_chq_nmbr' => new EE_Text_Input( |
|
| 1801 | + array( |
|
| 1802 | + 'default' => '', |
|
| 1803 | + 'required' => false, |
|
| 1804 | + 'html_label_text' => esc_html__('Transaction or Cheque Number', 'event_espresso'), |
|
| 1805 | + 'validation_strategies' => array( |
|
| 1806 | + new EE_Max_Length_Validation_Strategy( |
|
| 1807 | + esc_html__('Input too long', 'event_espresso'), |
|
| 1808 | + 100 |
|
| 1809 | + ), |
|
| 1810 | + ), |
|
| 1811 | + ) |
|
| 1812 | + ), |
|
| 1813 | + 'po_number' => new EE_Text_Input( |
|
| 1814 | + array( |
|
| 1815 | + 'default' => '', |
|
| 1816 | + 'required' => false, |
|
| 1817 | + 'html_label_text' => esc_html__('Purchase Order Number', 'event_espresso'), |
|
| 1818 | + 'validation_strategies' => array( |
|
| 1819 | + new EE_Max_Length_Validation_Strategy( |
|
| 1820 | + esc_html__('Input too long', 'event_espresso'), |
|
| 1821 | + 100 |
|
| 1822 | + ), |
|
| 1823 | + ), |
|
| 1824 | + ) |
|
| 1825 | + ), |
|
| 1826 | + 'accounting' => new EE_Text_Input( |
|
| 1827 | + array( |
|
| 1828 | + 'default' => '', |
|
| 1829 | + 'required' => false, |
|
| 1830 | + 'html_label_text' => esc_html__('Extra Field for Accounting', 'event_espresso'), |
|
| 1831 | + 'validation_strategies' => array( |
|
| 1832 | + new EE_Max_Length_Validation_Strategy( |
|
| 1833 | + esc_html__('Input too long', 'event_espresso'), |
|
| 1834 | + 100 |
|
| 1835 | + ), |
|
| 1836 | + ), |
|
| 1837 | + ) |
|
| 1838 | + ), |
|
| 1839 | + ), |
|
| 1840 | + ) |
|
| 1841 | + ); |
|
| 1842 | + } |
|
| 1843 | + |
|
| 1844 | + |
|
| 1845 | + /** |
|
| 1846 | + * _create_payment_from_request_data |
|
| 1847 | + * |
|
| 1848 | + * @param array $valid_data |
|
| 1849 | + * @return EE_Payment |
|
| 1850 | + * @throws EE_Error |
|
| 1851 | + * @throws InvalidArgumentException |
|
| 1852 | + * @throws InvalidDataTypeException |
|
| 1853 | + * @throws InvalidInterfaceException |
|
| 1854 | + * @throws ReflectionException |
|
| 1855 | + */ |
|
| 1856 | + protected function _create_payment_from_request_data($valid_data) |
|
| 1857 | + { |
|
| 1858 | + $PAY_ID = $valid_data['PAY_ID']; |
|
| 1859 | + // get payment amount |
|
| 1860 | + $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0; |
|
| 1861 | + // payments have a type value of 1 and refunds have a type value of -1 |
|
| 1862 | + // so multiplying amount by type will give a positive value for payments, and negative values for refunds |
|
| 1863 | + $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount; |
|
| 1864 | + // for some reason the date string coming in has extra spaces between the date and time. This fixes that. |
|
| 1865 | + $date = $valid_data['date'] |
|
| 1866 | + ? preg_replace('/\s+/', ' ', $valid_data['date']) |
|
| 1867 | + : date('Y-m-d g:i a', current_time('timestamp')); |
|
| 1868 | + $payment = EE_Payment::new_instance( |
|
| 1869 | + array( |
|
| 1870 | + 'TXN_ID' => $valid_data['TXN_ID'], |
|
| 1871 | + 'STS_ID' => $valid_data['status'], |
|
| 1872 | + 'PAY_timestamp' => $date, |
|
| 1873 | + 'PAY_source' => EEM_Payment_Method::scope_admin, |
|
| 1874 | + 'PMD_ID' => $valid_data['PMD_ID'], |
|
| 1875 | + 'PAY_amount' => $amount, |
|
| 1876 | + 'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'], |
|
| 1877 | + 'PAY_po_number' => $valid_data['po_number'], |
|
| 1878 | + 'PAY_extra_accntng' => $valid_data['accounting'], |
|
| 1879 | + 'PAY_details' => $valid_data, |
|
| 1880 | + 'PAY_ID' => $PAY_ID, |
|
| 1881 | + ), |
|
| 1882 | + '', |
|
| 1883 | + array('Y-m-d', 'g:i a') |
|
| 1884 | + ); |
|
| 1885 | + |
|
| 1886 | + if (! $payment->save()) { |
|
| 1887 | + EE_Error::add_error( |
|
| 1888 | + sprintf( |
|
| 1889 | + esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'), |
|
| 1890 | + $payment->ID() |
|
| 1891 | + ), |
|
| 1892 | + __FILE__, |
|
| 1893 | + __FUNCTION__, |
|
| 1894 | + __LINE__ |
|
| 1895 | + ); |
|
| 1896 | + } |
|
| 1897 | + |
|
| 1898 | + return $payment; |
|
| 1899 | + } |
|
| 1900 | + |
|
| 1901 | + |
|
| 1902 | + /** |
|
| 1903 | + * _process_transaction_payments |
|
| 1904 | + * |
|
| 1905 | + * @param \EE_Transaction $transaction |
|
| 1906 | + * @return void |
|
| 1907 | + * @throws EE_Error |
|
| 1908 | + * @throws InvalidArgumentException |
|
| 1909 | + * @throws ReflectionException |
|
| 1910 | + * @throws InvalidDataTypeException |
|
| 1911 | + * @throws InvalidInterfaceException |
|
| 1912 | + */ |
|
| 1913 | + protected function _process_transaction_payments(EE_Transaction $transaction) |
|
| 1914 | + { |
|
| 1915 | + /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 1916 | + $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 1917 | + // update the transaction with this payment |
|
| 1918 | + if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) { |
|
| 1919 | + EE_Error::add_success( |
|
| 1920 | + esc_html__( |
|
| 1921 | + 'The payment has been processed successfully.', |
|
| 1922 | + 'event_espresso' |
|
| 1923 | + ), |
|
| 1924 | + __FILE__, |
|
| 1925 | + __FUNCTION__, |
|
| 1926 | + __LINE__ |
|
| 1927 | + ); |
|
| 1928 | + } else { |
|
| 1929 | + EE_Error::add_error( |
|
| 1930 | + esc_html__( |
|
| 1931 | + 'The payment was processed successfully but the amount paid for the transaction was not updated.', |
|
| 1932 | + 'event_espresso' |
|
| 1933 | + ), |
|
| 1934 | + __FILE__, |
|
| 1935 | + __FUNCTION__, |
|
| 1936 | + __LINE__ |
|
| 1937 | + ); |
|
| 1938 | + } |
|
| 1939 | + } |
|
| 1940 | + |
|
| 1941 | + |
|
| 1942 | + /** |
|
| 1943 | + * _get_REG_IDs_to_apply_payment_to |
|
| 1944 | + * returns a list of registration IDs that the payment will apply to |
|
| 1945 | + * |
|
| 1946 | + * @param \EE_Payment $payment |
|
| 1947 | + * @return array |
|
| 1948 | + * @throws EE_Error |
|
| 1949 | + * @throws InvalidArgumentException |
|
| 1950 | + * @throws InvalidDataTypeException |
|
| 1951 | + * @throws InvalidInterfaceException |
|
| 1952 | + * @throws ReflectionException |
|
| 1953 | + */ |
|
| 1954 | + protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment) |
|
| 1955 | + { |
|
| 1956 | + $REG_IDs = array(); |
|
| 1957 | + // grab array of IDs for specific registrations to apply changes to |
|
| 1958 | + if (isset($this->_req_data['txn_admin_payment']['registrations'])) { |
|
| 1959 | + $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations']; |
|
| 1960 | + } |
|
| 1961 | + // nothing specified ? then get all reg IDs |
|
| 1962 | + if (empty($REG_IDs)) { |
|
| 1963 | + $registrations = $payment->transaction()->registrations(); |
|
| 1964 | + $REG_IDs = ! empty($registrations) |
|
| 1965 | + ? array_keys($registrations) |
|
| 1966 | + : $this->_get_existing_reg_payment_REG_IDs($payment); |
|
| 1967 | + } |
|
| 1968 | + |
|
| 1969 | + // ensure that REG_IDs are integers and NOT strings |
|
| 1970 | + return array_map('intval', $REG_IDs); |
|
| 1971 | + } |
|
| 1972 | + |
|
| 1973 | + |
|
| 1974 | + /** |
|
| 1975 | + * @return array |
|
| 1976 | + */ |
|
| 1977 | + public function existing_reg_payment_REG_IDs() |
|
| 1978 | + { |
|
| 1979 | + return $this->_existing_reg_payment_REG_IDs; |
|
| 1980 | + } |
|
| 1981 | + |
|
| 1982 | + |
|
| 1983 | + /** |
|
| 1984 | + * @param array $existing_reg_payment_REG_IDs |
|
| 1985 | + */ |
|
| 1986 | + public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null) |
|
| 1987 | + { |
|
| 1988 | + $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs; |
|
| 1989 | + } |
|
| 1990 | + |
|
| 1991 | + |
|
| 1992 | + /** |
|
| 1993 | + * _get_existing_reg_payment_REG_IDs |
|
| 1994 | + * returns a list of registration IDs that the payment is currently related to |
|
| 1995 | + * as recorded in the database |
|
| 1996 | + * |
|
| 1997 | + * @param \EE_Payment $payment |
|
| 1998 | + * @return array |
|
| 1999 | + * @throws EE_Error |
|
| 2000 | + * @throws InvalidArgumentException |
|
| 2001 | + * @throws InvalidDataTypeException |
|
| 2002 | + * @throws InvalidInterfaceException |
|
| 2003 | + * @throws ReflectionException |
|
| 2004 | + */ |
|
| 2005 | + protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment) |
|
| 2006 | + { |
|
| 2007 | + if ($this->existing_reg_payment_REG_IDs() === null) { |
|
| 2008 | + // let's get any existing reg payment records for this payment |
|
| 2009 | + $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration'); |
|
| 2010 | + // but we only want the REG IDs, so grab the array keys |
|
| 2011 | + $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs) |
|
| 2012 | + ? array_keys($existing_reg_payment_REG_IDs) |
|
| 2013 | + : array(); |
|
| 2014 | + $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs); |
|
| 2015 | + } |
|
| 2016 | + |
|
| 2017 | + return $this->existing_reg_payment_REG_IDs(); |
|
| 2018 | + } |
|
| 2019 | + |
|
| 2020 | + |
|
| 2021 | + /** |
|
| 2022 | + * _remove_existing_registration_payments |
|
| 2023 | + * this calculates the difference between existing relations |
|
| 2024 | + * to the supplied payment and the new list registration IDs, |
|
| 2025 | + * removes any related registrations that no longer apply, |
|
| 2026 | + * and then updates the registration paid fields |
|
| 2027 | + * |
|
| 2028 | + * @param \EE_Payment $payment |
|
| 2029 | + * @param int $PAY_ID |
|
| 2030 | + * @return bool; |
|
| 2031 | + * @throws EE_Error |
|
| 2032 | + * @throws InvalidArgumentException |
|
| 2033 | + * @throws ReflectionException |
|
| 2034 | + * @throws InvalidDataTypeException |
|
| 2035 | + * @throws InvalidInterfaceException |
|
| 2036 | + */ |
|
| 2037 | + protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0) |
|
| 2038 | + { |
|
| 2039 | + // newly created payments will have nothing recorded for $PAY_ID |
|
| 2040 | + if (absint($PAY_ID) === 0) { |
|
| 2041 | + return false; |
|
| 2042 | + } |
|
| 2043 | + $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment); |
|
| 2044 | + if (empty($existing_reg_payment_REG_IDs)) { |
|
| 2045 | + return false; |
|
| 2046 | + } |
|
| 2047 | + /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 2048 | + $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 2049 | + |
|
| 2050 | + return $transaction_payments->delete_registration_payments_and_update_registrations( |
|
| 2051 | + $payment, |
|
| 2052 | + array( |
|
| 2053 | + array( |
|
| 2054 | + 'PAY_ID' => $payment->ID(), |
|
| 2055 | + 'REG_ID' => array('IN', $existing_reg_payment_REG_IDs), |
|
| 2056 | + ), |
|
| 2057 | + ) |
|
| 2058 | + ); |
|
| 2059 | + } |
|
| 2060 | + |
|
| 2061 | + |
|
| 2062 | + /** |
|
| 2063 | + * _update_registration_payments |
|
| 2064 | + * this applies the payments to the selected registrations |
|
| 2065 | + * but only if they have not already been paid for |
|
| 2066 | + * |
|
| 2067 | + * @param EE_Transaction $transaction |
|
| 2068 | + * @param \EE_Payment $payment |
|
| 2069 | + * @param array $REG_IDs |
|
| 2070 | + * @return void |
|
| 2071 | + * @throws EE_Error |
|
| 2072 | + * @throws InvalidArgumentException |
|
| 2073 | + * @throws ReflectionException |
|
| 2074 | + * @throws RuntimeException |
|
| 2075 | + * @throws InvalidDataTypeException |
|
| 2076 | + * @throws InvalidInterfaceException |
|
| 2077 | + */ |
|
| 2078 | + protected function _update_registration_payments( |
|
| 2079 | + EE_Transaction $transaction, |
|
| 2080 | + EE_Payment $payment, |
|
| 2081 | + $REG_IDs = array() |
|
| 2082 | + ) { |
|
| 2083 | + // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments() |
|
| 2084 | + // so let's do that using our set of REG_IDs from the form |
|
| 2085 | + $registration_query_where_params = array( |
|
| 2086 | + 'REG_ID' => array('IN', $REG_IDs), |
|
| 2087 | + ); |
|
| 2088 | + // but add in some conditions regarding payment, |
|
| 2089 | + // so that we don't apply payments to registrations that are free or have already been paid for |
|
| 2090 | + // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative ) |
|
| 2091 | + if (! $payment->is_a_refund()) { |
|
| 2092 | + $registration_query_where_params['REG_final_price'] = array('!=', 0); |
|
| 2093 | + $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true); |
|
| 2094 | + } |
|
| 2095 | + $registrations = $transaction->registrations(array($registration_query_where_params)); |
|
| 2096 | + if (! empty($registrations)) { |
|
| 2097 | + /** @type EE_Payment_Processor $payment_processor */ |
|
| 2098 | + $payment_processor = EE_Registry::instance()->load_core('Payment_Processor'); |
|
| 2099 | + $payment_processor->process_registration_payments($transaction, $payment, $registrations); |
|
| 2100 | + } |
|
| 2101 | + } |
|
| 2102 | + |
|
| 2103 | + |
|
| 2104 | + /** |
|
| 2105 | + * _process_registration_status_change |
|
| 2106 | + * This processes requested registration status changes for all the registrations |
|
| 2107 | + * on a given transaction and (optionally) sends out notifications for the changes. |
|
| 2108 | + * |
|
| 2109 | + * @param EE_Transaction $transaction |
|
| 2110 | + * @param array $REG_IDs |
|
| 2111 | + * @return bool |
|
| 2112 | + * @throws EE_Error |
|
| 2113 | + * @throws InvalidArgumentException |
|
| 2114 | + * @throws ReflectionException |
|
| 2115 | + * @throws InvalidDataTypeException |
|
| 2116 | + * @throws InvalidInterfaceException |
|
| 2117 | + */ |
|
| 2118 | + protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array()) |
|
| 2119 | + { |
|
| 2120 | + // first if there is no change in status then we get out. |
|
| 2121 | + if (! isset($this->_req_data['txn_reg_status_change']['reg_status']) |
|
| 2122 | + || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN' |
|
| 2123 | + ) { |
|
| 2124 | + // no error message, no change requested, just nothing to do man. |
|
| 2125 | + return false; |
|
| 2126 | + } |
|
| 2127 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 2128 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 2129 | + |
|
| 2130 | + // made it here dude? Oh WOW. K, let's take care of changing the statuses |
|
| 2131 | + return $transaction_processor->manually_update_registration_statuses( |
|
| 2132 | + $transaction, |
|
| 2133 | + sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']), |
|
| 2134 | + array(array('REG_ID' => array('IN', $REG_IDs))) |
|
| 2135 | + ); |
|
| 2136 | + } |
|
| 2137 | + |
|
| 2138 | + |
|
| 2139 | + /** |
|
| 2140 | + * _build_payment_json_response |
|
| 2141 | + * |
|
| 2142 | + * @access public |
|
| 2143 | + * @param \EE_Payment $payment |
|
| 2144 | + * @param array $REG_IDs |
|
| 2145 | + * @param bool | null $delete_txn_reg_status_change |
|
| 2146 | + * @return array |
|
| 2147 | + * @throws EE_Error |
|
| 2148 | + * @throws InvalidArgumentException |
|
| 2149 | + * @throws InvalidDataTypeException |
|
| 2150 | + * @throws InvalidInterfaceException |
|
| 2151 | + * @throws ReflectionException |
|
| 2152 | + */ |
|
| 2153 | + protected function _build_payment_json_response( |
|
| 2154 | + EE_Payment $payment, |
|
| 2155 | + $REG_IDs = array(), |
|
| 2156 | + $delete_txn_reg_status_change = null |
|
| 2157 | + ) { |
|
| 2158 | + // was the payment deleted ? |
|
| 2159 | + if (is_bool($delete_txn_reg_status_change)) { |
|
| 2160 | + return array( |
|
| 2161 | + 'PAY_ID' => $payment->ID(), |
|
| 2162 | + 'amount' => $payment->amount(), |
|
| 2163 | + 'total_paid' => $payment->transaction()->paid(), |
|
| 2164 | + 'txn_status' => $payment->transaction()->status_ID(), |
|
| 2165 | + 'pay_status' => $payment->STS_ID(), |
|
| 2166 | + 'registrations' => $this->_registration_payment_data_array($REG_IDs), |
|
| 2167 | + 'delete_txn_reg_status_change' => $delete_txn_reg_status_change, |
|
| 2168 | + ); |
|
| 2169 | + } else { |
|
| 2170 | + $this->_get_payment_status_array(); |
|
| 2171 | + |
|
| 2172 | + return array( |
|
| 2173 | + 'amount' => $payment->amount(), |
|
| 2174 | + 'total_paid' => $payment->transaction()->paid(), |
|
| 2175 | + 'txn_status' => $payment->transaction()->status_ID(), |
|
| 2176 | + 'pay_status' => $payment->STS_ID(), |
|
| 2177 | + 'PAY_ID' => $payment->ID(), |
|
| 2178 | + 'STS_ID' => $payment->STS_ID(), |
|
| 2179 | + 'status' => self::$_pay_status[ $payment->STS_ID() ], |
|
| 2180 | + 'date' => $payment->timestamp('Y-m-d', 'h:i a'), |
|
| 2181 | + 'method' => strtoupper($payment->source()), |
|
| 2182 | + 'PM_ID' => $payment->payment_method() ? $payment->payment_method()->ID() : 1, |
|
| 2183 | + 'gateway' => $payment->payment_method() |
|
| 2184 | + ? $payment->payment_method()->admin_name() |
|
| 2185 | + : esc_html__('Unknown', 'event_espresso'), |
|
| 2186 | + 'gateway_response' => $payment->gateway_response(), |
|
| 2187 | + 'txn_id_chq_nmbr' => $payment->txn_id_chq_nmbr(), |
|
| 2188 | + 'po_number' => $payment->po_number(), |
|
| 2189 | + 'extra_accntng' => $payment->extra_accntng(), |
|
| 2190 | + 'registrations' => $this->_registration_payment_data_array($REG_IDs), |
|
| 2191 | + ); |
|
| 2192 | + } |
|
| 2193 | + } |
|
| 2194 | + |
|
| 2195 | + |
|
| 2196 | + /** |
|
| 2197 | + * delete_payment |
|
| 2198 | + * delete a payment or refund made towards a transaction |
|
| 2199 | + * |
|
| 2200 | + * @access public |
|
| 2201 | + * @return void |
|
| 2202 | + * @throws EE_Error |
|
| 2203 | + * @throws InvalidArgumentException |
|
| 2204 | + * @throws ReflectionException |
|
| 2205 | + * @throws InvalidDataTypeException |
|
| 2206 | + * @throws InvalidInterfaceException |
|
| 2207 | + */ |
|
| 2208 | + public function delete_payment() |
|
| 2209 | + { |
|
| 2210 | + $json_response_data = array('return_data' => false); |
|
| 2211 | + $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID']) |
|
| 2212 | + ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID']) |
|
| 2213 | + : 0; |
|
| 2214 | + $can_delete = EE_Registry::instance()->CAP->current_user_can( |
|
| 2215 | + 'ee_delete_payments', |
|
| 2216 | + 'delete_payment_from_registration_details' |
|
| 2217 | + ); |
|
| 2218 | + if ($PAY_ID && $can_delete) { |
|
| 2219 | + $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change']) |
|
| 2220 | + ? $this->_req_data['delete_txn_reg_status_change'] |
|
| 2221 | + : false; |
|
| 2222 | + $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID); |
|
| 2223 | + if ($payment instanceof EE_Payment) { |
|
| 2224 | + $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment); |
|
| 2225 | + /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 2226 | + $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 2227 | + if ($transaction_payments->delete_payment_and_update_transaction($payment)) { |
|
| 2228 | + $json_response_data['return_data'] = $this->_build_payment_json_response( |
|
| 2229 | + $payment, |
|
| 2230 | + $REG_IDs, |
|
| 2231 | + $delete_txn_reg_status_change |
|
| 2232 | + ); |
|
| 2233 | + if ($delete_txn_reg_status_change) { |
|
| 2234 | + $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change; |
|
| 2235 | + // MAKE sure we also add the delete_txn_req_status_change to the |
|
| 2236 | + // $_REQUEST global because that's how messages will be looking for it. |
|
| 2237 | + $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change; |
|
| 2238 | + $this->_maybe_send_notifications(); |
|
| 2239 | + $this->_process_registration_status_change($payment->transaction(), $REG_IDs); |
|
| 2240 | + } |
|
| 2241 | + } |
|
| 2242 | + } else { |
|
| 2243 | + EE_Error::add_error( |
|
| 2244 | + esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'), |
|
| 2245 | + __FILE__, |
|
| 2246 | + __FUNCTION__, |
|
| 2247 | + __LINE__ |
|
| 2248 | + ); |
|
| 2249 | + } |
|
| 2250 | + } elseif ($can_delete) { |
|
| 2251 | + EE_Error::add_error( |
|
| 2252 | + esc_html__( |
|
| 2253 | + 'A valid Payment ID was not received, therefore payment form data could not be loaded.', |
|
| 2254 | + 'event_espresso' |
|
| 2255 | + ), |
|
| 2256 | + __FILE__, |
|
| 2257 | + __FUNCTION__, |
|
| 2258 | + __LINE__ |
|
| 2259 | + ); |
|
| 2260 | + } else { |
|
| 2261 | + EE_Error::add_error( |
|
| 2262 | + esc_html__( |
|
| 2263 | + 'You do not have access to delete a payment.', |
|
| 2264 | + 'event_espresso' |
|
| 2265 | + ), |
|
| 2266 | + __FILE__, |
|
| 2267 | + __FUNCTION__, |
|
| 2268 | + __LINE__ |
|
| 2269 | + ); |
|
| 2270 | + } |
|
| 2271 | + $notices = EE_Error::get_notices(false, false, false); |
|
| 2272 | + $this->_template_args = array( |
|
| 2273 | + 'data' => $json_response_data, |
|
| 2274 | + 'success' => $notices['success'], |
|
| 2275 | + 'error' => $notices['errors'], |
|
| 2276 | + 'attention' => $notices['attention'], |
|
| 2277 | + ); |
|
| 2278 | + $this->_return_json(); |
|
| 2279 | + } |
|
| 2280 | + |
|
| 2281 | + |
|
| 2282 | + /** |
|
| 2283 | + * _registration_payment_data_array |
|
| 2284 | + * adds info for 'owing' and 'paid' for each registration to the json response |
|
| 2285 | + * |
|
| 2286 | + * @access protected |
|
| 2287 | + * @param array $REG_IDs |
|
| 2288 | + * @return array |
|
| 2289 | + * @throws EE_Error |
|
| 2290 | + * @throws InvalidArgumentException |
|
| 2291 | + * @throws InvalidDataTypeException |
|
| 2292 | + * @throws InvalidInterfaceException |
|
| 2293 | + * @throws ReflectionException |
|
| 2294 | + */ |
|
| 2295 | + protected function _registration_payment_data_array($REG_IDs) |
|
| 2296 | + { |
|
| 2297 | + $registration_payment_data = array(); |
|
| 2298 | + // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows. |
|
| 2299 | + if (! empty($REG_IDs)) { |
|
| 2300 | + $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs)))); |
|
| 2301 | + foreach ($registrations as $registration) { |
|
| 2302 | + if ($registration instanceof EE_Registration) { |
|
| 2303 | + $registration_payment_data[ $registration->ID() ] = array( |
|
| 2304 | + 'paid' => $registration->pretty_paid(), |
|
| 2305 | + 'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()), |
|
| 2306 | + ); |
|
| 2307 | + } |
|
| 2308 | + } |
|
| 2309 | + } |
|
| 2310 | + |
|
| 2311 | + return $registration_payment_data; |
|
| 2312 | + } |
|
| 2313 | + |
|
| 2314 | + |
|
| 2315 | + /** |
|
| 2316 | + * _maybe_send_notifications |
|
| 2317 | + * determines whether or not the admin has indicated that notifications should be sent. |
|
| 2318 | + * If so, will toggle a filter switch for delivering registration notices. |
|
| 2319 | + * If passed an EE_Payment object, then it will trigger payment notifications instead. |
|
| 2320 | + * |
|
| 2321 | + * @access protected |
|
| 2322 | + * @param \EE_Payment | null $payment |
|
| 2323 | + */ |
|
| 2324 | + protected function _maybe_send_notifications($payment = null) |
|
| 2325 | + { |
|
| 2326 | + switch ($payment instanceof EE_Payment) { |
|
| 2327 | + // payment notifications |
|
| 2328 | + case true: |
|
| 2329 | + if (isset($this->_req_data['txn_payments']['send_notifications']) |
|
| 2330 | + && filter_var( |
|
| 2331 | + $this->_req_data['txn_payments']['send_notifications'], |
|
| 2332 | + FILTER_VALIDATE_BOOLEAN |
|
| 2333 | + ) |
|
| 2334 | + ) { |
|
| 2335 | + $this->_process_payment_notification($payment); |
|
| 2336 | + } |
|
| 2337 | + break; |
|
| 2338 | + // registration notifications |
|
| 2339 | + case false: |
|
| 2340 | + if (isset($this->_req_data['txn_reg_status_change']['send_notifications']) |
|
| 2341 | + && filter_var( |
|
| 2342 | + $this->_req_data['txn_reg_status_change']['send_notifications'], |
|
| 2343 | + FILTER_VALIDATE_BOOLEAN |
|
| 2344 | + ) |
|
| 2345 | + ) { |
|
| 2346 | + add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true'); |
|
| 2347 | + } |
|
| 2348 | + break; |
|
| 2349 | + } |
|
| 2350 | + } |
|
| 2351 | + |
|
| 2352 | + |
|
| 2353 | + /** |
|
| 2354 | + * _send_payment_reminder |
|
| 2355 | + * generates HTML for the View Transaction Details Admin page |
|
| 2356 | + * |
|
| 2357 | + * @access protected |
|
| 2358 | + * @return void |
|
| 2359 | + * @throws EE_Error |
|
| 2360 | + * @throws InvalidArgumentException |
|
| 2361 | + * @throws InvalidDataTypeException |
|
| 2362 | + * @throws InvalidInterfaceException |
|
| 2363 | + */ |
|
| 2364 | + protected function _send_payment_reminder() |
|
| 2365 | + { |
|
| 2366 | + $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false; |
|
| 2367 | + $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
| 2368 | + $query_args = isset($this->_req_data['redirect_to']) ? array( |
|
| 2369 | + 'action' => $this->_req_data['redirect_to'], |
|
| 2370 | + 'TXN_ID' => $this->_req_data['TXN_ID'], |
|
| 2371 | + ) : array(); |
|
| 2372 | + do_action( |
|
| 2373 | + 'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder', |
|
| 2374 | + $transaction |
|
| 2375 | + ); |
|
| 2376 | + $this->_redirect_after_action( |
|
| 2377 | + false, |
|
| 2378 | + esc_html__('payment reminder', 'event_espresso'), |
|
| 2379 | + esc_html__('sent', 'event_espresso'), |
|
| 2380 | + $query_args, |
|
| 2381 | + true |
|
| 2382 | + ); |
|
| 2383 | + } |
|
| 2384 | + |
|
| 2385 | + |
|
| 2386 | + /** |
|
| 2387 | + * get_transactions |
|
| 2388 | + * get transactions for given parameters (used by list table) |
|
| 2389 | + * |
|
| 2390 | + * @param int $perpage how many transactions displayed per page |
|
| 2391 | + * @param boolean $count return the count or objects |
|
| 2392 | + * @param string $view |
|
| 2393 | + * @return mixed int = count || array of transaction objects |
|
| 2394 | + * @throws EE_Error |
|
| 2395 | + * @throws InvalidArgumentException |
|
| 2396 | + * @throws InvalidDataTypeException |
|
| 2397 | + * @throws InvalidInterfaceException |
|
| 2398 | + */ |
|
| 2399 | + public function get_transactions($perpage, $count = false, $view = '') |
|
| 2400 | + { |
|
| 2401 | + |
|
| 2402 | + $TXN = EEM_Transaction::instance(); |
|
| 2403 | + |
|
| 2404 | + $start_date = isset($this->_req_data['txn-filter-start-date']) |
|
| 2405 | + ? wp_strip_all_tags($this->_req_data['txn-filter-start-date']) |
|
| 2406 | + : date( |
|
| 2407 | + 'm/d/Y', |
|
| 2408 | + strtotime('-10 year') |
|
| 2409 | + ); |
|
| 2410 | + $end_date = isset($this->_req_data['txn-filter-end-date']) |
|
| 2411 | + ? wp_strip_all_tags($this->_req_data['txn-filter-end-date']) |
|
| 2412 | + : date('m/d/Y'); |
|
| 2413 | + |
|
| 2414 | + // make sure our timestamps start and end right at the boundaries for each day |
|
| 2415 | + $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00'; |
|
| 2416 | + $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59'; |
|
| 2417 | + |
|
| 2418 | + |
|
| 2419 | + // convert to timestamps |
|
| 2420 | + $start_date = strtotime($start_date); |
|
| 2421 | + $end_date = strtotime($end_date); |
|
| 2422 | + |
|
| 2423 | + // makes sure start date is the lowest value and vice versa |
|
| 2424 | + $start_date = min($start_date, $end_date); |
|
| 2425 | + $end_date = max($start_date, $end_date); |
|
| 2426 | + |
|
| 2427 | + // convert to correct format for query |
|
| 2428 | + $start_date = EEM_Transaction::instance()->convert_datetime_for_query( |
|
| 2429 | + 'TXN_timestamp', |
|
| 2430 | + date('Y-m-d H:i:s', $start_date), |
|
| 2431 | + 'Y-m-d H:i:s' |
|
| 2432 | + ); |
|
| 2433 | + $end_date = EEM_Transaction::instance()->convert_datetime_for_query( |
|
| 2434 | + 'TXN_timestamp', |
|
| 2435 | + date('Y-m-d H:i:s', $end_date), |
|
| 2436 | + 'Y-m-d H:i:s' |
|
| 2437 | + ); |
|
| 2438 | + |
|
| 2439 | + |
|
| 2440 | + // set orderby |
|
| 2441 | + $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : ''; |
|
| 2442 | + |
|
| 2443 | + switch ($this->_req_data['orderby']) { |
|
| 2444 | + case 'TXN_ID': |
|
| 2445 | + $orderby = 'TXN_ID'; |
|
| 2446 | + break; |
|
| 2447 | + case 'ATT_fname': |
|
| 2448 | + $orderby = 'Registration.Attendee.ATT_fname'; |
|
| 2449 | + break; |
|
| 2450 | + case 'event_name': |
|
| 2451 | + $orderby = 'Registration.Event.EVT_name'; |
|
| 2452 | + break; |
|
| 2453 | + default: // 'TXN_timestamp' |
|
| 2454 | + $orderby = 'TXN_timestamp'; |
|
| 2455 | + } |
|
| 2456 | + |
|
| 2457 | + $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC'; |
|
| 2458 | + $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1; |
|
| 2459 | + $per_page = ! empty($perpage) ? $perpage : 10; |
|
| 2460 | + $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page; |
|
| 2461 | + |
|
| 2462 | + $offset = ($current_page - 1) * $per_page; |
|
| 2463 | + $limit = array($offset, $per_page); |
|
| 2464 | + |
|
| 2465 | + $_where = array( |
|
| 2466 | + 'TXN_timestamp' => array('BETWEEN', array($start_date, $end_date)), |
|
| 2467 | + 'Registration.REG_count' => 1, |
|
| 2468 | + ); |
|
| 2469 | + |
|
| 2470 | + if (isset($this->_req_data['EVT_ID'])) { |
|
| 2471 | + $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID']; |
|
| 2472 | + } |
|
| 2473 | + |
|
| 2474 | + if (isset($this->_req_data['s'])) { |
|
| 2475 | + $search_string = '%' . $this->_req_data['s'] . '%'; |
|
| 2476 | + $_where['OR'] = array( |
|
| 2477 | + 'Registration.Event.EVT_name' => array('LIKE', $search_string), |
|
| 2478 | + 'Registration.Event.EVT_desc' => array('LIKE', $search_string), |
|
| 2479 | + 'Registration.Event.EVT_short_desc' => array('LIKE', $search_string), |
|
| 2480 | + 'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string), |
|
| 2481 | + 'Registration.Attendee.ATT_fname' => array('LIKE', $search_string), |
|
| 2482 | + 'Registration.Attendee.ATT_lname' => array('LIKE', $search_string), |
|
| 2483 | + 'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string), |
|
| 2484 | + 'Registration.Attendee.ATT_email' => array('LIKE', $search_string), |
|
| 2485 | + 'Registration.Attendee.ATT_address' => array('LIKE', $search_string), |
|
| 2486 | + 'Registration.Attendee.ATT_address2' => array('LIKE', $search_string), |
|
| 2487 | + 'Registration.Attendee.ATT_city' => array('LIKE', $search_string), |
|
| 2488 | + 'Registration.REG_final_price' => array('LIKE', $search_string), |
|
| 2489 | + 'Registration.REG_code' => array('LIKE', $search_string), |
|
| 2490 | + 'Registration.REG_count' => array('LIKE', $search_string), |
|
| 2491 | + 'Registration.REG_group_size' => array('LIKE', $search_string), |
|
| 2492 | + 'Registration.Ticket.TKT_name' => array('LIKE', $search_string), |
|
| 2493 | + 'Registration.Ticket.TKT_description' => array('LIKE', $search_string), |
|
| 2494 | + 'Payment.PAY_source' => array('LIKE', $search_string), |
|
| 2495 | + 'Payment.Payment_Method.PMD_name' => array('LIKE', $search_string), |
|
| 2496 | + 'TXN_session_data' => array('LIKE', $search_string), |
|
| 2497 | + 'Payment.PAY_txn_id_chq_nmbr' => array('LIKE', $search_string), |
|
| 2498 | + ); |
|
| 2499 | + } |
|
| 2500 | + |
|
| 2501 | + // failed transactions |
|
| 2502 | + $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count) |
|
| 2503 | + || ($count && $view === 'failed'); |
|
| 2504 | + $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count) |
|
| 2505 | + || ($count && $view === 'abandoned'); |
|
| 2506 | + $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count) |
|
| 2507 | + || ($count && $view === 'incomplete'); |
|
| 2508 | + |
|
| 2509 | + if ($failed) { |
|
| 2510 | + $_where['STS_ID'] = EEM_Transaction::failed_status_code; |
|
| 2511 | + } elseif ($abandoned) { |
|
| 2512 | + $_where['STS_ID'] = EEM_Transaction::abandoned_status_code; |
|
| 2513 | + } elseif ($incomplete) { |
|
| 2514 | + $_where['STS_ID'] = EEM_Transaction::incomplete_status_code; |
|
| 2515 | + } else { |
|
| 2516 | + $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code); |
|
| 2517 | + $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code); |
|
| 2518 | + } |
|
| 2519 | + |
|
| 2520 | + $query_params = apply_filters( |
|
| 2521 | + 'FHEE__Transactions_Admin_Page___get_transactions_query_params', |
|
| 2522 | + array( |
|
| 2523 | + $_where, |
|
| 2524 | + 'order_by' => array($orderby => $sort), |
|
| 2525 | + 'limit' => $limit, |
|
| 2526 | + 'default_where_conditions' => EEM_Base::default_where_conditions_this_only, |
|
| 2527 | + ), |
|
| 2528 | + $this->_req_data, |
|
| 2529 | + $view, |
|
| 2530 | + $count |
|
| 2531 | + ); |
|
| 2532 | + |
|
| 2533 | + $transactions = $count |
|
| 2534 | + ? $TXN->count(array($query_params[0]), 'TXN_ID', true) |
|
| 2535 | + : $TXN->get_all($query_params); |
|
| 2536 | + |
|
| 2537 | + return $transactions; |
|
| 2538 | + } |
|
| 2539 | + |
|
| 2540 | + |
|
| 2541 | + /** |
|
| 2542 | + * @since 4.9.79.p |
|
| 2543 | + * @throws EE_Error |
|
| 2544 | + * @throws InvalidArgumentException |
|
| 2545 | + * @throws InvalidDataTypeException |
|
| 2546 | + * @throws InvalidInterfaceException |
|
| 2547 | + * @throws ReflectionException |
|
| 2548 | + * @throws RuntimeException |
|
| 2549 | + */ |
|
| 2550 | + public function recalculateLineItems() |
|
| 2551 | + { |
|
| 2552 | + $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false; |
|
| 2553 | + /** @var EE_Transaction $transaction */ |
|
| 2554 | + $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID); |
|
| 2555 | + $total_line_item = $transaction->total_line_item(false); |
|
| 2556 | + $success = false; |
|
| 2557 | + if ($total_line_item instanceof EE_Line_Item) { |
|
| 2558 | + EEH_Line_Item::resetIsTaxableForTickets($total_line_item); |
|
| 2559 | + $success = EEH_Line_Item::apply_taxes($total_line_item, true); |
|
| 2560 | + } |
|
| 2561 | + $this->_redirect_after_action( |
|
| 2562 | + (bool) $success, |
|
| 2563 | + esc_html__('Transaction taxes and totals', 'event_espresso'), |
|
| 2564 | + esc_html__('recalculated', 'event_espresso'), |
|
| 2565 | + isset($this->_req_data['redirect_to']) |
|
| 2566 | + ? array( |
|
| 2567 | + 'action' => $this->_req_data['redirect_to'], |
|
| 2568 | + 'TXN_ID' => $this->_req_data['TXN_ID'], |
|
| 2569 | + ) |
|
| 2570 | + : array(), |
|
| 2571 | + true |
|
| 2572 | + ); |
|
| 2573 | + } |
|
| 2574 | 2574 | } |
@@ -366,7 +366,7 @@ discard block |
||
| 366 | 366 | |
| 367 | 367 | |
| 368 | 368 | /** |
| 369 | - * @return mixed|null |
|
| 369 | + * @return EE_Cart|null |
|
| 370 | 370 | * @throws EE_Error |
| 371 | 371 | * @throws InvalidArgumentException |
| 372 | 372 | * @throws InvalidDataTypeException |
@@ -508,7 +508,7 @@ discard block |
||
| 508 | 508 | * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event |
| 509 | 509 | * function for getting attendees and how many registrations they each have for an event) |
| 510 | 510 | * |
| 511 | - * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT' |
|
| 511 | + * @return EE_Base_Class[] EE_Attendee[] by default, int if $output is set to 'COUNT' |
|
| 512 | 512 | * @throws EE_Error |
| 513 | 513 | * @throws InvalidArgumentException |
| 514 | 514 | * @throws InvalidDataTypeException |
@@ -564,7 +564,7 @@ discard block |
||
| 564 | 564 | /** |
| 565 | 565 | * Gets all payments which have not been approved |
| 566 | 566 | * |
| 567 | - * @return EE_Base_Class[]|EEI_Payment[] |
|
| 567 | + * @return EE_Base_Class[] |
|
| 568 | 568 | * @throws EE_Error if a model is misconfigured somehow |
| 569 | 569 | * @throws InvalidArgumentException |
| 570 | 570 | * @throws InvalidDataTypeException |
@@ -13,1682 +13,1682 @@ |
||
| 13 | 13 | class EE_Transaction extends EE_Base_Class implements EEI_Transaction |
| 14 | 14 | { |
| 15 | 15 | |
| 16 | - /** |
|
| 17 | - * The length of time in seconds that a lock is applied before being considered expired. |
|
| 18 | - * It is not long because a transaction should only be locked for the duration of the request that locked it |
|
| 19 | - */ |
|
| 20 | - const LOCK_EXPIRATION = 2; |
|
| 21 | - |
|
| 22 | - /** |
|
| 23 | - * txn status upon initial construction. |
|
| 24 | - * |
|
| 25 | - * @var string |
|
| 26 | - */ |
|
| 27 | - protected $_old_txn_status; |
|
| 28 | - |
|
| 29 | - |
|
| 30 | - /** |
|
| 31 | - * @param array $props_n_values incoming values |
|
| 32 | - * @param string $timezone incoming timezone |
|
| 33 | - * (if not set the timezone set for the website will be used.) |
|
| 34 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 35 | - * date_format and the second value is the time format |
|
| 36 | - * @return EE_Transaction |
|
| 37 | - * @throws EE_Error |
|
| 38 | - * @throws InvalidArgumentException |
|
| 39 | - * @throws InvalidDataTypeException |
|
| 40 | - * @throws InvalidInterfaceException |
|
| 41 | - * @throws ReflectionException |
|
| 42 | - */ |
|
| 43 | - public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
| 44 | - { |
|
| 45 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 46 | - $txn = $has_object |
|
| 47 | - ? $has_object |
|
| 48 | - : new self($props_n_values, false, $timezone, $date_formats); |
|
| 49 | - if (! $has_object) { |
|
| 50 | - $txn->set_old_txn_status($txn->status_ID()); |
|
| 51 | - } |
|
| 52 | - return $txn; |
|
| 53 | - } |
|
| 54 | - |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * @param array $props_n_values incoming values from the database |
|
| 58 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 59 | - * the website will be used. |
|
| 60 | - * @return EE_Transaction |
|
| 61 | - * @throws EE_Error |
|
| 62 | - * @throws InvalidArgumentException |
|
| 63 | - * @throws InvalidDataTypeException |
|
| 64 | - * @throws InvalidInterfaceException |
|
| 65 | - * @throws ReflectionException |
|
| 66 | - */ |
|
| 67 | - public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
| 68 | - { |
|
| 69 | - $txn = new self($props_n_values, true, $timezone); |
|
| 70 | - $txn->set_old_txn_status($txn->status_ID()); |
|
| 71 | - return $txn; |
|
| 72 | - } |
|
| 73 | - |
|
| 74 | - |
|
| 75 | - /** |
|
| 76 | - * Sets a meta field indicating that this TXN is locked and should not be updated in the db. |
|
| 77 | - * If a lock has already been set, then we will attempt to remove it in case it has expired. |
|
| 78 | - * If that also fails, then an exception is thrown. |
|
| 79 | - * |
|
| 80 | - * @throws EE_Error |
|
| 81 | - * @throws InvalidArgumentException |
|
| 82 | - * @throws InvalidDataTypeException |
|
| 83 | - * @throws InvalidInterfaceException |
|
| 84 | - * @throws ReflectionException |
|
| 85 | - */ |
|
| 86 | - public function lock() |
|
| 87 | - { |
|
| 88 | - // attempt to set lock, but if that fails... |
|
| 89 | - if (! $this->add_extra_meta('lock', time(), true)) { |
|
| 90 | - // then attempt to remove the lock in case it is expired |
|
| 91 | - if ($this->_remove_expired_lock()) { |
|
| 92 | - // if removal was successful, then try setting lock again |
|
| 93 | - $this->lock(); |
|
| 94 | - } else { |
|
| 95 | - // but if the lock can not be removed, then throw an exception |
|
| 96 | - throw new EE_Error( |
|
| 97 | - sprintf( |
|
| 98 | - __( |
|
| 99 | - 'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.', |
|
| 100 | - 'event_espresso' |
|
| 101 | - ), |
|
| 102 | - $this->ID() |
|
| 103 | - ) |
|
| 104 | - ); |
|
| 105 | - } |
|
| 106 | - } |
|
| 107 | - } |
|
| 108 | - |
|
| 109 | - |
|
| 110 | - /** |
|
| 111 | - * removes transaction lock applied in EE_Transaction::lock() |
|
| 112 | - * |
|
| 113 | - * @return int |
|
| 114 | - * @throws EE_Error |
|
| 115 | - * @throws InvalidArgumentException |
|
| 116 | - * @throws InvalidDataTypeException |
|
| 117 | - * @throws InvalidInterfaceException |
|
| 118 | - * @throws ReflectionException |
|
| 119 | - */ |
|
| 120 | - public function unlock() |
|
| 121 | - { |
|
| 122 | - return $this->delete_extra_meta('lock'); |
|
| 123 | - } |
|
| 124 | - |
|
| 125 | - |
|
| 126 | - /** |
|
| 127 | - * Decides whether or not now is the right time to update the transaction. |
|
| 128 | - * This is useful because we don't always know if it is safe to update the transaction |
|
| 129 | - * and its related data. why? |
|
| 130 | - * because it's possible that the transaction is being used in another |
|
| 131 | - * request and could overwrite anything we save. |
|
| 132 | - * So we want to only update the txn once we know that won't happen. |
|
| 133 | - * We also check that the lock isn't expired, and remove it if it is |
|
| 134 | - * |
|
| 135 | - * @return boolean |
|
| 136 | - * @throws EE_Error |
|
| 137 | - * @throws InvalidArgumentException |
|
| 138 | - * @throws InvalidDataTypeException |
|
| 139 | - * @throws InvalidInterfaceException |
|
| 140 | - * @throws ReflectionException |
|
| 141 | - */ |
|
| 142 | - public function is_locked() |
|
| 143 | - { |
|
| 144 | - // if TXN is not locked, then return false immediately |
|
| 145 | - if (! $this->_get_lock()) { |
|
| 146 | - return false; |
|
| 147 | - } |
|
| 148 | - // if not, then let's try and remove the lock in case it's expired... |
|
| 149 | - // _remove_expired_lock() returns 0 when lock is valid (ie: removed = false) |
|
| 150 | - // and a positive number if the lock was removed (ie: number of locks deleted), |
|
| 151 | - // so we need to return the opposite |
|
| 152 | - return ! $this->_remove_expired_lock() ? true : false; |
|
| 153 | - } |
|
| 154 | - |
|
| 155 | - |
|
| 156 | - /** |
|
| 157 | - * Gets the meta field indicating that this TXN is locked |
|
| 158 | - * |
|
| 159 | - * @return int |
|
| 160 | - * @throws EE_Error |
|
| 161 | - * @throws InvalidArgumentException |
|
| 162 | - * @throws InvalidDataTypeException |
|
| 163 | - * @throws InvalidInterfaceException |
|
| 164 | - * @throws ReflectionException |
|
| 165 | - */ |
|
| 166 | - protected function _get_lock() |
|
| 167 | - { |
|
| 168 | - return (int) $this->get_extra_meta('lock', true, 0); |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated |
|
| 174 | - * |
|
| 175 | - * @return int |
|
| 176 | - * @throws EE_Error |
|
| 177 | - * @throws InvalidArgumentException |
|
| 178 | - * @throws InvalidDataTypeException |
|
| 179 | - * @throws InvalidInterfaceException |
|
| 180 | - * @throws ReflectionException |
|
| 181 | - */ |
|
| 182 | - protected function _remove_expired_lock() |
|
| 183 | - { |
|
| 184 | - $locked = $this->_get_lock(); |
|
| 185 | - if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) { |
|
| 186 | - return $this->unlock(); |
|
| 187 | - } |
|
| 188 | - return 0; |
|
| 189 | - } |
|
| 190 | - |
|
| 191 | - |
|
| 192 | - /** |
|
| 193 | - * Set transaction total |
|
| 194 | - * |
|
| 195 | - * @param float $total total value of transaction |
|
| 196 | - * @throws EE_Error |
|
| 197 | - * @throws InvalidArgumentException |
|
| 198 | - * @throws InvalidDataTypeException |
|
| 199 | - * @throws InvalidInterfaceException |
|
| 200 | - * @throws ReflectionException |
|
| 201 | - */ |
|
| 202 | - public function set_total($total = 0.00) |
|
| 203 | - { |
|
| 204 | - $this->set('TXN_total', (float) $total); |
|
| 205 | - } |
|
| 206 | - |
|
| 207 | - |
|
| 208 | - /** |
|
| 209 | - * Set Total Amount Paid to Date |
|
| 210 | - * |
|
| 211 | - * @param float $total_paid total amount paid to date (sum of all payments) |
|
| 212 | - * @throws EE_Error |
|
| 213 | - * @throws InvalidArgumentException |
|
| 214 | - * @throws InvalidDataTypeException |
|
| 215 | - * @throws InvalidInterfaceException |
|
| 216 | - * @throws ReflectionException |
|
| 217 | - */ |
|
| 218 | - public function set_paid($total_paid = 0.00) |
|
| 219 | - { |
|
| 220 | - $this->set('TXN_paid', (float) $total_paid); |
|
| 221 | - } |
|
| 222 | - |
|
| 223 | - |
|
| 224 | - /** |
|
| 225 | - * Set transaction status |
|
| 226 | - * |
|
| 227 | - * @param string $status whether the transaction is open, declined, accepted, |
|
| 228 | - * or any number of custom values that can be set |
|
| 229 | - * @throws EE_Error |
|
| 230 | - * @throws InvalidArgumentException |
|
| 231 | - * @throws InvalidDataTypeException |
|
| 232 | - * @throws InvalidInterfaceException |
|
| 233 | - * @throws ReflectionException |
|
| 234 | - */ |
|
| 235 | - public function set_status($status = '') |
|
| 236 | - { |
|
| 237 | - $this->set('STS_ID', $status); |
|
| 238 | - } |
|
| 239 | - |
|
| 240 | - |
|
| 241 | - /** |
|
| 242 | - * Set hash salt |
|
| 243 | - * |
|
| 244 | - * @param string $hash_salt required for some payment gateways |
|
| 245 | - * @throws EE_Error |
|
| 246 | - * @throws InvalidArgumentException |
|
| 247 | - * @throws InvalidDataTypeException |
|
| 248 | - * @throws InvalidInterfaceException |
|
| 249 | - * @throws ReflectionException |
|
| 250 | - */ |
|
| 251 | - public function set_hash_salt($hash_salt = '') |
|
| 252 | - { |
|
| 253 | - $this->set('TXN_hash_salt', $hash_salt); |
|
| 254 | - } |
|
| 255 | - |
|
| 256 | - |
|
| 257 | - /** |
|
| 258 | - * Sets TXN_reg_steps array |
|
| 259 | - * |
|
| 260 | - * @param array $txn_reg_steps |
|
| 261 | - * @throws EE_Error |
|
| 262 | - * @throws InvalidArgumentException |
|
| 263 | - * @throws InvalidDataTypeException |
|
| 264 | - * @throws InvalidInterfaceException |
|
| 265 | - * @throws ReflectionException |
|
| 266 | - */ |
|
| 267 | - public function set_reg_steps(array $txn_reg_steps) |
|
| 268 | - { |
|
| 269 | - $this->set('TXN_reg_steps', $txn_reg_steps); |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - |
|
| 273 | - /** |
|
| 274 | - * Gets TXN_reg_steps |
|
| 275 | - * |
|
| 276 | - * @return array |
|
| 277 | - * @throws EE_Error |
|
| 278 | - * @throws InvalidArgumentException |
|
| 279 | - * @throws InvalidDataTypeException |
|
| 280 | - * @throws InvalidInterfaceException |
|
| 281 | - * @throws ReflectionException |
|
| 282 | - */ |
|
| 283 | - public function reg_steps() |
|
| 284 | - { |
|
| 285 | - $TXN_reg_steps = $this->get('TXN_reg_steps'); |
|
| 286 | - return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array(); |
|
| 287 | - } |
|
| 288 | - |
|
| 289 | - |
|
| 290 | - /** |
|
| 291 | - * @return string of transaction's total cost, with currency symbol and decimal |
|
| 292 | - * @throws EE_Error |
|
| 293 | - * @throws InvalidArgumentException |
|
| 294 | - * @throws InvalidDataTypeException |
|
| 295 | - * @throws InvalidInterfaceException |
|
| 296 | - * @throws ReflectionException |
|
| 297 | - */ |
|
| 298 | - public function pretty_total() |
|
| 299 | - { |
|
| 300 | - return $this->get_pretty('TXN_total'); |
|
| 301 | - } |
|
| 302 | - |
|
| 303 | - |
|
| 304 | - /** |
|
| 305 | - * Gets the amount paid in a pretty string (formatted and with currency symbol) |
|
| 306 | - * |
|
| 307 | - * @return string |
|
| 308 | - * @throws EE_Error |
|
| 309 | - * @throws InvalidArgumentException |
|
| 310 | - * @throws InvalidDataTypeException |
|
| 311 | - * @throws InvalidInterfaceException |
|
| 312 | - * @throws ReflectionException |
|
| 313 | - */ |
|
| 314 | - public function pretty_paid() |
|
| 315 | - { |
|
| 316 | - return $this->get_pretty('TXN_paid'); |
|
| 317 | - } |
|
| 318 | - |
|
| 319 | - |
|
| 320 | - /** |
|
| 321 | - * calculate the amount remaining for this transaction and return; |
|
| 322 | - * |
|
| 323 | - * @return float amount remaining |
|
| 324 | - * @throws EE_Error |
|
| 325 | - * @throws InvalidArgumentException |
|
| 326 | - * @throws InvalidDataTypeException |
|
| 327 | - * @throws InvalidInterfaceException |
|
| 328 | - * @throws ReflectionException |
|
| 329 | - */ |
|
| 330 | - public function remaining() |
|
| 331 | - { |
|
| 332 | - return $this->total() - $this->paid(); |
|
| 333 | - } |
|
| 334 | - |
|
| 335 | - |
|
| 336 | - /** |
|
| 337 | - * get Transaction Total |
|
| 338 | - * |
|
| 339 | - * @return float |
|
| 340 | - * @throws EE_Error |
|
| 341 | - * @throws InvalidArgumentException |
|
| 342 | - * @throws InvalidDataTypeException |
|
| 343 | - * @throws InvalidInterfaceException |
|
| 344 | - * @throws ReflectionException |
|
| 345 | - */ |
|
| 346 | - public function total() |
|
| 347 | - { |
|
| 348 | - return (float) $this->get('TXN_total'); |
|
| 349 | - } |
|
| 350 | - |
|
| 351 | - |
|
| 352 | - /** |
|
| 353 | - * get Total Amount Paid to Date |
|
| 354 | - * |
|
| 355 | - * @return float |
|
| 356 | - * @throws EE_Error |
|
| 357 | - * @throws InvalidArgumentException |
|
| 358 | - * @throws InvalidDataTypeException |
|
| 359 | - * @throws InvalidInterfaceException |
|
| 360 | - * @throws ReflectionException |
|
| 361 | - */ |
|
| 362 | - public function paid() |
|
| 363 | - { |
|
| 364 | - return (float) $this->get('TXN_paid'); |
|
| 365 | - } |
|
| 366 | - |
|
| 367 | - |
|
| 368 | - /** |
|
| 369 | - * @return mixed|null |
|
| 370 | - * @throws EE_Error |
|
| 371 | - * @throws InvalidArgumentException |
|
| 372 | - * @throws InvalidDataTypeException |
|
| 373 | - * @throws InvalidInterfaceException |
|
| 374 | - * @throws ReflectionException |
|
| 375 | - */ |
|
| 376 | - public function get_cart_session() |
|
| 377 | - { |
|
| 378 | - $session_data = (array) $this->get('TXN_session_data'); |
|
| 379 | - return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart |
|
| 380 | - ? $session_data['cart'] |
|
| 381 | - : null; |
|
| 382 | - } |
|
| 383 | - |
|
| 384 | - |
|
| 385 | - /** |
|
| 386 | - * get Transaction session data |
|
| 387 | - * |
|
| 388 | - * @return array|mixed |
|
| 389 | - * @throws EE_Error |
|
| 390 | - * @throws InvalidArgumentException |
|
| 391 | - * @throws InvalidDataTypeException |
|
| 392 | - * @throws InvalidInterfaceException |
|
| 393 | - * @throws ReflectionException |
|
| 394 | - */ |
|
| 395 | - public function session_data() |
|
| 396 | - { |
|
| 397 | - $session_data = $this->get('TXN_session_data'); |
|
| 398 | - if (empty($session_data)) { |
|
| 399 | - $session_data = array( |
|
| 400 | - 'id' => null, |
|
| 401 | - 'user_id' => null, |
|
| 402 | - 'ip_address' => null, |
|
| 403 | - 'user_agent' => null, |
|
| 404 | - 'init_access' => null, |
|
| 405 | - 'last_access' => null, |
|
| 406 | - 'pages_visited' => array(), |
|
| 407 | - ); |
|
| 408 | - } |
|
| 409 | - return $session_data; |
|
| 410 | - } |
|
| 411 | - |
|
| 412 | - |
|
| 413 | - /** |
|
| 414 | - * Set session data within the TXN object |
|
| 415 | - * |
|
| 416 | - * @param EE_Session|array $session_data |
|
| 417 | - * @throws EE_Error |
|
| 418 | - * @throws InvalidArgumentException |
|
| 419 | - * @throws InvalidDataTypeException |
|
| 420 | - * @throws InvalidInterfaceException |
|
| 421 | - * @throws ReflectionException |
|
| 422 | - */ |
|
| 423 | - public function set_txn_session_data($session_data) |
|
| 424 | - { |
|
| 425 | - if ($session_data instanceof EE_Session) { |
|
| 426 | - $this->set('TXN_session_data', $session_data->get_session_data(null, true)); |
|
| 427 | - } else { |
|
| 428 | - $this->set('TXN_session_data', $session_data); |
|
| 429 | - } |
|
| 430 | - } |
|
| 431 | - |
|
| 432 | - |
|
| 433 | - /** |
|
| 434 | - * get Transaction hash salt |
|
| 435 | - * |
|
| 436 | - * @return mixed |
|
| 437 | - * @throws EE_Error |
|
| 438 | - * @throws InvalidArgumentException |
|
| 439 | - * @throws InvalidDataTypeException |
|
| 440 | - * @throws InvalidInterfaceException |
|
| 441 | - * @throws ReflectionException |
|
| 442 | - */ |
|
| 443 | - public function hash_salt_() |
|
| 444 | - { |
|
| 445 | - return $this->get('TXN_hash_salt'); |
|
| 446 | - } |
|
| 447 | - |
|
| 448 | - |
|
| 449 | - /** |
|
| 450 | - * Returns the transaction datetime as either: |
|
| 451 | - * - unix timestamp format ($format = false, $gmt = true) |
|
| 452 | - * - formatted date string including the UTC (timezone) offset ($format = true ($gmt |
|
| 453 | - * has no affect with this option)), this also may include a timezone abbreviation if the |
|
| 454 | - * set timezone in this class differs from what the timezone is on the blog. |
|
| 455 | - * - formatted date string including the UTC (timezone) offset (default). |
|
| 456 | - * |
|
| 457 | - * @param boolean $format - whether to return a unix timestamp (default) or formatted date string |
|
| 458 | - * @param boolean $gmt - whether to return a unix timestamp with UTC offset applied (default) |
|
| 459 | - * or no UTC offset applied |
|
| 460 | - * @return string | int |
|
| 461 | - * @throws EE_Error |
|
| 462 | - * @throws InvalidArgumentException |
|
| 463 | - * @throws InvalidDataTypeException |
|
| 464 | - * @throws InvalidInterfaceException |
|
| 465 | - * @throws ReflectionException |
|
| 466 | - */ |
|
| 467 | - public function datetime($format = false, $gmt = false) |
|
| 468 | - { |
|
| 469 | - if ($format) { |
|
| 470 | - return $this->get_pretty('TXN_timestamp'); |
|
| 471 | - } |
|
| 472 | - if ($gmt) { |
|
| 473 | - return $this->get_raw('TXN_timestamp'); |
|
| 474 | - } |
|
| 475 | - return $this->get('TXN_timestamp'); |
|
| 476 | - } |
|
| 477 | - |
|
| 478 | - |
|
| 479 | - /** |
|
| 480 | - * Gets registrations on this transaction |
|
| 481 | - * |
|
| 482 | - * @param array $query_params array of query parameters |
|
| 483 | - * @param boolean $get_cached TRUE to retrieve cached registrations or FALSE to pull from the db |
|
| 484 | - * @return EE_Base_Class[]|EE_Registration[] |
|
| 485 | - * @throws EE_Error |
|
| 486 | - * @throws InvalidArgumentException |
|
| 487 | - * @throws InvalidDataTypeException |
|
| 488 | - * @throws InvalidInterfaceException |
|
| 489 | - * @throws ReflectionException |
|
| 490 | - */ |
|
| 491 | - public function registrations($query_params = array(), $get_cached = false) |
|
| 492 | - { |
|
| 493 | - $query_params = (empty($query_params) || ! is_array($query_params)) |
|
| 494 | - ? array( |
|
| 495 | - 'order_by' => array( |
|
| 496 | - 'Event.EVT_name' => 'ASC', |
|
| 497 | - 'Attendee.ATT_lname' => 'ASC', |
|
| 498 | - 'Attendee.ATT_fname' => 'ASC', |
|
| 499 | - ), |
|
| 500 | - ) |
|
| 501 | - : $query_params; |
|
| 502 | - $query_params = $get_cached ? array() : $query_params; |
|
| 503 | - return $this->get_many_related('Registration', $query_params); |
|
| 504 | - } |
|
| 505 | - |
|
| 506 | - |
|
| 507 | - /** |
|
| 508 | - * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event |
|
| 509 | - * function for getting attendees and how many registrations they each have for an event) |
|
| 510 | - * |
|
| 511 | - * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT' |
|
| 512 | - * @throws EE_Error |
|
| 513 | - * @throws InvalidArgumentException |
|
| 514 | - * @throws InvalidDataTypeException |
|
| 515 | - * @throws InvalidInterfaceException |
|
| 516 | - * @throws ReflectionException |
|
| 517 | - */ |
|
| 518 | - public function attendees() |
|
| 519 | - { |
|
| 520 | - return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID()))); |
|
| 521 | - } |
|
| 522 | - |
|
| 523 | - |
|
| 524 | - /** |
|
| 525 | - * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default |
|
| 526 | - * |
|
| 527 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 528 | - * @return EE_Base_Class[]|EE_Payment[] |
|
| 529 | - * @throws EE_Error |
|
| 530 | - * @throws InvalidArgumentException |
|
| 531 | - * @throws InvalidDataTypeException |
|
| 532 | - * @throws InvalidInterfaceException |
|
| 533 | - * @throws ReflectionException |
|
| 534 | - */ |
|
| 535 | - public function payments($query_params = array()) |
|
| 536 | - { |
|
| 537 | - return $this->get_many_related('Payment', $query_params); |
|
| 538 | - } |
|
| 539 | - |
|
| 540 | - |
|
| 541 | - /** |
|
| 542 | - * gets only approved payments for this transaction |
|
| 543 | - * |
|
| 544 | - * @return EE_Base_Class[]|EE_Payment[] |
|
| 545 | - * @throws EE_Error |
|
| 546 | - * @throws InvalidArgumentException |
|
| 547 | - * @throws ReflectionException |
|
| 548 | - * @throws InvalidDataTypeException |
|
| 549 | - * @throws InvalidInterfaceException |
|
| 550 | - */ |
|
| 551 | - public function approved_payments() |
|
| 552 | - { |
|
| 553 | - EE_Registry::instance()->load_model('Payment'); |
|
| 554 | - return $this->get_many_related( |
|
| 555 | - 'Payment', |
|
| 556 | - array( |
|
| 557 | - array('STS_ID' => EEM_Payment::status_id_approved), |
|
| 558 | - 'order_by' => array('PAY_timestamp' => 'DESC'), |
|
| 559 | - ) |
|
| 560 | - ); |
|
| 561 | - } |
|
| 562 | - |
|
| 563 | - |
|
| 564 | - /** |
|
| 565 | - * Gets all payments which have not been approved |
|
| 566 | - * |
|
| 567 | - * @return EE_Base_Class[]|EEI_Payment[] |
|
| 568 | - * @throws EE_Error if a model is misconfigured somehow |
|
| 569 | - * @throws InvalidArgumentException |
|
| 570 | - * @throws InvalidDataTypeException |
|
| 571 | - * @throws InvalidInterfaceException |
|
| 572 | - * @throws ReflectionException |
|
| 573 | - */ |
|
| 574 | - public function pending_payments() |
|
| 575 | - { |
|
| 576 | - return $this->get_many_related( |
|
| 577 | - 'Payment', |
|
| 578 | - array( |
|
| 579 | - array( |
|
| 580 | - 'STS_ID' => EEM_Payment::status_id_pending, |
|
| 581 | - ), |
|
| 582 | - 'order_by' => array( |
|
| 583 | - 'PAY_timestamp' => 'DESC', |
|
| 584 | - ), |
|
| 585 | - ) |
|
| 586 | - ); |
|
| 587 | - } |
|
| 588 | - |
|
| 589 | - |
|
| 590 | - /** |
|
| 591 | - * echoes $this->pretty_status() |
|
| 592 | - * |
|
| 593 | - * @param bool $show_icons |
|
| 594 | - * @throws EE_Error |
|
| 595 | - * @throws InvalidArgumentException |
|
| 596 | - * @throws InvalidDataTypeException |
|
| 597 | - * @throws InvalidInterfaceException |
|
| 598 | - * @throws ReflectionException |
|
| 599 | - */ |
|
| 600 | - public function e_pretty_status($show_icons = false) |
|
| 601 | - { |
|
| 602 | - echo $this->pretty_status($show_icons); |
|
| 603 | - } |
|
| 604 | - |
|
| 605 | - |
|
| 606 | - /** |
|
| 607 | - * returns a pretty version of the status, good for displaying to users |
|
| 608 | - * |
|
| 609 | - * @param bool $show_icons |
|
| 610 | - * @return string |
|
| 611 | - * @throws EE_Error |
|
| 612 | - * @throws InvalidArgumentException |
|
| 613 | - * @throws InvalidDataTypeException |
|
| 614 | - * @throws InvalidInterfaceException |
|
| 615 | - * @throws ReflectionException |
|
| 616 | - */ |
|
| 617 | - public function pretty_status($show_icons = false) |
|
| 618 | - { |
|
| 619 | - $status = EEM_Status::instance()->localized_status( |
|
| 620 | - array($this->status_ID() => __('unknown', 'event_espresso')), |
|
| 621 | - false, |
|
| 622 | - 'sentence' |
|
| 623 | - ); |
|
| 624 | - $icon = ''; |
|
| 625 | - switch ($this->status_ID()) { |
|
| 626 | - case EEM_Transaction::complete_status_code: |
|
| 627 | - $icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : ''; |
|
| 628 | - break; |
|
| 629 | - case EEM_Transaction::incomplete_status_code: |
|
| 630 | - $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>' |
|
| 631 | - : ''; |
|
| 632 | - break; |
|
| 633 | - case EEM_Transaction::abandoned_status_code: |
|
| 634 | - $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : ''; |
|
| 635 | - break; |
|
| 636 | - case EEM_Transaction::failed_status_code: |
|
| 637 | - $icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : ''; |
|
| 638 | - break; |
|
| 639 | - case EEM_Transaction::overpaid_status_code: |
|
| 640 | - $icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : ''; |
|
| 641 | - break; |
|
| 642 | - } |
|
| 643 | - return $icon . $status[ $this->status_ID() ]; |
|
| 644 | - } |
|
| 645 | - |
|
| 646 | - |
|
| 647 | - /** |
|
| 648 | - * get Transaction Status |
|
| 649 | - * |
|
| 650 | - * @return mixed |
|
| 651 | - * @throws EE_Error |
|
| 652 | - * @throws InvalidArgumentException |
|
| 653 | - * @throws InvalidDataTypeException |
|
| 654 | - * @throws InvalidInterfaceException |
|
| 655 | - * @throws ReflectionException |
|
| 656 | - */ |
|
| 657 | - public function status_ID() |
|
| 658 | - { |
|
| 659 | - return $this->get('STS_ID'); |
|
| 660 | - } |
|
| 661 | - |
|
| 662 | - |
|
| 663 | - /** |
|
| 664 | - * Returns TRUE or FALSE for whether or not this transaction cost any money |
|
| 665 | - * |
|
| 666 | - * @return boolean |
|
| 667 | - * @throws EE_Error |
|
| 668 | - * @throws InvalidArgumentException |
|
| 669 | - * @throws InvalidDataTypeException |
|
| 670 | - * @throws InvalidInterfaceException |
|
| 671 | - * @throws ReflectionException |
|
| 672 | - */ |
|
| 673 | - public function is_free() |
|
| 674 | - { |
|
| 675 | - return EEH_Money::compare_floats($this->get('TXN_total'), 0, '=='); |
|
| 676 | - } |
|
| 677 | - |
|
| 678 | - |
|
| 679 | - /** |
|
| 680 | - * Returns whether this transaction is complete |
|
| 681 | - * Useful in templates and other logic for deciding if we should ask for another payment... |
|
| 682 | - * |
|
| 683 | - * @return boolean |
|
| 684 | - * @throws EE_Error |
|
| 685 | - * @throws InvalidArgumentException |
|
| 686 | - * @throws InvalidDataTypeException |
|
| 687 | - * @throws InvalidInterfaceException |
|
| 688 | - * @throws ReflectionException |
|
| 689 | - */ |
|
| 690 | - public function is_completed() |
|
| 691 | - { |
|
| 692 | - return $this->status_ID() === EEM_Transaction::complete_status_code; |
|
| 693 | - } |
|
| 694 | - |
|
| 695 | - |
|
| 696 | - /** |
|
| 697 | - * Returns whether this transaction is incomplete |
|
| 698 | - * Useful in templates and other logic for deciding if we should ask for another payment... |
|
| 699 | - * |
|
| 700 | - * @return boolean |
|
| 701 | - * @throws EE_Error |
|
| 702 | - * @throws InvalidArgumentException |
|
| 703 | - * @throws InvalidDataTypeException |
|
| 704 | - * @throws InvalidInterfaceException |
|
| 705 | - * @throws ReflectionException |
|
| 706 | - */ |
|
| 707 | - public function is_incomplete() |
|
| 708 | - { |
|
| 709 | - return $this->status_ID() === EEM_Transaction::incomplete_status_code; |
|
| 710 | - } |
|
| 711 | - |
|
| 712 | - |
|
| 713 | - /** |
|
| 714 | - * Returns whether this transaction is overpaid |
|
| 715 | - * Useful in templates and other logic for deciding if monies need to be refunded |
|
| 716 | - * |
|
| 717 | - * @return boolean |
|
| 718 | - * @throws EE_Error |
|
| 719 | - * @throws InvalidArgumentException |
|
| 720 | - * @throws InvalidDataTypeException |
|
| 721 | - * @throws InvalidInterfaceException |
|
| 722 | - * @throws ReflectionException |
|
| 723 | - */ |
|
| 724 | - public function is_overpaid() |
|
| 725 | - { |
|
| 726 | - return $this->status_ID() === EEM_Transaction::overpaid_status_code; |
|
| 727 | - } |
|
| 728 | - |
|
| 729 | - |
|
| 730 | - /** |
|
| 731 | - * Returns whether this transaction was abandoned |
|
| 732 | - * meaning that the transaction/registration process was somehow interrupted and never completed |
|
| 733 | - * but that contact information exists for at least one registrant |
|
| 734 | - * |
|
| 735 | - * @return boolean |
|
| 736 | - * @throws EE_Error |
|
| 737 | - * @throws InvalidArgumentException |
|
| 738 | - * @throws InvalidDataTypeException |
|
| 739 | - * @throws InvalidInterfaceException |
|
| 740 | - * @throws ReflectionException |
|
| 741 | - */ |
|
| 742 | - public function is_abandoned() |
|
| 743 | - { |
|
| 744 | - return $this->status_ID() === EEM_Transaction::abandoned_status_code; |
|
| 745 | - } |
|
| 746 | - |
|
| 747 | - |
|
| 748 | - /** |
|
| 749 | - * Returns whether this transaction failed |
|
| 750 | - * meaning that the transaction/registration process was somehow interrupted and never completed |
|
| 751 | - * and that NO contact information exists for any registrants |
|
| 752 | - * |
|
| 753 | - * @return boolean |
|
| 754 | - * @throws EE_Error |
|
| 755 | - * @throws InvalidArgumentException |
|
| 756 | - * @throws InvalidDataTypeException |
|
| 757 | - * @throws InvalidInterfaceException |
|
| 758 | - * @throws ReflectionException |
|
| 759 | - */ |
|
| 760 | - public function failed() |
|
| 761 | - { |
|
| 762 | - return $this->status_ID() === EEM_Transaction::failed_status_code; |
|
| 763 | - } |
|
| 764 | - |
|
| 765 | - |
|
| 766 | - /** |
|
| 767 | - * This returns the url for the invoice of this transaction |
|
| 768 | - * |
|
| 769 | - * @param string $type 'html' or 'pdf' (default is pdf) |
|
| 770 | - * @return string |
|
| 771 | - * @throws EE_Error |
|
| 772 | - * @throws InvalidArgumentException |
|
| 773 | - * @throws InvalidDataTypeException |
|
| 774 | - * @throws InvalidInterfaceException |
|
| 775 | - * @throws ReflectionException |
|
| 776 | - */ |
|
| 777 | - public function invoice_url($type = 'html') |
|
| 778 | - { |
|
| 779 | - $REG = $this->primary_registration(); |
|
| 780 | - if (! $REG instanceof EE_Registration) { |
|
| 781 | - return ''; |
|
| 782 | - } |
|
| 783 | - return $REG->invoice_url($type); |
|
| 784 | - } |
|
| 785 | - |
|
| 786 | - |
|
| 787 | - /** |
|
| 788 | - * Gets the primary registration only |
|
| 789 | - * |
|
| 790 | - * @return EE_Base_Class|EE_Registration |
|
| 791 | - * @throws EE_Error |
|
| 792 | - * @throws InvalidArgumentException |
|
| 793 | - * @throws InvalidDataTypeException |
|
| 794 | - * @throws InvalidInterfaceException |
|
| 795 | - * @throws ReflectionException |
|
| 796 | - */ |
|
| 797 | - public function primary_registration() |
|
| 798 | - { |
|
| 799 | - $registrations = (array) $this->get_many_related( |
|
| 800 | - 'Registration', |
|
| 801 | - array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT)) |
|
| 802 | - ); |
|
| 803 | - foreach ($registrations as $registration) { |
|
| 804 | - // valid registration that is NOT cancelled or declined ? |
|
| 805 | - if ($registration instanceof EE_Registration |
|
| 806 | - && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true) |
|
| 807 | - ) { |
|
| 808 | - return $registration; |
|
| 809 | - } |
|
| 810 | - } |
|
| 811 | - // nothing valid found, so just return first thing from array of results |
|
| 812 | - return reset($registrations); |
|
| 813 | - } |
|
| 814 | - |
|
| 815 | - |
|
| 816 | - /** |
|
| 817 | - * Gets the URL for viewing the receipt |
|
| 818 | - * |
|
| 819 | - * @param string $type 'pdf' or 'html' (default is 'html') |
|
| 820 | - * @return string |
|
| 821 | - * @throws EE_Error |
|
| 822 | - * @throws InvalidArgumentException |
|
| 823 | - * @throws InvalidDataTypeException |
|
| 824 | - * @throws InvalidInterfaceException |
|
| 825 | - * @throws ReflectionException |
|
| 826 | - */ |
|
| 827 | - public function receipt_url($type = 'html') |
|
| 828 | - { |
|
| 829 | - $REG = $this->primary_registration(); |
|
| 830 | - if (! $REG instanceof EE_Registration) { |
|
| 831 | - return ''; |
|
| 832 | - } |
|
| 833 | - return $REG->receipt_url($type); |
|
| 834 | - } |
|
| 835 | - |
|
| 836 | - |
|
| 837 | - /** |
|
| 838 | - * Gets the URL of the thank you page with this registration REG_url_link added as |
|
| 839 | - * a query parameter |
|
| 840 | - * |
|
| 841 | - * @return string |
|
| 842 | - * @throws EE_Error |
|
| 843 | - * @throws InvalidArgumentException |
|
| 844 | - * @throws InvalidDataTypeException |
|
| 845 | - * @throws InvalidInterfaceException |
|
| 846 | - * @throws ReflectionException |
|
| 847 | - */ |
|
| 848 | - public function payment_overview_url() |
|
| 849 | - { |
|
| 850 | - $primary_registration = $this->primary_registration(); |
|
| 851 | - return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false; |
|
| 852 | - } |
|
| 853 | - |
|
| 854 | - |
|
| 855 | - /** |
|
| 856 | - * @return string |
|
| 857 | - * @throws EE_Error |
|
| 858 | - * @throws InvalidArgumentException |
|
| 859 | - * @throws InvalidDataTypeException |
|
| 860 | - * @throws InvalidInterfaceException |
|
| 861 | - * @throws ReflectionException |
|
| 862 | - */ |
|
| 863 | - public function gateway_response_on_transaction() |
|
| 864 | - { |
|
| 865 | - $payment = $this->get_first_related('Payment'); |
|
| 866 | - return $payment instanceof EE_Payment ? $payment->gateway_response() : ''; |
|
| 867 | - } |
|
| 868 | - |
|
| 869 | - |
|
| 870 | - /** |
|
| 871 | - * Get the status object of this object |
|
| 872 | - * |
|
| 873 | - * @return EE_Base_Class|EE_Status |
|
| 874 | - * @throws EE_Error |
|
| 875 | - * @throws InvalidArgumentException |
|
| 876 | - * @throws InvalidDataTypeException |
|
| 877 | - * @throws InvalidInterfaceException |
|
| 878 | - * @throws ReflectionException |
|
| 879 | - */ |
|
| 880 | - public function status_obj() |
|
| 881 | - { |
|
| 882 | - return $this->get_first_related('Status'); |
|
| 883 | - } |
|
| 884 | - |
|
| 885 | - |
|
| 886 | - /** |
|
| 887 | - * Gets all the extra meta info on this payment |
|
| 888 | - * |
|
| 889 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 890 | - * @return EE_Base_Class[]|EE_Extra_Meta |
|
| 891 | - * @throws EE_Error |
|
| 892 | - * @throws InvalidArgumentException |
|
| 893 | - * @throws InvalidDataTypeException |
|
| 894 | - * @throws InvalidInterfaceException |
|
| 895 | - * @throws ReflectionException |
|
| 896 | - */ |
|
| 897 | - public function extra_meta($query_params = array()) |
|
| 898 | - { |
|
| 899 | - return $this->get_many_related('Extra_Meta', $query_params); |
|
| 900 | - } |
|
| 901 | - |
|
| 902 | - |
|
| 903 | - /** |
|
| 904 | - * Wrapper for _add_relation_to |
|
| 905 | - * |
|
| 906 | - * @param EE_Registration $registration |
|
| 907 | - * @return EE_Base_Class the relation was added to |
|
| 908 | - * @throws EE_Error |
|
| 909 | - * @throws InvalidArgumentException |
|
| 910 | - * @throws InvalidDataTypeException |
|
| 911 | - * @throws InvalidInterfaceException |
|
| 912 | - * @throws ReflectionException |
|
| 913 | - */ |
|
| 914 | - public function add_registration(EE_Registration $registration) |
|
| 915 | - { |
|
| 916 | - return $this->_add_relation_to($registration, 'Registration'); |
|
| 917 | - } |
|
| 918 | - |
|
| 919 | - |
|
| 920 | - /** |
|
| 921 | - * Removes the given registration from being related (even before saving this transaction). |
|
| 922 | - * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations |
|
| 923 | - * |
|
| 924 | - * @param int $registration_or_id |
|
| 925 | - * @return EE_Base_Class that was removed from being related |
|
| 926 | - * @throws EE_Error |
|
| 927 | - * @throws InvalidArgumentException |
|
| 928 | - * @throws InvalidDataTypeException |
|
| 929 | - * @throws InvalidInterfaceException |
|
| 930 | - * @throws ReflectionException |
|
| 931 | - */ |
|
| 932 | - public function remove_registration_with_id($registration_or_id) |
|
| 933 | - { |
|
| 934 | - return $this->_remove_relation_to($registration_or_id, 'Registration'); |
|
| 935 | - } |
|
| 936 | - |
|
| 937 | - |
|
| 938 | - /** |
|
| 939 | - * Gets all the line items which are for ACTUAL items |
|
| 940 | - * |
|
| 941 | - * @return EE_Line_Item[] |
|
| 942 | - * @throws EE_Error |
|
| 943 | - * @throws InvalidArgumentException |
|
| 944 | - * @throws InvalidDataTypeException |
|
| 945 | - * @throws InvalidInterfaceException |
|
| 946 | - * @throws ReflectionException |
|
| 947 | - */ |
|
| 948 | - public function items_purchased() |
|
| 949 | - { |
|
| 950 | - return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item))); |
|
| 951 | - } |
|
| 952 | - |
|
| 953 | - |
|
| 954 | - /** |
|
| 955 | - * Wrapper for _add_relation_to |
|
| 956 | - * |
|
| 957 | - * @param EE_Line_Item $line_item |
|
| 958 | - * @return EE_Base_Class the relation was added to |
|
| 959 | - * @throws EE_Error |
|
| 960 | - * @throws InvalidArgumentException |
|
| 961 | - * @throws InvalidDataTypeException |
|
| 962 | - * @throws InvalidInterfaceException |
|
| 963 | - * @throws ReflectionException |
|
| 964 | - */ |
|
| 965 | - public function add_line_item(EE_Line_Item $line_item) |
|
| 966 | - { |
|
| 967 | - return $this->_add_relation_to($line_item, 'Line_Item'); |
|
| 968 | - } |
|
| 969 | - |
|
| 970 | - |
|
| 971 | - /** |
|
| 972 | - * Gets ALL the line items related to this transaction (unstructured) |
|
| 973 | - * |
|
| 974 | - * @param array $query_params |
|
| 975 | - * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 976 | - * @throws EE_Error |
|
| 977 | - * @throws InvalidArgumentException |
|
| 978 | - * @throws InvalidDataTypeException |
|
| 979 | - * @throws InvalidInterfaceException |
|
| 980 | - * @throws ReflectionException |
|
| 981 | - */ |
|
| 982 | - public function line_items($query_params = array()) |
|
| 983 | - { |
|
| 984 | - return $this->get_many_related('Line_Item', $query_params); |
|
| 985 | - } |
|
| 986 | - |
|
| 987 | - |
|
| 988 | - /** |
|
| 989 | - * Gets all the line items which are taxes on the total |
|
| 990 | - * |
|
| 991 | - * @return EE_Line_Item[] |
|
| 992 | - * @throws EE_Error |
|
| 993 | - * @throws InvalidArgumentException |
|
| 994 | - * @throws InvalidDataTypeException |
|
| 995 | - * @throws InvalidInterfaceException |
|
| 996 | - * @throws ReflectionException |
|
| 997 | - */ |
|
| 998 | - public function tax_items() |
|
| 999 | - { |
|
| 1000 | - return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax))); |
|
| 1001 | - } |
|
| 1002 | - |
|
| 1003 | - |
|
| 1004 | - /** |
|
| 1005 | - * Gets the total line item (which is a parent of all other related line items, |
|
| 1006 | - * meaning it takes them all into account on its total) |
|
| 1007 | - * |
|
| 1008 | - * @param bool $create_if_not_found |
|
| 1009 | - * @return \EE_Line_Item |
|
| 1010 | - * @throws EE_Error |
|
| 1011 | - * @throws InvalidArgumentException |
|
| 1012 | - * @throws InvalidDataTypeException |
|
| 1013 | - * @throws InvalidInterfaceException |
|
| 1014 | - * @throws ReflectionException |
|
| 1015 | - */ |
|
| 1016 | - public function total_line_item($create_if_not_found = true) |
|
| 1017 | - { |
|
| 1018 | - $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total))); |
|
| 1019 | - if (! $item && $create_if_not_found) { |
|
| 1020 | - $item = EEH_Line_Item::create_total_line_item($this); |
|
| 1021 | - } |
|
| 1022 | - return $item; |
|
| 1023 | - } |
|
| 1024 | - |
|
| 1025 | - |
|
| 1026 | - /** |
|
| 1027 | - * Returns the total amount of tax on this transaction |
|
| 1028 | - * (assumes there's only one tax subtotal line item) |
|
| 1029 | - * |
|
| 1030 | - * @return float |
|
| 1031 | - * @throws EE_Error |
|
| 1032 | - * @throws InvalidArgumentException |
|
| 1033 | - * @throws InvalidDataTypeException |
|
| 1034 | - * @throws InvalidInterfaceException |
|
| 1035 | - * @throws ReflectionException |
|
| 1036 | - */ |
|
| 1037 | - public function tax_total() |
|
| 1038 | - { |
|
| 1039 | - $tax_line_item = $this->tax_total_line_item(); |
|
| 1040 | - if ($tax_line_item) { |
|
| 1041 | - return (float) $tax_line_item->total(); |
|
| 1042 | - } |
|
| 1043 | - return (float) 0; |
|
| 1044 | - } |
|
| 1045 | - |
|
| 1046 | - |
|
| 1047 | - /** |
|
| 1048 | - * Gets the tax subtotal line item (assumes there's only one) |
|
| 1049 | - * |
|
| 1050 | - * @return EE_Line_Item |
|
| 1051 | - * @throws EE_Error |
|
| 1052 | - * @throws InvalidArgumentException |
|
| 1053 | - * @throws InvalidDataTypeException |
|
| 1054 | - * @throws InvalidInterfaceException |
|
| 1055 | - * @throws ReflectionException |
|
| 1056 | - */ |
|
| 1057 | - public function tax_total_line_item() |
|
| 1058 | - { |
|
| 1059 | - return EEH_Line_Item::get_taxes_subtotal($this->total_line_item()); |
|
| 1060 | - } |
|
| 1061 | - |
|
| 1062 | - |
|
| 1063 | - /** |
|
| 1064 | - * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee. |
|
| 1065 | - * |
|
| 1066 | - * @return EE_Form_Section_Proper |
|
| 1067 | - * @throws EE_Error |
|
| 1068 | - * @throws InvalidArgumentException |
|
| 1069 | - * @throws InvalidDataTypeException |
|
| 1070 | - * @throws InvalidInterfaceException |
|
| 1071 | - * @throws ReflectionException |
|
| 1072 | - */ |
|
| 1073 | - public function billing_info() |
|
| 1074 | - { |
|
| 1075 | - $payment_method = $this->payment_method(); |
|
| 1076 | - if (! $payment_method) { |
|
| 1077 | - EE_Error::add_error( |
|
| 1078 | - __( |
|
| 1079 | - 'Could not find billing info for transaction because no gateway has been used for it yet', |
|
| 1080 | - 'event_espresso' |
|
| 1081 | - ), |
|
| 1082 | - __FILE__, |
|
| 1083 | - __FUNCTION__, |
|
| 1084 | - __LINE__ |
|
| 1085 | - ); |
|
| 1086 | - return null; |
|
| 1087 | - } |
|
| 1088 | - $primary_reg = $this->primary_registration(); |
|
| 1089 | - if (! $primary_reg) { |
|
| 1090 | - EE_Error::add_error( |
|
| 1091 | - __( |
|
| 1092 | - 'Cannot get billing info for gateway %s on transaction because no primary registration exists', |
|
| 1093 | - 'event_espresso' |
|
| 1094 | - ), |
|
| 1095 | - __FILE__, |
|
| 1096 | - __FUNCTION__, |
|
| 1097 | - __LINE__ |
|
| 1098 | - ); |
|
| 1099 | - return null; |
|
| 1100 | - } |
|
| 1101 | - $attendee = $primary_reg->attendee(); |
|
| 1102 | - if (! $attendee) { |
|
| 1103 | - EE_Error::add_error( |
|
| 1104 | - __( |
|
| 1105 | - 'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists', |
|
| 1106 | - 'event_espresso' |
|
| 1107 | - ), |
|
| 1108 | - __FILE__, |
|
| 1109 | - __FUNCTION__, |
|
| 1110 | - __LINE__ |
|
| 1111 | - ); |
|
| 1112 | - return null; |
|
| 1113 | - } |
|
| 1114 | - return $attendee->billing_info_for_payment_method($payment_method); |
|
| 1115 | - } |
|
| 1116 | - |
|
| 1117 | - |
|
| 1118 | - /** |
|
| 1119 | - * Gets PMD_ID |
|
| 1120 | - * |
|
| 1121 | - * @return int |
|
| 1122 | - * @throws EE_Error |
|
| 1123 | - * @throws InvalidArgumentException |
|
| 1124 | - * @throws InvalidDataTypeException |
|
| 1125 | - * @throws InvalidInterfaceException |
|
| 1126 | - * @throws ReflectionException |
|
| 1127 | - */ |
|
| 1128 | - public function payment_method_ID() |
|
| 1129 | - { |
|
| 1130 | - return $this->get('PMD_ID'); |
|
| 1131 | - } |
|
| 1132 | - |
|
| 1133 | - |
|
| 1134 | - /** |
|
| 1135 | - * Sets PMD_ID |
|
| 1136 | - * |
|
| 1137 | - * @param int $PMD_ID |
|
| 1138 | - * @throws EE_Error |
|
| 1139 | - * @throws InvalidArgumentException |
|
| 1140 | - * @throws InvalidDataTypeException |
|
| 1141 | - * @throws InvalidInterfaceException |
|
| 1142 | - * @throws ReflectionException |
|
| 1143 | - */ |
|
| 1144 | - public function set_payment_method_ID($PMD_ID) |
|
| 1145 | - { |
|
| 1146 | - $this->set('PMD_ID', $PMD_ID); |
|
| 1147 | - } |
|
| 1148 | - |
|
| 1149 | - |
|
| 1150 | - /** |
|
| 1151 | - * Gets the last-used payment method on this transaction |
|
| 1152 | - * (we COULD just use the last-made payment, but some payment methods, namely |
|
| 1153 | - * offline ones, dont' create payments) |
|
| 1154 | - * |
|
| 1155 | - * @return EE_Payment_Method |
|
| 1156 | - * @throws EE_Error |
|
| 1157 | - * @throws InvalidArgumentException |
|
| 1158 | - * @throws InvalidDataTypeException |
|
| 1159 | - * @throws InvalidInterfaceException |
|
| 1160 | - * @throws ReflectionException |
|
| 1161 | - */ |
|
| 1162 | - public function payment_method() |
|
| 1163 | - { |
|
| 1164 | - $pm = $this->get_first_related('Payment_Method'); |
|
| 1165 | - if ($pm instanceof EE_Payment_Method) { |
|
| 1166 | - return $pm; |
|
| 1167 | - } |
|
| 1168 | - $last_payment = $this->last_payment(); |
|
| 1169 | - if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) { |
|
| 1170 | - return $last_payment->payment_method(); |
|
| 1171 | - } |
|
| 1172 | - return null; |
|
| 1173 | - } |
|
| 1174 | - |
|
| 1175 | - |
|
| 1176 | - /** |
|
| 1177 | - * Gets the last payment made |
|
| 1178 | - * |
|
| 1179 | - * @return EE_Base_Class|EE_Payment |
|
| 1180 | - * @throws EE_Error |
|
| 1181 | - * @throws InvalidArgumentException |
|
| 1182 | - * @throws InvalidDataTypeException |
|
| 1183 | - * @throws InvalidInterfaceException |
|
| 1184 | - * @throws ReflectionException |
|
| 1185 | - */ |
|
| 1186 | - public function last_payment() |
|
| 1187 | - { |
|
| 1188 | - return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc'))); |
|
| 1189 | - } |
|
| 1190 | - |
|
| 1191 | - |
|
| 1192 | - /** |
|
| 1193 | - * Gets all the line items which are unrelated to tickets on this transaction |
|
| 1194 | - * |
|
| 1195 | - * @return EE_Line_Item[] |
|
| 1196 | - * @throws EE_Error |
|
| 1197 | - * @throws InvalidArgumentException |
|
| 1198 | - * @throws InvalidDataTypeException |
|
| 1199 | - * @throws InvalidInterfaceException |
|
| 1200 | - * @throws ReflectionException |
|
| 1201 | - */ |
|
| 1202 | - public function non_ticket_line_items() |
|
| 1203 | - { |
|
| 1204 | - return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID()); |
|
| 1205 | - } |
|
| 1206 | - |
|
| 1207 | - |
|
| 1208 | - /** |
|
| 1209 | - * possibly toggles TXN status |
|
| 1210 | - * |
|
| 1211 | - * @param boolean $update whether to save the TXN |
|
| 1212 | - * @return bool whether the TXN was saved |
|
| 1213 | - * @throws EE_Error |
|
| 1214 | - * @throws InvalidArgumentException |
|
| 1215 | - * @throws InvalidDataTypeException |
|
| 1216 | - * @throws InvalidInterfaceException |
|
| 1217 | - * @throws ReflectionException |
|
| 1218 | - * @throws RuntimeException |
|
| 1219 | - */ |
|
| 1220 | - public function update_status_based_on_total_paid($update = true) |
|
| 1221 | - { |
|
| 1222 | - // set transaction status based on comparison of TXN_paid vs TXN_total |
|
| 1223 | - if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) { |
|
| 1224 | - $new_txn_status = EEM_Transaction::overpaid_status_code; |
|
| 1225 | - } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) { |
|
| 1226 | - $new_txn_status = EEM_Transaction::complete_status_code; |
|
| 1227 | - } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) { |
|
| 1228 | - $new_txn_status = EEM_Transaction::incomplete_status_code; |
|
| 1229 | - } else { |
|
| 1230 | - throw new RuntimeException( |
|
| 1231 | - __('The total paid calculation for this transaction is inaccurate.', 'event_espresso') |
|
| 1232 | - ); |
|
| 1233 | - } |
|
| 1234 | - if ($new_txn_status !== $this->status_ID()) { |
|
| 1235 | - $this->set_status($new_txn_status); |
|
| 1236 | - if ($update) { |
|
| 1237 | - return $this->save() ? true : false; |
|
| 1238 | - } |
|
| 1239 | - } |
|
| 1240 | - return false; |
|
| 1241 | - } |
|
| 1242 | - |
|
| 1243 | - |
|
| 1244 | - /** |
|
| 1245 | - * Updates the transaction's status and total_paid based on all the payments |
|
| 1246 | - * that apply to it |
|
| 1247 | - * |
|
| 1248 | - * @deprecated |
|
| 1249 | - * @return array|bool |
|
| 1250 | - * @throws EE_Error |
|
| 1251 | - * @throws InvalidArgumentException |
|
| 1252 | - * @throws ReflectionException |
|
| 1253 | - * @throws InvalidDataTypeException |
|
| 1254 | - * @throws InvalidInterfaceException |
|
| 1255 | - */ |
|
| 1256 | - public function update_based_on_payments() |
|
| 1257 | - { |
|
| 1258 | - EE_Error::doing_it_wrong( |
|
| 1259 | - __CLASS__ . '::' . __FUNCTION__, |
|
| 1260 | - sprintf( |
|
| 1261 | - __('This method is deprecated. Please use "%s" instead', 'event_espresso'), |
|
| 1262 | - 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()' |
|
| 1263 | - ), |
|
| 1264 | - '4.6.0' |
|
| 1265 | - ); |
|
| 1266 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 1267 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 1268 | - return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this); |
|
| 1269 | - } |
|
| 1270 | - |
|
| 1271 | - |
|
| 1272 | - /** |
|
| 1273 | - * @return string |
|
| 1274 | - */ |
|
| 1275 | - public function old_txn_status() |
|
| 1276 | - { |
|
| 1277 | - return $this->_old_txn_status; |
|
| 1278 | - } |
|
| 1279 | - |
|
| 1280 | - |
|
| 1281 | - /** |
|
| 1282 | - * @param string $old_txn_status |
|
| 1283 | - */ |
|
| 1284 | - public function set_old_txn_status($old_txn_status) |
|
| 1285 | - { |
|
| 1286 | - // only set the first time |
|
| 1287 | - if ($this->_old_txn_status === null) { |
|
| 1288 | - $this->_old_txn_status = $old_txn_status; |
|
| 1289 | - } |
|
| 1290 | - } |
|
| 1291 | - |
|
| 1292 | - |
|
| 1293 | - /** |
|
| 1294 | - * reg_status_updated |
|
| 1295 | - * |
|
| 1296 | - * @return bool |
|
| 1297 | - * @throws EE_Error |
|
| 1298 | - * @throws InvalidArgumentException |
|
| 1299 | - * @throws InvalidDataTypeException |
|
| 1300 | - * @throws InvalidInterfaceException |
|
| 1301 | - * @throws ReflectionException |
|
| 1302 | - */ |
|
| 1303 | - public function txn_status_updated() |
|
| 1304 | - { |
|
| 1305 | - return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null; |
|
| 1306 | - } |
|
| 1307 | - |
|
| 1308 | - |
|
| 1309 | - /** |
|
| 1310 | - * _reg_steps_completed |
|
| 1311 | - * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed, |
|
| 1312 | - * if a $reg_step_slug is provided, then this step will be skipped when testing for completion |
|
| 1313 | - * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion |
|
| 1314 | - * |
|
| 1315 | - * @param string $reg_step_slug |
|
| 1316 | - * @param bool $check_all |
|
| 1317 | - * @return bool|int |
|
| 1318 | - * @throws EE_Error |
|
| 1319 | - * @throws InvalidArgumentException |
|
| 1320 | - * @throws InvalidDataTypeException |
|
| 1321 | - * @throws InvalidInterfaceException |
|
| 1322 | - * @throws ReflectionException |
|
| 1323 | - */ |
|
| 1324 | - private function _reg_steps_completed($reg_step_slug = '', $check_all = true) |
|
| 1325 | - { |
|
| 1326 | - $reg_steps = $this->reg_steps(); |
|
| 1327 | - if (! is_array($reg_steps) || empty($reg_steps)) { |
|
| 1328 | - return false; |
|
| 1329 | - } |
|
| 1330 | - // loop thru reg steps array) |
|
| 1331 | - foreach ($reg_steps as $slug => $reg_step_completed) { |
|
| 1332 | - // if NOT checking ALL steps (only checking one step) |
|
| 1333 | - if (! $check_all) { |
|
| 1334 | - // and this is the one |
|
| 1335 | - if ($slug === $reg_step_slug) { |
|
| 1336 | - return $reg_step_completed; |
|
| 1337 | - } |
|
| 1338 | - // skip to next reg step in loop |
|
| 1339 | - continue; |
|
| 1340 | - } |
|
| 1341 | - // $check_all must be true, else we would never have gotten to this point |
|
| 1342 | - if ($slug === $reg_step_slug) { |
|
| 1343 | - // if we reach this point, then we are testing either: |
|
| 1344 | - // all_reg_steps_completed_except() or |
|
| 1345 | - // all_reg_steps_completed_except_final_step(), |
|
| 1346 | - // and since this is the reg step EXCEPTION being tested |
|
| 1347 | - // we want to return true (yes true) if this reg step is NOT completed |
|
| 1348 | - // ie: "is everything completed except the final step?" |
|
| 1349 | - // "that is correct... the final step is not completed, but all others are." |
|
| 1350 | - return $reg_step_completed !== true; |
|
| 1351 | - } |
|
| 1352 | - if ($reg_step_completed !== true) { |
|
| 1353 | - // if any reg step is NOT completed, then ALL steps are not completed |
|
| 1354 | - return false; |
|
| 1355 | - } |
|
| 1356 | - } |
|
| 1357 | - return true; |
|
| 1358 | - } |
|
| 1359 | - |
|
| 1360 | - |
|
| 1361 | - /** |
|
| 1362 | - * all_reg_steps_completed |
|
| 1363 | - * returns: |
|
| 1364 | - * true if ALL reg steps have been marked as completed |
|
| 1365 | - * or false if any step is not completed |
|
| 1366 | - * |
|
| 1367 | - * @return bool |
|
| 1368 | - * @throws EE_Error |
|
| 1369 | - * @throws InvalidArgumentException |
|
| 1370 | - * @throws InvalidDataTypeException |
|
| 1371 | - * @throws InvalidInterfaceException |
|
| 1372 | - * @throws ReflectionException |
|
| 1373 | - */ |
|
| 1374 | - public function all_reg_steps_completed() |
|
| 1375 | - { |
|
| 1376 | - return $this->_reg_steps_completed(); |
|
| 1377 | - } |
|
| 1378 | - |
|
| 1379 | - |
|
| 1380 | - /** |
|
| 1381 | - * all_reg_steps_completed_except |
|
| 1382 | - * returns: |
|
| 1383 | - * true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed |
|
| 1384 | - * or false if any other step is not completed |
|
| 1385 | - * or false if ALL steps are completed including the exception you are testing !!! |
|
| 1386 | - * |
|
| 1387 | - * @param string $exception |
|
| 1388 | - * @return bool |
|
| 1389 | - * @throws EE_Error |
|
| 1390 | - * @throws InvalidArgumentException |
|
| 1391 | - * @throws InvalidDataTypeException |
|
| 1392 | - * @throws InvalidInterfaceException |
|
| 1393 | - * @throws ReflectionException |
|
| 1394 | - */ |
|
| 1395 | - public function all_reg_steps_completed_except($exception = '') |
|
| 1396 | - { |
|
| 1397 | - return $this->_reg_steps_completed($exception); |
|
| 1398 | - } |
|
| 1399 | - |
|
| 1400 | - |
|
| 1401 | - /** |
|
| 1402 | - * all_reg_steps_completed_except |
|
| 1403 | - * returns: |
|
| 1404 | - * true if ALL reg steps, except the final step, have been marked as completed |
|
| 1405 | - * or false if any step is not completed |
|
| 1406 | - * or false if ALL steps are completed including the final step !!! |
|
| 1407 | - * |
|
| 1408 | - * @return bool |
|
| 1409 | - * @throws EE_Error |
|
| 1410 | - * @throws InvalidArgumentException |
|
| 1411 | - * @throws InvalidDataTypeException |
|
| 1412 | - * @throws InvalidInterfaceException |
|
| 1413 | - * @throws ReflectionException |
|
| 1414 | - */ |
|
| 1415 | - public function all_reg_steps_completed_except_final_step() |
|
| 1416 | - { |
|
| 1417 | - return $this->_reg_steps_completed('finalize_registration'); |
|
| 1418 | - } |
|
| 1419 | - |
|
| 1420 | - |
|
| 1421 | - /** |
|
| 1422 | - * reg_step_completed |
|
| 1423 | - * returns: |
|
| 1424 | - * true if a specific reg step has been marked as completed |
|
| 1425 | - * a Unix timestamp if it has been initialized but not yet completed, |
|
| 1426 | - * or false if it has not yet been initialized |
|
| 1427 | - * |
|
| 1428 | - * @param string $reg_step_slug |
|
| 1429 | - * @return bool|int |
|
| 1430 | - * @throws EE_Error |
|
| 1431 | - * @throws InvalidArgumentException |
|
| 1432 | - * @throws InvalidDataTypeException |
|
| 1433 | - * @throws InvalidInterfaceException |
|
| 1434 | - * @throws ReflectionException |
|
| 1435 | - */ |
|
| 1436 | - public function reg_step_completed($reg_step_slug) |
|
| 1437 | - { |
|
| 1438 | - return $this->_reg_steps_completed($reg_step_slug, false); |
|
| 1439 | - } |
|
| 1440 | - |
|
| 1441 | - |
|
| 1442 | - /** |
|
| 1443 | - * completed_final_reg_step |
|
| 1444 | - * returns: |
|
| 1445 | - * true if the finalize_registration reg step has been marked as completed |
|
| 1446 | - * a Unix timestamp if it has been initialized but not yet completed, |
|
| 1447 | - * or false if it has not yet been initialized |
|
| 1448 | - * |
|
| 1449 | - * @return bool|int |
|
| 1450 | - * @throws EE_Error |
|
| 1451 | - * @throws InvalidArgumentException |
|
| 1452 | - * @throws InvalidDataTypeException |
|
| 1453 | - * @throws InvalidInterfaceException |
|
| 1454 | - * @throws ReflectionException |
|
| 1455 | - */ |
|
| 1456 | - public function final_reg_step_completed() |
|
| 1457 | - { |
|
| 1458 | - return $this->_reg_steps_completed('finalize_registration', false); |
|
| 1459 | - } |
|
| 1460 | - |
|
| 1461 | - |
|
| 1462 | - /** |
|
| 1463 | - * set_reg_step_initiated |
|
| 1464 | - * given a valid TXN_reg_step, this sets it's value to a unix timestamp |
|
| 1465 | - * |
|
| 1466 | - * @param string $reg_step_slug |
|
| 1467 | - * @return boolean |
|
| 1468 | - * @throws EE_Error |
|
| 1469 | - * @throws InvalidArgumentException |
|
| 1470 | - * @throws InvalidDataTypeException |
|
| 1471 | - * @throws InvalidInterfaceException |
|
| 1472 | - * @throws ReflectionException |
|
| 1473 | - */ |
|
| 1474 | - public function set_reg_step_initiated($reg_step_slug) |
|
| 1475 | - { |
|
| 1476 | - return $this->_set_reg_step_completed_status($reg_step_slug, time()); |
|
| 1477 | - } |
|
| 1478 | - |
|
| 1479 | - |
|
| 1480 | - /** |
|
| 1481 | - * set_reg_step_completed |
|
| 1482 | - * given a valid TXN_reg_step, this sets the step as completed |
|
| 1483 | - * |
|
| 1484 | - * @param string $reg_step_slug |
|
| 1485 | - * @return boolean |
|
| 1486 | - * @throws EE_Error |
|
| 1487 | - * @throws InvalidArgumentException |
|
| 1488 | - * @throws InvalidDataTypeException |
|
| 1489 | - * @throws InvalidInterfaceException |
|
| 1490 | - * @throws ReflectionException |
|
| 1491 | - */ |
|
| 1492 | - public function set_reg_step_completed($reg_step_slug) |
|
| 1493 | - { |
|
| 1494 | - return $this->_set_reg_step_completed_status($reg_step_slug, true); |
|
| 1495 | - } |
|
| 1496 | - |
|
| 1497 | - |
|
| 1498 | - /** |
|
| 1499 | - * set_reg_step_completed |
|
| 1500 | - * given a valid TXN_reg_step slug, this sets the step as NOT completed |
|
| 1501 | - * |
|
| 1502 | - * @param string $reg_step_slug |
|
| 1503 | - * @return boolean |
|
| 1504 | - * @throws EE_Error |
|
| 1505 | - * @throws InvalidArgumentException |
|
| 1506 | - * @throws InvalidDataTypeException |
|
| 1507 | - * @throws InvalidInterfaceException |
|
| 1508 | - * @throws ReflectionException |
|
| 1509 | - */ |
|
| 1510 | - public function set_reg_step_not_completed($reg_step_slug) |
|
| 1511 | - { |
|
| 1512 | - return $this->_set_reg_step_completed_status($reg_step_slug, false); |
|
| 1513 | - } |
|
| 1514 | - |
|
| 1515 | - |
|
| 1516 | - /** |
|
| 1517 | - * set_reg_step_completed |
|
| 1518 | - * given a valid reg step slug, this sets the TXN_reg_step completed status which is either: |
|
| 1519 | - * |
|
| 1520 | - * @param string $reg_step_slug |
|
| 1521 | - * @param boolean|int $status |
|
| 1522 | - * @return boolean |
|
| 1523 | - * @throws EE_Error |
|
| 1524 | - * @throws InvalidArgumentException |
|
| 1525 | - * @throws InvalidDataTypeException |
|
| 1526 | - * @throws InvalidInterfaceException |
|
| 1527 | - * @throws ReflectionException |
|
| 1528 | - */ |
|
| 1529 | - private function _set_reg_step_completed_status($reg_step_slug, $status) |
|
| 1530 | - { |
|
| 1531 | - // validate status |
|
| 1532 | - $status = is_bool($status) || is_int($status) ? $status : false; |
|
| 1533 | - // get reg steps array |
|
| 1534 | - $txn_reg_steps = $this->reg_steps(); |
|
| 1535 | - // if reg step does NOT exist |
|
| 1536 | - if (! isset($txn_reg_steps[ $reg_step_slug ])) { |
|
| 1537 | - return false; |
|
| 1538 | - } |
|
| 1539 | - // if we're trying to complete a step that is already completed |
|
| 1540 | - if ($txn_reg_steps[ $reg_step_slug ] === true) { |
|
| 1541 | - return true; |
|
| 1542 | - } |
|
| 1543 | - // if we're trying to complete a step that hasn't even started |
|
| 1544 | - if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) { |
|
| 1545 | - return false; |
|
| 1546 | - } |
|
| 1547 | - // if current status value matches the incoming value (no change) |
|
| 1548 | - // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890 |
|
| 1549 | - if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) { |
|
| 1550 | - // this will happen in cases where multiple AJAX requests occur during the same step |
|
| 1551 | - return true; |
|
| 1552 | - } |
|
| 1553 | - // if we're trying to set a start time, but it has already been set... |
|
| 1554 | - if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) { |
|
| 1555 | - // skip the update below, but don't return FALSE so that errors won't be displayed |
|
| 1556 | - return true; |
|
| 1557 | - } |
|
| 1558 | - // update completed status |
|
| 1559 | - $txn_reg_steps[ $reg_step_slug ] = $status; |
|
| 1560 | - $this->set_reg_steps($txn_reg_steps); |
|
| 1561 | - $this->save(); |
|
| 1562 | - return true; |
|
| 1563 | - } |
|
| 1564 | - |
|
| 1565 | - |
|
| 1566 | - /** |
|
| 1567 | - * remove_reg_step |
|
| 1568 | - * given a valid TXN_reg_step slug, this will remove (unset) |
|
| 1569 | - * the reg step from the TXN reg step array |
|
| 1570 | - * |
|
| 1571 | - * @param string $reg_step_slug |
|
| 1572 | - * @return void |
|
| 1573 | - * @throws EE_Error |
|
| 1574 | - * @throws InvalidArgumentException |
|
| 1575 | - * @throws InvalidDataTypeException |
|
| 1576 | - * @throws InvalidInterfaceException |
|
| 1577 | - * @throws ReflectionException |
|
| 1578 | - */ |
|
| 1579 | - public function remove_reg_step($reg_step_slug) |
|
| 1580 | - { |
|
| 1581 | - // get reg steps array |
|
| 1582 | - $txn_reg_steps = $this->reg_steps(); |
|
| 1583 | - unset($txn_reg_steps[ $reg_step_slug ]); |
|
| 1584 | - $this->set_reg_steps($txn_reg_steps); |
|
| 1585 | - } |
|
| 1586 | - |
|
| 1587 | - |
|
| 1588 | - /** |
|
| 1589 | - * toggle_failed_transaction_status |
|
| 1590 | - * upgrades a TXNs status from failed to abandoned, |
|
| 1591 | - * meaning that contact information has been captured for at least one registrant |
|
| 1592 | - * |
|
| 1593 | - * @param bool $save |
|
| 1594 | - * @return bool |
|
| 1595 | - * @throws EE_Error |
|
| 1596 | - * @throws InvalidArgumentException |
|
| 1597 | - * @throws InvalidDataTypeException |
|
| 1598 | - * @throws InvalidInterfaceException |
|
| 1599 | - * @throws ReflectionException |
|
| 1600 | - */ |
|
| 1601 | - public function toggle_failed_transaction_status($save = true) |
|
| 1602 | - { |
|
| 1603 | - // if TXN status is still set as "failed"... |
|
| 1604 | - if ($this->status_ID() === EEM_Transaction::failed_status_code) { |
|
| 1605 | - $this->set_status(EEM_Transaction::abandoned_status_code); |
|
| 1606 | - if ($save) { |
|
| 1607 | - $this->save(); |
|
| 1608 | - } |
|
| 1609 | - return true; |
|
| 1610 | - } |
|
| 1611 | - return false; |
|
| 1612 | - } |
|
| 1613 | - |
|
| 1614 | - |
|
| 1615 | - /** |
|
| 1616 | - * toggle_abandoned_transaction_status |
|
| 1617 | - * upgrades a TXNs status from failed or abandoned to incomplete |
|
| 1618 | - * |
|
| 1619 | - * @return bool |
|
| 1620 | - * @throws EE_Error |
|
| 1621 | - * @throws InvalidArgumentException |
|
| 1622 | - * @throws InvalidDataTypeException |
|
| 1623 | - * @throws InvalidInterfaceException |
|
| 1624 | - * @throws ReflectionException |
|
| 1625 | - */ |
|
| 1626 | - public function toggle_abandoned_transaction_status() |
|
| 1627 | - { |
|
| 1628 | - // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"... |
|
| 1629 | - $txn_status = $this->status_ID(); |
|
| 1630 | - if ($txn_status === EEM_Transaction::failed_status_code |
|
| 1631 | - || $txn_status === EEM_Transaction::abandoned_status_code |
|
| 1632 | - ) { |
|
| 1633 | - // if a contact record for the primary registrant has been created |
|
| 1634 | - if ($this->primary_registration() instanceof EE_Registration |
|
| 1635 | - && $this->primary_registration()->attendee() instanceof EE_Attendee |
|
| 1636 | - ) { |
|
| 1637 | - $this->set_status(EEM_Transaction::incomplete_status_code); |
|
| 1638 | - } else { |
|
| 1639 | - // no contact record? yer abandoned! |
|
| 1640 | - $this->set_status(EEM_Transaction::abandoned_status_code); |
|
| 1641 | - } |
|
| 1642 | - return true; |
|
| 1643 | - } |
|
| 1644 | - return false; |
|
| 1645 | - } |
|
| 1646 | - |
|
| 1647 | - |
|
| 1648 | - /** |
|
| 1649 | - * checks if an Abandoned TXN has any related payments, and if so, |
|
| 1650 | - * updates the TXN status based on the amount paid |
|
| 1651 | - * |
|
| 1652 | - * @throws EE_Error |
|
| 1653 | - * @throws InvalidDataTypeException |
|
| 1654 | - * @throws InvalidInterfaceException |
|
| 1655 | - * @throws InvalidArgumentException |
|
| 1656 | - * @throws RuntimeException |
|
| 1657 | - * @throws ReflectionException |
|
| 1658 | - */ |
|
| 1659 | - public function verify_abandoned_transaction_status() |
|
| 1660 | - { |
|
| 1661 | - if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) { |
|
| 1662 | - return; |
|
| 1663 | - } |
|
| 1664 | - $payments = $this->get_many_related('Payment'); |
|
| 1665 | - if (! empty($payments)) { |
|
| 1666 | - foreach ($payments as $payment) { |
|
| 1667 | - if ($payment instanceof EE_Payment) { |
|
| 1668 | - // kk this TXN should NOT be abandoned |
|
| 1669 | - $this->update_status_based_on_total_paid(); |
|
| 1670 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) { |
|
| 1671 | - EE_Error::add_attention( |
|
| 1672 | - sprintf( |
|
| 1673 | - esc_html__( |
|
| 1674 | - 'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.', |
|
| 1675 | - 'event_espresso' |
|
| 1676 | - ), |
|
| 1677 | - $this->ID(), |
|
| 1678 | - $this->pretty_status() |
|
| 1679 | - ) |
|
| 1680 | - ); |
|
| 1681 | - } |
|
| 1682 | - // get final reg step status |
|
| 1683 | - $finalized = $this->final_reg_step_completed(); |
|
| 1684 | - // if the 'finalize_registration' step has been initiated (has a timestamp) |
|
| 1685 | - // but has not yet been fully completed (TRUE) |
|
| 1686 | - if (is_int($finalized) && $finalized !== false && $finalized !== true) { |
|
| 1687 | - $this->set_reg_step_completed('finalize_registration'); |
|
| 1688 | - $this->save(); |
|
| 1689 | - } |
|
| 1690 | - } |
|
| 1691 | - } |
|
| 1692 | - } |
|
| 1693 | - } |
|
| 16 | + /** |
|
| 17 | + * The length of time in seconds that a lock is applied before being considered expired. |
|
| 18 | + * It is not long because a transaction should only be locked for the duration of the request that locked it |
|
| 19 | + */ |
|
| 20 | + const LOCK_EXPIRATION = 2; |
|
| 21 | + |
|
| 22 | + /** |
|
| 23 | + * txn status upon initial construction. |
|
| 24 | + * |
|
| 25 | + * @var string |
|
| 26 | + */ |
|
| 27 | + protected $_old_txn_status; |
|
| 28 | + |
|
| 29 | + |
|
| 30 | + /** |
|
| 31 | + * @param array $props_n_values incoming values |
|
| 32 | + * @param string $timezone incoming timezone |
|
| 33 | + * (if not set the timezone set for the website will be used.) |
|
| 34 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 35 | + * date_format and the second value is the time format |
|
| 36 | + * @return EE_Transaction |
|
| 37 | + * @throws EE_Error |
|
| 38 | + * @throws InvalidArgumentException |
|
| 39 | + * @throws InvalidDataTypeException |
|
| 40 | + * @throws InvalidInterfaceException |
|
| 41 | + * @throws ReflectionException |
|
| 42 | + */ |
|
| 43 | + public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array()) |
|
| 44 | + { |
|
| 45 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 46 | + $txn = $has_object |
|
| 47 | + ? $has_object |
|
| 48 | + : new self($props_n_values, false, $timezone, $date_formats); |
|
| 49 | + if (! $has_object) { |
|
| 50 | + $txn->set_old_txn_status($txn->status_ID()); |
|
| 51 | + } |
|
| 52 | + return $txn; |
|
| 53 | + } |
|
| 54 | + |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * @param array $props_n_values incoming values from the database |
|
| 58 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 59 | + * the website will be used. |
|
| 60 | + * @return EE_Transaction |
|
| 61 | + * @throws EE_Error |
|
| 62 | + * @throws InvalidArgumentException |
|
| 63 | + * @throws InvalidDataTypeException |
|
| 64 | + * @throws InvalidInterfaceException |
|
| 65 | + * @throws ReflectionException |
|
| 66 | + */ |
|
| 67 | + public static function new_instance_from_db($props_n_values = array(), $timezone = null) |
|
| 68 | + { |
|
| 69 | + $txn = new self($props_n_values, true, $timezone); |
|
| 70 | + $txn->set_old_txn_status($txn->status_ID()); |
|
| 71 | + return $txn; |
|
| 72 | + } |
|
| 73 | + |
|
| 74 | + |
|
| 75 | + /** |
|
| 76 | + * Sets a meta field indicating that this TXN is locked and should not be updated in the db. |
|
| 77 | + * If a lock has already been set, then we will attempt to remove it in case it has expired. |
|
| 78 | + * If that also fails, then an exception is thrown. |
|
| 79 | + * |
|
| 80 | + * @throws EE_Error |
|
| 81 | + * @throws InvalidArgumentException |
|
| 82 | + * @throws InvalidDataTypeException |
|
| 83 | + * @throws InvalidInterfaceException |
|
| 84 | + * @throws ReflectionException |
|
| 85 | + */ |
|
| 86 | + public function lock() |
|
| 87 | + { |
|
| 88 | + // attempt to set lock, but if that fails... |
|
| 89 | + if (! $this->add_extra_meta('lock', time(), true)) { |
|
| 90 | + // then attempt to remove the lock in case it is expired |
|
| 91 | + if ($this->_remove_expired_lock()) { |
|
| 92 | + // if removal was successful, then try setting lock again |
|
| 93 | + $this->lock(); |
|
| 94 | + } else { |
|
| 95 | + // but if the lock can not be removed, then throw an exception |
|
| 96 | + throw new EE_Error( |
|
| 97 | + sprintf( |
|
| 98 | + __( |
|
| 99 | + 'Could not lock Transaction %1$d because it is already locked, meaning another part of the system is currently editing it. It should already be unlocked by the time you read this, so please refresh the page and try again.', |
|
| 100 | + 'event_espresso' |
|
| 101 | + ), |
|
| 102 | + $this->ID() |
|
| 103 | + ) |
|
| 104 | + ); |
|
| 105 | + } |
|
| 106 | + } |
|
| 107 | + } |
|
| 108 | + |
|
| 109 | + |
|
| 110 | + /** |
|
| 111 | + * removes transaction lock applied in EE_Transaction::lock() |
|
| 112 | + * |
|
| 113 | + * @return int |
|
| 114 | + * @throws EE_Error |
|
| 115 | + * @throws InvalidArgumentException |
|
| 116 | + * @throws InvalidDataTypeException |
|
| 117 | + * @throws InvalidInterfaceException |
|
| 118 | + * @throws ReflectionException |
|
| 119 | + */ |
|
| 120 | + public function unlock() |
|
| 121 | + { |
|
| 122 | + return $this->delete_extra_meta('lock'); |
|
| 123 | + } |
|
| 124 | + |
|
| 125 | + |
|
| 126 | + /** |
|
| 127 | + * Decides whether or not now is the right time to update the transaction. |
|
| 128 | + * This is useful because we don't always know if it is safe to update the transaction |
|
| 129 | + * and its related data. why? |
|
| 130 | + * because it's possible that the transaction is being used in another |
|
| 131 | + * request and could overwrite anything we save. |
|
| 132 | + * So we want to only update the txn once we know that won't happen. |
|
| 133 | + * We also check that the lock isn't expired, and remove it if it is |
|
| 134 | + * |
|
| 135 | + * @return boolean |
|
| 136 | + * @throws EE_Error |
|
| 137 | + * @throws InvalidArgumentException |
|
| 138 | + * @throws InvalidDataTypeException |
|
| 139 | + * @throws InvalidInterfaceException |
|
| 140 | + * @throws ReflectionException |
|
| 141 | + */ |
|
| 142 | + public function is_locked() |
|
| 143 | + { |
|
| 144 | + // if TXN is not locked, then return false immediately |
|
| 145 | + if (! $this->_get_lock()) { |
|
| 146 | + return false; |
|
| 147 | + } |
|
| 148 | + // if not, then let's try and remove the lock in case it's expired... |
|
| 149 | + // _remove_expired_lock() returns 0 when lock is valid (ie: removed = false) |
|
| 150 | + // and a positive number if the lock was removed (ie: number of locks deleted), |
|
| 151 | + // so we need to return the opposite |
|
| 152 | + return ! $this->_remove_expired_lock() ? true : false; |
|
| 153 | + } |
|
| 154 | + |
|
| 155 | + |
|
| 156 | + /** |
|
| 157 | + * Gets the meta field indicating that this TXN is locked |
|
| 158 | + * |
|
| 159 | + * @return int |
|
| 160 | + * @throws EE_Error |
|
| 161 | + * @throws InvalidArgumentException |
|
| 162 | + * @throws InvalidDataTypeException |
|
| 163 | + * @throws InvalidInterfaceException |
|
| 164 | + * @throws ReflectionException |
|
| 165 | + */ |
|
| 166 | + protected function _get_lock() |
|
| 167 | + { |
|
| 168 | + return (int) $this->get_extra_meta('lock', true, 0); |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * If the lock on this transaction is expired, then we want to remove it so that the transaction can be updated |
|
| 174 | + * |
|
| 175 | + * @return int |
|
| 176 | + * @throws EE_Error |
|
| 177 | + * @throws InvalidArgumentException |
|
| 178 | + * @throws InvalidDataTypeException |
|
| 179 | + * @throws InvalidInterfaceException |
|
| 180 | + * @throws ReflectionException |
|
| 181 | + */ |
|
| 182 | + protected function _remove_expired_lock() |
|
| 183 | + { |
|
| 184 | + $locked = $this->_get_lock(); |
|
| 185 | + if ($locked && time() - EE_Transaction::LOCK_EXPIRATION > $locked) { |
|
| 186 | + return $this->unlock(); |
|
| 187 | + } |
|
| 188 | + return 0; |
|
| 189 | + } |
|
| 190 | + |
|
| 191 | + |
|
| 192 | + /** |
|
| 193 | + * Set transaction total |
|
| 194 | + * |
|
| 195 | + * @param float $total total value of transaction |
|
| 196 | + * @throws EE_Error |
|
| 197 | + * @throws InvalidArgumentException |
|
| 198 | + * @throws InvalidDataTypeException |
|
| 199 | + * @throws InvalidInterfaceException |
|
| 200 | + * @throws ReflectionException |
|
| 201 | + */ |
|
| 202 | + public function set_total($total = 0.00) |
|
| 203 | + { |
|
| 204 | + $this->set('TXN_total', (float) $total); |
|
| 205 | + } |
|
| 206 | + |
|
| 207 | + |
|
| 208 | + /** |
|
| 209 | + * Set Total Amount Paid to Date |
|
| 210 | + * |
|
| 211 | + * @param float $total_paid total amount paid to date (sum of all payments) |
|
| 212 | + * @throws EE_Error |
|
| 213 | + * @throws InvalidArgumentException |
|
| 214 | + * @throws InvalidDataTypeException |
|
| 215 | + * @throws InvalidInterfaceException |
|
| 216 | + * @throws ReflectionException |
|
| 217 | + */ |
|
| 218 | + public function set_paid($total_paid = 0.00) |
|
| 219 | + { |
|
| 220 | + $this->set('TXN_paid', (float) $total_paid); |
|
| 221 | + } |
|
| 222 | + |
|
| 223 | + |
|
| 224 | + /** |
|
| 225 | + * Set transaction status |
|
| 226 | + * |
|
| 227 | + * @param string $status whether the transaction is open, declined, accepted, |
|
| 228 | + * or any number of custom values that can be set |
|
| 229 | + * @throws EE_Error |
|
| 230 | + * @throws InvalidArgumentException |
|
| 231 | + * @throws InvalidDataTypeException |
|
| 232 | + * @throws InvalidInterfaceException |
|
| 233 | + * @throws ReflectionException |
|
| 234 | + */ |
|
| 235 | + public function set_status($status = '') |
|
| 236 | + { |
|
| 237 | + $this->set('STS_ID', $status); |
|
| 238 | + } |
|
| 239 | + |
|
| 240 | + |
|
| 241 | + /** |
|
| 242 | + * Set hash salt |
|
| 243 | + * |
|
| 244 | + * @param string $hash_salt required for some payment gateways |
|
| 245 | + * @throws EE_Error |
|
| 246 | + * @throws InvalidArgumentException |
|
| 247 | + * @throws InvalidDataTypeException |
|
| 248 | + * @throws InvalidInterfaceException |
|
| 249 | + * @throws ReflectionException |
|
| 250 | + */ |
|
| 251 | + public function set_hash_salt($hash_salt = '') |
|
| 252 | + { |
|
| 253 | + $this->set('TXN_hash_salt', $hash_salt); |
|
| 254 | + } |
|
| 255 | + |
|
| 256 | + |
|
| 257 | + /** |
|
| 258 | + * Sets TXN_reg_steps array |
|
| 259 | + * |
|
| 260 | + * @param array $txn_reg_steps |
|
| 261 | + * @throws EE_Error |
|
| 262 | + * @throws InvalidArgumentException |
|
| 263 | + * @throws InvalidDataTypeException |
|
| 264 | + * @throws InvalidInterfaceException |
|
| 265 | + * @throws ReflectionException |
|
| 266 | + */ |
|
| 267 | + public function set_reg_steps(array $txn_reg_steps) |
|
| 268 | + { |
|
| 269 | + $this->set('TXN_reg_steps', $txn_reg_steps); |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + |
|
| 273 | + /** |
|
| 274 | + * Gets TXN_reg_steps |
|
| 275 | + * |
|
| 276 | + * @return array |
|
| 277 | + * @throws EE_Error |
|
| 278 | + * @throws InvalidArgumentException |
|
| 279 | + * @throws InvalidDataTypeException |
|
| 280 | + * @throws InvalidInterfaceException |
|
| 281 | + * @throws ReflectionException |
|
| 282 | + */ |
|
| 283 | + public function reg_steps() |
|
| 284 | + { |
|
| 285 | + $TXN_reg_steps = $this->get('TXN_reg_steps'); |
|
| 286 | + return is_array($TXN_reg_steps) ? (array) $TXN_reg_steps : array(); |
|
| 287 | + } |
|
| 288 | + |
|
| 289 | + |
|
| 290 | + /** |
|
| 291 | + * @return string of transaction's total cost, with currency symbol and decimal |
|
| 292 | + * @throws EE_Error |
|
| 293 | + * @throws InvalidArgumentException |
|
| 294 | + * @throws InvalidDataTypeException |
|
| 295 | + * @throws InvalidInterfaceException |
|
| 296 | + * @throws ReflectionException |
|
| 297 | + */ |
|
| 298 | + public function pretty_total() |
|
| 299 | + { |
|
| 300 | + return $this->get_pretty('TXN_total'); |
|
| 301 | + } |
|
| 302 | + |
|
| 303 | + |
|
| 304 | + /** |
|
| 305 | + * Gets the amount paid in a pretty string (formatted and with currency symbol) |
|
| 306 | + * |
|
| 307 | + * @return string |
|
| 308 | + * @throws EE_Error |
|
| 309 | + * @throws InvalidArgumentException |
|
| 310 | + * @throws InvalidDataTypeException |
|
| 311 | + * @throws InvalidInterfaceException |
|
| 312 | + * @throws ReflectionException |
|
| 313 | + */ |
|
| 314 | + public function pretty_paid() |
|
| 315 | + { |
|
| 316 | + return $this->get_pretty('TXN_paid'); |
|
| 317 | + } |
|
| 318 | + |
|
| 319 | + |
|
| 320 | + /** |
|
| 321 | + * calculate the amount remaining for this transaction and return; |
|
| 322 | + * |
|
| 323 | + * @return float amount remaining |
|
| 324 | + * @throws EE_Error |
|
| 325 | + * @throws InvalidArgumentException |
|
| 326 | + * @throws InvalidDataTypeException |
|
| 327 | + * @throws InvalidInterfaceException |
|
| 328 | + * @throws ReflectionException |
|
| 329 | + */ |
|
| 330 | + public function remaining() |
|
| 331 | + { |
|
| 332 | + return $this->total() - $this->paid(); |
|
| 333 | + } |
|
| 334 | + |
|
| 335 | + |
|
| 336 | + /** |
|
| 337 | + * get Transaction Total |
|
| 338 | + * |
|
| 339 | + * @return float |
|
| 340 | + * @throws EE_Error |
|
| 341 | + * @throws InvalidArgumentException |
|
| 342 | + * @throws InvalidDataTypeException |
|
| 343 | + * @throws InvalidInterfaceException |
|
| 344 | + * @throws ReflectionException |
|
| 345 | + */ |
|
| 346 | + public function total() |
|
| 347 | + { |
|
| 348 | + return (float) $this->get('TXN_total'); |
|
| 349 | + } |
|
| 350 | + |
|
| 351 | + |
|
| 352 | + /** |
|
| 353 | + * get Total Amount Paid to Date |
|
| 354 | + * |
|
| 355 | + * @return float |
|
| 356 | + * @throws EE_Error |
|
| 357 | + * @throws InvalidArgumentException |
|
| 358 | + * @throws InvalidDataTypeException |
|
| 359 | + * @throws InvalidInterfaceException |
|
| 360 | + * @throws ReflectionException |
|
| 361 | + */ |
|
| 362 | + public function paid() |
|
| 363 | + { |
|
| 364 | + return (float) $this->get('TXN_paid'); |
|
| 365 | + } |
|
| 366 | + |
|
| 367 | + |
|
| 368 | + /** |
|
| 369 | + * @return mixed|null |
|
| 370 | + * @throws EE_Error |
|
| 371 | + * @throws InvalidArgumentException |
|
| 372 | + * @throws InvalidDataTypeException |
|
| 373 | + * @throws InvalidInterfaceException |
|
| 374 | + * @throws ReflectionException |
|
| 375 | + */ |
|
| 376 | + public function get_cart_session() |
|
| 377 | + { |
|
| 378 | + $session_data = (array) $this->get('TXN_session_data'); |
|
| 379 | + return isset($session_data['cart']) && $session_data['cart'] instanceof EE_Cart |
|
| 380 | + ? $session_data['cart'] |
|
| 381 | + : null; |
|
| 382 | + } |
|
| 383 | + |
|
| 384 | + |
|
| 385 | + /** |
|
| 386 | + * get Transaction session data |
|
| 387 | + * |
|
| 388 | + * @return array|mixed |
|
| 389 | + * @throws EE_Error |
|
| 390 | + * @throws InvalidArgumentException |
|
| 391 | + * @throws InvalidDataTypeException |
|
| 392 | + * @throws InvalidInterfaceException |
|
| 393 | + * @throws ReflectionException |
|
| 394 | + */ |
|
| 395 | + public function session_data() |
|
| 396 | + { |
|
| 397 | + $session_data = $this->get('TXN_session_data'); |
|
| 398 | + if (empty($session_data)) { |
|
| 399 | + $session_data = array( |
|
| 400 | + 'id' => null, |
|
| 401 | + 'user_id' => null, |
|
| 402 | + 'ip_address' => null, |
|
| 403 | + 'user_agent' => null, |
|
| 404 | + 'init_access' => null, |
|
| 405 | + 'last_access' => null, |
|
| 406 | + 'pages_visited' => array(), |
|
| 407 | + ); |
|
| 408 | + } |
|
| 409 | + return $session_data; |
|
| 410 | + } |
|
| 411 | + |
|
| 412 | + |
|
| 413 | + /** |
|
| 414 | + * Set session data within the TXN object |
|
| 415 | + * |
|
| 416 | + * @param EE_Session|array $session_data |
|
| 417 | + * @throws EE_Error |
|
| 418 | + * @throws InvalidArgumentException |
|
| 419 | + * @throws InvalidDataTypeException |
|
| 420 | + * @throws InvalidInterfaceException |
|
| 421 | + * @throws ReflectionException |
|
| 422 | + */ |
|
| 423 | + public function set_txn_session_data($session_data) |
|
| 424 | + { |
|
| 425 | + if ($session_data instanceof EE_Session) { |
|
| 426 | + $this->set('TXN_session_data', $session_data->get_session_data(null, true)); |
|
| 427 | + } else { |
|
| 428 | + $this->set('TXN_session_data', $session_data); |
|
| 429 | + } |
|
| 430 | + } |
|
| 431 | + |
|
| 432 | + |
|
| 433 | + /** |
|
| 434 | + * get Transaction hash salt |
|
| 435 | + * |
|
| 436 | + * @return mixed |
|
| 437 | + * @throws EE_Error |
|
| 438 | + * @throws InvalidArgumentException |
|
| 439 | + * @throws InvalidDataTypeException |
|
| 440 | + * @throws InvalidInterfaceException |
|
| 441 | + * @throws ReflectionException |
|
| 442 | + */ |
|
| 443 | + public function hash_salt_() |
|
| 444 | + { |
|
| 445 | + return $this->get('TXN_hash_salt'); |
|
| 446 | + } |
|
| 447 | + |
|
| 448 | + |
|
| 449 | + /** |
|
| 450 | + * Returns the transaction datetime as either: |
|
| 451 | + * - unix timestamp format ($format = false, $gmt = true) |
|
| 452 | + * - formatted date string including the UTC (timezone) offset ($format = true ($gmt |
|
| 453 | + * has no affect with this option)), this also may include a timezone abbreviation if the |
|
| 454 | + * set timezone in this class differs from what the timezone is on the blog. |
|
| 455 | + * - formatted date string including the UTC (timezone) offset (default). |
|
| 456 | + * |
|
| 457 | + * @param boolean $format - whether to return a unix timestamp (default) or formatted date string |
|
| 458 | + * @param boolean $gmt - whether to return a unix timestamp with UTC offset applied (default) |
|
| 459 | + * or no UTC offset applied |
|
| 460 | + * @return string | int |
|
| 461 | + * @throws EE_Error |
|
| 462 | + * @throws InvalidArgumentException |
|
| 463 | + * @throws InvalidDataTypeException |
|
| 464 | + * @throws InvalidInterfaceException |
|
| 465 | + * @throws ReflectionException |
|
| 466 | + */ |
|
| 467 | + public function datetime($format = false, $gmt = false) |
|
| 468 | + { |
|
| 469 | + if ($format) { |
|
| 470 | + return $this->get_pretty('TXN_timestamp'); |
|
| 471 | + } |
|
| 472 | + if ($gmt) { |
|
| 473 | + return $this->get_raw('TXN_timestamp'); |
|
| 474 | + } |
|
| 475 | + return $this->get('TXN_timestamp'); |
|
| 476 | + } |
|
| 477 | + |
|
| 478 | + |
|
| 479 | + /** |
|
| 480 | + * Gets registrations on this transaction |
|
| 481 | + * |
|
| 482 | + * @param array $query_params array of query parameters |
|
| 483 | + * @param boolean $get_cached TRUE to retrieve cached registrations or FALSE to pull from the db |
|
| 484 | + * @return EE_Base_Class[]|EE_Registration[] |
|
| 485 | + * @throws EE_Error |
|
| 486 | + * @throws InvalidArgumentException |
|
| 487 | + * @throws InvalidDataTypeException |
|
| 488 | + * @throws InvalidInterfaceException |
|
| 489 | + * @throws ReflectionException |
|
| 490 | + */ |
|
| 491 | + public function registrations($query_params = array(), $get_cached = false) |
|
| 492 | + { |
|
| 493 | + $query_params = (empty($query_params) || ! is_array($query_params)) |
|
| 494 | + ? array( |
|
| 495 | + 'order_by' => array( |
|
| 496 | + 'Event.EVT_name' => 'ASC', |
|
| 497 | + 'Attendee.ATT_lname' => 'ASC', |
|
| 498 | + 'Attendee.ATT_fname' => 'ASC', |
|
| 499 | + ), |
|
| 500 | + ) |
|
| 501 | + : $query_params; |
|
| 502 | + $query_params = $get_cached ? array() : $query_params; |
|
| 503 | + return $this->get_many_related('Registration', $query_params); |
|
| 504 | + } |
|
| 505 | + |
|
| 506 | + |
|
| 507 | + /** |
|
| 508 | + * Gets all the attendees for this transaction (handy for use with EE_Attendee's get_registrations_for_event |
|
| 509 | + * function for getting attendees and how many registrations they each have for an event) |
|
| 510 | + * |
|
| 511 | + * @return mixed EE_Attendee[] by default, int if $output is set to 'COUNT' |
|
| 512 | + * @throws EE_Error |
|
| 513 | + * @throws InvalidArgumentException |
|
| 514 | + * @throws InvalidDataTypeException |
|
| 515 | + * @throws InvalidInterfaceException |
|
| 516 | + * @throws ReflectionException |
|
| 517 | + */ |
|
| 518 | + public function attendees() |
|
| 519 | + { |
|
| 520 | + return $this->get_many_related('Attendee', array(array('Registration.Transaction.TXN_ID' => $this->ID()))); |
|
| 521 | + } |
|
| 522 | + |
|
| 523 | + |
|
| 524 | + /** |
|
| 525 | + * Gets payments for this transaction. Unlike other such functions, order by 'DESC' by default |
|
| 526 | + * |
|
| 527 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 528 | + * @return EE_Base_Class[]|EE_Payment[] |
|
| 529 | + * @throws EE_Error |
|
| 530 | + * @throws InvalidArgumentException |
|
| 531 | + * @throws InvalidDataTypeException |
|
| 532 | + * @throws InvalidInterfaceException |
|
| 533 | + * @throws ReflectionException |
|
| 534 | + */ |
|
| 535 | + public function payments($query_params = array()) |
|
| 536 | + { |
|
| 537 | + return $this->get_many_related('Payment', $query_params); |
|
| 538 | + } |
|
| 539 | + |
|
| 540 | + |
|
| 541 | + /** |
|
| 542 | + * gets only approved payments for this transaction |
|
| 543 | + * |
|
| 544 | + * @return EE_Base_Class[]|EE_Payment[] |
|
| 545 | + * @throws EE_Error |
|
| 546 | + * @throws InvalidArgumentException |
|
| 547 | + * @throws ReflectionException |
|
| 548 | + * @throws InvalidDataTypeException |
|
| 549 | + * @throws InvalidInterfaceException |
|
| 550 | + */ |
|
| 551 | + public function approved_payments() |
|
| 552 | + { |
|
| 553 | + EE_Registry::instance()->load_model('Payment'); |
|
| 554 | + return $this->get_many_related( |
|
| 555 | + 'Payment', |
|
| 556 | + array( |
|
| 557 | + array('STS_ID' => EEM_Payment::status_id_approved), |
|
| 558 | + 'order_by' => array('PAY_timestamp' => 'DESC'), |
|
| 559 | + ) |
|
| 560 | + ); |
|
| 561 | + } |
|
| 562 | + |
|
| 563 | + |
|
| 564 | + /** |
|
| 565 | + * Gets all payments which have not been approved |
|
| 566 | + * |
|
| 567 | + * @return EE_Base_Class[]|EEI_Payment[] |
|
| 568 | + * @throws EE_Error if a model is misconfigured somehow |
|
| 569 | + * @throws InvalidArgumentException |
|
| 570 | + * @throws InvalidDataTypeException |
|
| 571 | + * @throws InvalidInterfaceException |
|
| 572 | + * @throws ReflectionException |
|
| 573 | + */ |
|
| 574 | + public function pending_payments() |
|
| 575 | + { |
|
| 576 | + return $this->get_many_related( |
|
| 577 | + 'Payment', |
|
| 578 | + array( |
|
| 579 | + array( |
|
| 580 | + 'STS_ID' => EEM_Payment::status_id_pending, |
|
| 581 | + ), |
|
| 582 | + 'order_by' => array( |
|
| 583 | + 'PAY_timestamp' => 'DESC', |
|
| 584 | + ), |
|
| 585 | + ) |
|
| 586 | + ); |
|
| 587 | + } |
|
| 588 | + |
|
| 589 | + |
|
| 590 | + /** |
|
| 591 | + * echoes $this->pretty_status() |
|
| 592 | + * |
|
| 593 | + * @param bool $show_icons |
|
| 594 | + * @throws EE_Error |
|
| 595 | + * @throws InvalidArgumentException |
|
| 596 | + * @throws InvalidDataTypeException |
|
| 597 | + * @throws InvalidInterfaceException |
|
| 598 | + * @throws ReflectionException |
|
| 599 | + */ |
|
| 600 | + public function e_pretty_status($show_icons = false) |
|
| 601 | + { |
|
| 602 | + echo $this->pretty_status($show_icons); |
|
| 603 | + } |
|
| 604 | + |
|
| 605 | + |
|
| 606 | + /** |
|
| 607 | + * returns a pretty version of the status, good for displaying to users |
|
| 608 | + * |
|
| 609 | + * @param bool $show_icons |
|
| 610 | + * @return string |
|
| 611 | + * @throws EE_Error |
|
| 612 | + * @throws InvalidArgumentException |
|
| 613 | + * @throws InvalidDataTypeException |
|
| 614 | + * @throws InvalidInterfaceException |
|
| 615 | + * @throws ReflectionException |
|
| 616 | + */ |
|
| 617 | + public function pretty_status($show_icons = false) |
|
| 618 | + { |
|
| 619 | + $status = EEM_Status::instance()->localized_status( |
|
| 620 | + array($this->status_ID() => __('unknown', 'event_espresso')), |
|
| 621 | + false, |
|
| 622 | + 'sentence' |
|
| 623 | + ); |
|
| 624 | + $icon = ''; |
|
| 625 | + switch ($this->status_ID()) { |
|
| 626 | + case EEM_Transaction::complete_status_code: |
|
| 627 | + $icon = $show_icons ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>' : ''; |
|
| 628 | + break; |
|
| 629 | + case EEM_Transaction::incomplete_status_code: |
|
| 630 | + $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 lt-blue-text"></span>' |
|
| 631 | + : ''; |
|
| 632 | + break; |
|
| 633 | + case EEM_Transaction::abandoned_status_code: |
|
| 634 | + $icon = $show_icons ? '<span class="dashicons dashicons-marker ee-icon-size-16 red-text"></span>' : ''; |
|
| 635 | + break; |
|
| 636 | + case EEM_Transaction::failed_status_code: |
|
| 637 | + $icon = $show_icons ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' : ''; |
|
| 638 | + break; |
|
| 639 | + case EEM_Transaction::overpaid_status_code: |
|
| 640 | + $icon = $show_icons ? '<span class="dashicons dashicons-plus ee-icon-size-16 orange-text"></span>' : ''; |
|
| 641 | + break; |
|
| 642 | + } |
|
| 643 | + return $icon . $status[ $this->status_ID() ]; |
|
| 644 | + } |
|
| 645 | + |
|
| 646 | + |
|
| 647 | + /** |
|
| 648 | + * get Transaction Status |
|
| 649 | + * |
|
| 650 | + * @return mixed |
|
| 651 | + * @throws EE_Error |
|
| 652 | + * @throws InvalidArgumentException |
|
| 653 | + * @throws InvalidDataTypeException |
|
| 654 | + * @throws InvalidInterfaceException |
|
| 655 | + * @throws ReflectionException |
|
| 656 | + */ |
|
| 657 | + public function status_ID() |
|
| 658 | + { |
|
| 659 | + return $this->get('STS_ID'); |
|
| 660 | + } |
|
| 661 | + |
|
| 662 | + |
|
| 663 | + /** |
|
| 664 | + * Returns TRUE or FALSE for whether or not this transaction cost any money |
|
| 665 | + * |
|
| 666 | + * @return boolean |
|
| 667 | + * @throws EE_Error |
|
| 668 | + * @throws InvalidArgumentException |
|
| 669 | + * @throws InvalidDataTypeException |
|
| 670 | + * @throws InvalidInterfaceException |
|
| 671 | + * @throws ReflectionException |
|
| 672 | + */ |
|
| 673 | + public function is_free() |
|
| 674 | + { |
|
| 675 | + return EEH_Money::compare_floats($this->get('TXN_total'), 0, '=='); |
|
| 676 | + } |
|
| 677 | + |
|
| 678 | + |
|
| 679 | + /** |
|
| 680 | + * Returns whether this transaction is complete |
|
| 681 | + * Useful in templates and other logic for deciding if we should ask for another payment... |
|
| 682 | + * |
|
| 683 | + * @return boolean |
|
| 684 | + * @throws EE_Error |
|
| 685 | + * @throws InvalidArgumentException |
|
| 686 | + * @throws InvalidDataTypeException |
|
| 687 | + * @throws InvalidInterfaceException |
|
| 688 | + * @throws ReflectionException |
|
| 689 | + */ |
|
| 690 | + public function is_completed() |
|
| 691 | + { |
|
| 692 | + return $this->status_ID() === EEM_Transaction::complete_status_code; |
|
| 693 | + } |
|
| 694 | + |
|
| 695 | + |
|
| 696 | + /** |
|
| 697 | + * Returns whether this transaction is incomplete |
|
| 698 | + * Useful in templates and other logic for deciding if we should ask for another payment... |
|
| 699 | + * |
|
| 700 | + * @return boolean |
|
| 701 | + * @throws EE_Error |
|
| 702 | + * @throws InvalidArgumentException |
|
| 703 | + * @throws InvalidDataTypeException |
|
| 704 | + * @throws InvalidInterfaceException |
|
| 705 | + * @throws ReflectionException |
|
| 706 | + */ |
|
| 707 | + public function is_incomplete() |
|
| 708 | + { |
|
| 709 | + return $this->status_ID() === EEM_Transaction::incomplete_status_code; |
|
| 710 | + } |
|
| 711 | + |
|
| 712 | + |
|
| 713 | + /** |
|
| 714 | + * Returns whether this transaction is overpaid |
|
| 715 | + * Useful in templates and other logic for deciding if monies need to be refunded |
|
| 716 | + * |
|
| 717 | + * @return boolean |
|
| 718 | + * @throws EE_Error |
|
| 719 | + * @throws InvalidArgumentException |
|
| 720 | + * @throws InvalidDataTypeException |
|
| 721 | + * @throws InvalidInterfaceException |
|
| 722 | + * @throws ReflectionException |
|
| 723 | + */ |
|
| 724 | + public function is_overpaid() |
|
| 725 | + { |
|
| 726 | + return $this->status_ID() === EEM_Transaction::overpaid_status_code; |
|
| 727 | + } |
|
| 728 | + |
|
| 729 | + |
|
| 730 | + /** |
|
| 731 | + * Returns whether this transaction was abandoned |
|
| 732 | + * meaning that the transaction/registration process was somehow interrupted and never completed |
|
| 733 | + * but that contact information exists for at least one registrant |
|
| 734 | + * |
|
| 735 | + * @return boolean |
|
| 736 | + * @throws EE_Error |
|
| 737 | + * @throws InvalidArgumentException |
|
| 738 | + * @throws InvalidDataTypeException |
|
| 739 | + * @throws InvalidInterfaceException |
|
| 740 | + * @throws ReflectionException |
|
| 741 | + */ |
|
| 742 | + public function is_abandoned() |
|
| 743 | + { |
|
| 744 | + return $this->status_ID() === EEM_Transaction::abandoned_status_code; |
|
| 745 | + } |
|
| 746 | + |
|
| 747 | + |
|
| 748 | + /** |
|
| 749 | + * Returns whether this transaction failed |
|
| 750 | + * meaning that the transaction/registration process was somehow interrupted and never completed |
|
| 751 | + * and that NO contact information exists for any registrants |
|
| 752 | + * |
|
| 753 | + * @return boolean |
|
| 754 | + * @throws EE_Error |
|
| 755 | + * @throws InvalidArgumentException |
|
| 756 | + * @throws InvalidDataTypeException |
|
| 757 | + * @throws InvalidInterfaceException |
|
| 758 | + * @throws ReflectionException |
|
| 759 | + */ |
|
| 760 | + public function failed() |
|
| 761 | + { |
|
| 762 | + return $this->status_ID() === EEM_Transaction::failed_status_code; |
|
| 763 | + } |
|
| 764 | + |
|
| 765 | + |
|
| 766 | + /** |
|
| 767 | + * This returns the url for the invoice of this transaction |
|
| 768 | + * |
|
| 769 | + * @param string $type 'html' or 'pdf' (default is pdf) |
|
| 770 | + * @return string |
|
| 771 | + * @throws EE_Error |
|
| 772 | + * @throws InvalidArgumentException |
|
| 773 | + * @throws InvalidDataTypeException |
|
| 774 | + * @throws InvalidInterfaceException |
|
| 775 | + * @throws ReflectionException |
|
| 776 | + */ |
|
| 777 | + public function invoice_url($type = 'html') |
|
| 778 | + { |
|
| 779 | + $REG = $this->primary_registration(); |
|
| 780 | + if (! $REG instanceof EE_Registration) { |
|
| 781 | + return ''; |
|
| 782 | + } |
|
| 783 | + return $REG->invoice_url($type); |
|
| 784 | + } |
|
| 785 | + |
|
| 786 | + |
|
| 787 | + /** |
|
| 788 | + * Gets the primary registration only |
|
| 789 | + * |
|
| 790 | + * @return EE_Base_Class|EE_Registration |
|
| 791 | + * @throws EE_Error |
|
| 792 | + * @throws InvalidArgumentException |
|
| 793 | + * @throws InvalidDataTypeException |
|
| 794 | + * @throws InvalidInterfaceException |
|
| 795 | + * @throws ReflectionException |
|
| 796 | + */ |
|
| 797 | + public function primary_registration() |
|
| 798 | + { |
|
| 799 | + $registrations = (array) $this->get_many_related( |
|
| 800 | + 'Registration', |
|
| 801 | + array(array('REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT)) |
|
| 802 | + ); |
|
| 803 | + foreach ($registrations as $registration) { |
|
| 804 | + // valid registration that is NOT cancelled or declined ? |
|
| 805 | + if ($registration instanceof EE_Registration |
|
| 806 | + && ! in_array($registration->status_ID(), EEM_Registration::closed_reg_statuses(), true) |
|
| 807 | + ) { |
|
| 808 | + return $registration; |
|
| 809 | + } |
|
| 810 | + } |
|
| 811 | + // nothing valid found, so just return first thing from array of results |
|
| 812 | + return reset($registrations); |
|
| 813 | + } |
|
| 814 | + |
|
| 815 | + |
|
| 816 | + /** |
|
| 817 | + * Gets the URL for viewing the receipt |
|
| 818 | + * |
|
| 819 | + * @param string $type 'pdf' or 'html' (default is 'html') |
|
| 820 | + * @return string |
|
| 821 | + * @throws EE_Error |
|
| 822 | + * @throws InvalidArgumentException |
|
| 823 | + * @throws InvalidDataTypeException |
|
| 824 | + * @throws InvalidInterfaceException |
|
| 825 | + * @throws ReflectionException |
|
| 826 | + */ |
|
| 827 | + public function receipt_url($type = 'html') |
|
| 828 | + { |
|
| 829 | + $REG = $this->primary_registration(); |
|
| 830 | + if (! $REG instanceof EE_Registration) { |
|
| 831 | + return ''; |
|
| 832 | + } |
|
| 833 | + return $REG->receipt_url($type); |
|
| 834 | + } |
|
| 835 | + |
|
| 836 | + |
|
| 837 | + /** |
|
| 838 | + * Gets the URL of the thank you page with this registration REG_url_link added as |
|
| 839 | + * a query parameter |
|
| 840 | + * |
|
| 841 | + * @return string |
|
| 842 | + * @throws EE_Error |
|
| 843 | + * @throws InvalidArgumentException |
|
| 844 | + * @throws InvalidDataTypeException |
|
| 845 | + * @throws InvalidInterfaceException |
|
| 846 | + * @throws ReflectionException |
|
| 847 | + */ |
|
| 848 | + public function payment_overview_url() |
|
| 849 | + { |
|
| 850 | + $primary_registration = $this->primary_registration(); |
|
| 851 | + return $primary_registration instanceof EE_Registration ? $primary_registration->payment_overview_url() : false; |
|
| 852 | + } |
|
| 853 | + |
|
| 854 | + |
|
| 855 | + /** |
|
| 856 | + * @return string |
|
| 857 | + * @throws EE_Error |
|
| 858 | + * @throws InvalidArgumentException |
|
| 859 | + * @throws InvalidDataTypeException |
|
| 860 | + * @throws InvalidInterfaceException |
|
| 861 | + * @throws ReflectionException |
|
| 862 | + */ |
|
| 863 | + public function gateway_response_on_transaction() |
|
| 864 | + { |
|
| 865 | + $payment = $this->get_first_related('Payment'); |
|
| 866 | + return $payment instanceof EE_Payment ? $payment->gateway_response() : ''; |
|
| 867 | + } |
|
| 868 | + |
|
| 869 | + |
|
| 870 | + /** |
|
| 871 | + * Get the status object of this object |
|
| 872 | + * |
|
| 873 | + * @return EE_Base_Class|EE_Status |
|
| 874 | + * @throws EE_Error |
|
| 875 | + * @throws InvalidArgumentException |
|
| 876 | + * @throws InvalidDataTypeException |
|
| 877 | + * @throws InvalidInterfaceException |
|
| 878 | + * @throws ReflectionException |
|
| 879 | + */ |
|
| 880 | + public function status_obj() |
|
| 881 | + { |
|
| 882 | + return $this->get_first_related('Status'); |
|
| 883 | + } |
|
| 884 | + |
|
| 885 | + |
|
| 886 | + /** |
|
| 887 | + * Gets all the extra meta info on this payment |
|
| 888 | + * |
|
| 889 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 890 | + * @return EE_Base_Class[]|EE_Extra_Meta |
|
| 891 | + * @throws EE_Error |
|
| 892 | + * @throws InvalidArgumentException |
|
| 893 | + * @throws InvalidDataTypeException |
|
| 894 | + * @throws InvalidInterfaceException |
|
| 895 | + * @throws ReflectionException |
|
| 896 | + */ |
|
| 897 | + public function extra_meta($query_params = array()) |
|
| 898 | + { |
|
| 899 | + return $this->get_many_related('Extra_Meta', $query_params); |
|
| 900 | + } |
|
| 901 | + |
|
| 902 | + |
|
| 903 | + /** |
|
| 904 | + * Wrapper for _add_relation_to |
|
| 905 | + * |
|
| 906 | + * @param EE_Registration $registration |
|
| 907 | + * @return EE_Base_Class the relation was added to |
|
| 908 | + * @throws EE_Error |
|
| 909 | + * @throws InvalidArgumentException |
|
| 910 | + * @throws InvalidDataTypeException |
|
| 911 | + * @throws InvalidInterfaceException |
|
| 912 | + * @throws ReflectionException |
|
| 913 | + */ |
|
| 914 | + public function add_registration(EE_Registration $registration) |
|
| 915 | + { |
|
| 916 | + return $this->_add_relation_to($registration, 'Registration'); |
|
| 917 | + } |
|
| 918 | + |
|
| 919 | + |
|
| 920 | + /** |
|
| 921 | + * Removes the given registration from being related (even before saving this transaction). |
|
| 922 | + * If an ID/index is provided and this transaction isn't saved yet, removes it from list of cached relations |
|
| 923 | + * |
|
| 924 | + * @param int $registration_or_id |
|
| 925 | + * @return EE_Base_Class that was removed from being related |
|
| 926 | + * @throws EE_Error |
|
| 927 | + * @throws InvalidArgumentException |
|
| 928 | + * @throws InvalidDataTypeException |
|
| 929 | + * @throws InvalidInterfaceException |
|
| 930 | + * @throws ReflectionException |
|
| 931 | + */ |
|
| 932 | + public function remove_registration_with_id($registration_or_id) |
|
| 933 | + { |
|
| 934 | + return $this->_remove_relation_to($registration_or_id, 'Registration'); |
|
| 935 | + } |
|
| 936 | + |
|
| 937 | + |
|
| 938 | + /** |
|
| 939 | + * Gets all the line items which are for ACTUAL items |
|
| 940 | + * |
|
| 941 | + * @return EE_Line_Item[] |
|
| 942 | + * @throws EE_Error |
|
| 943 | + * @throws InvalidArgumentException |
|
| 944 | + * @throws InvalidDataTypeException |
|
| 945 | + * @throws InvalidInterfaceException |
|
| 946 | + * @throws ReflectionException |
|
| 947 | + */ |
|
| 948 | + public function items_purchased() |
|
| 949 | + { |
|
| 950 | + return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_line_item))); |
|
| 951 | + } |
|
| 952 | + |
|
| 953 | + |
|
| 954 | + /** |
|
| 955 | + * Wrapper for _add_relation_to |
|
| 956 | + * |
|
| 957 | + * @param EE_Line_Item $line_item |
|
| 958 | + * @return EE_Base_Class the relation was added to |
|
| 959 | + * @throws EE_Error |
|
| 960 | + * @throws InvalidArgumentException |
|
| 961 | + * @throws InvalidDataTypeException |
|
| 962 | + * @throws InvalidInterfaceException |
|
| 963 | + * @throws ReflectionException |
|
| 964 | + */ |
|
| 965 | + public function add_line_item(EE_Line_Item $line_item) |
|
| 966 | + { |
|
| 967 | + return $this->_add_relation_to($line_item, 'Line_Item'); |
|
| 968 | + } |
|
| 969 | + |
|
| 970 | + |
|
| 971 | + /** |
|
| 972 | + * Gets ALL the line items related to this transaction (unstructured) |
|
| 973 | + * |
|
| 974 | + * @param array $query_params |
|
| 975 | + * @return EE_Base_Class[]|EE_Line_Item[] |
|
| 976 | + * @throws EE_Error |
|
| 977 | + * @throws InvalidArgumentException |
|
| 978 | + * @throws InvalidDataTypeException |
|
| 979 | + * @throws InvalidInterfaceException |
|
| 980 | + * @throws ReflectionException |
|
| 981 | + */ |
|
| 982 | + public function line_items($query_params = array()) |
|
| 983 | + { |
|
| 984 | + return $this->get_many_related('Line_Item', $query_params); |
|
| 985 | + } |
|
| 986 | + |
|
| 987 | + |
|
| 988 | + /** |
|
| 989 | + * Gets all the line items which are taxes on the total |
|
| 990 | + * |
|
| 991 | + * @return EE_Line_Item[] |
|
| 992 | + * @throws EE_Error |
|
| 993 | + * @throws InvalidArgumentException |
|
| 994 | + * @throws InvalidDataTypeException |
|
| 995 | + * @throws InvalidInterfaceException |
|
| 996 | + * @throws ReflectionException |
|
| 997 | + */ |
|
| 998 | + public function tax_items() |
|
| 999 | + { |
|
| 1000 | + return $this->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax))); |
|
| 1001 | + } |
|
| 1002 | + |
|
| 1003 | + |
|
| 1004 | + /** |
|
| 1005 | + * Gets the total line item (which is a parent of all other related line items, |
|
| 1006 | + * meaning it takes them all into account on its total) |
|
| 1007 | + * |
|
| 1008 | + * @param bool $create_if_not_found |
|
| 1009 | + * @return \EE_Line_Item |
|
| 1010 | + * @throws EE_Error |
|
| 1011 | + * @throws InvalidArgumentException |
|
| 1012 | + * @throws InvalidDataTypeException |
|
| 1013 | + * @throws InvalidInterfaceException |
|
| 1014 | + * @throws ReflectionException |
|
| 1015 | + */ |
|
| 1016 | + public function total_line_item($create_if_not_found = true) |
|
| 1017 | + { |
|
| 1018 | + $item = $this->get_first_related('Line_Item', array(array('LIN_type' => EEM_Line_Item::type_total))); |
|
| 1019 | + if (! $item && $create_if_not_found) { |
|
| 1020 | + $item = EEH_Line_Item::create_total_line_item($this); |
|
| 1021 | + } |
|
| 1022 | + return $item; |
|
| 1023 | + } |
|
| 1024 | + |
|
| 1025 | + |
|
| 1026 | + /** |
|
| 1027 | + * Returns the total amount of tax on this transaction |
|
| 1028 | + * (assumes there's only one tax subtotal line item) |
|
| 1029 | + * |
|
| 1030 | + * @return float |
|
| 1031 | + * @throws EE_Error |
|
| 1032 | + * @throws InvalidArgumentException |
|
| 1033 | + * @throws InvalidDataTypeException |
|
| 1034 | + * @throws InvalidInterfaceException |
|
| 1035 | + * @throws ReflectionException |
|
| 1036 | + */ |
|
| 1037 | + public function tax_total() |
|
| 1038 | + { |
|
| 1039 | + $tax_line_item = $this->tax_total_line_item(); |
|
| 1040 | + if ($tax_line_item) { |
|
| 1041 | + return (float) $tax_line_item->total(); |
|
| 1042 | + } |
|
| 1043 | + return (float) 0; |
|
| 1044 | + } |
|
| 1045 | + |
|
| 1046 | + |
|
| 1047 | + /** |
|
| 1048 | + * Gets the tax subtotal line item (assumes there's only one) |
|
| 1049 | + * |
|
| 1050 | + * @return EE_Line_Item |
|
| 1051 | + * @throws EE_Error |
|
| 1052 | + * @throws InvalidArgumentException |
|
| 1053 | + * @throws InvalidDataTypeException |
|
| 1054 | + * @throws InvalidInterfaceException |
|
| 1055 | + * @throws ReflectionException |
|
| 1056 | + */ |
|
| 1057 | + public function tax_total_line_item() |
|
| 1058 | + { |
|
| 1059 | + return EEH_Line_Item::get_taxes_subtotal($this->total_line_item()); |
|
| 1060 | + } |
|
| 1061 | + |
|
| 1062 | + |
|
| 1063 | + /** |
|
| 1064 | + * Gets the array of billing info for the gateway and for this transaction's primary registration's attendee. |
|
| 1065 | + * |
|
| 1066 | + * @return EE_Form_Section_Proper |
|
| 1067 | + * @throws EE_Error |
|
| 1068 | + * @throws InvalidArgumentException |
|
| 1069 | + * @throws InvalidDataTypeException |
|
| 1070 | + * @throws InvalidInterfaceException |
|
| 1071 | + * @throws ReflectionException |
|
| 1072 | + */ |
|
| 1073 | + public function billing_info() |
|
| 1074 | + { |
|
| 1075 | + $payment_method = $this->payment_method(); |
|
| 1076 | + if (! $payment_method) { |
|
| 1077 | + EE_Error::add_error( |
|
| 1078 | + __( |
|
| 1079 | + 'Could not find billing info for transaction because no gateway has been used for it yet', |
|
| 1080 | + 'event_espresso' |
|
| 1081 | + ), |
|
| 1082 | + __FILE__, |
|
| 1083 | + __FUNCTION__, |
|
| 1084 | + __LINE__ |
|
| 1085 | + ); |
|
| 1086 | + return null; |
|
| 1087 | + } |
|
| 1088 | + $primary_reg = $this->primary_registration(); |
|
| 1089 | + if (! $primary_reg) { |
|
| 1090 | + EE_Error::add_error( |
|
| 1091 | + __( |
|
| 1092 | + 'Cannot get billing info for gateway %s on transaction because no primary registration exists', |
|
| 1093 | + 'event_espresso' |
|
| 1094 | + ), |
|
| 1095 | + __FILE__, |
|
| 1096 | + __FUNCTION__, |
|
| 1097 | + __LINE__ |
|
| 1098 | + ); |
|
| 1099 | + return null; |
|
| 1100 | + } |
|
| 1101 | + $attendee = $primary_reg->attendee(); |
|
| 1102 | + if (! $attendee) { |
|
| 1103 | + EE_Error::add_error( |
|
| 1104 | + __( |
|
| 1105 | + 'Cannot get billing info for gateway %s on transaction because the primary registration has no attendee exists', |
|
| 1106 | + 'event_espresso' |
|
| 1107 | + ), |
|
| 1108 | + __FILE__, |
|
| 1109 | + __FUNCTION__, |
|
| 1110 | + __LINE__ |
|
| 1111 | + ); |
|
| 1112 | + return null; |
|
| 1113 | + } |
|
| 1114 | + return $attendee->billing_info_for_payment_method($payment_method); |
|
| 1115 | + } |
|
| 1116 | + |
|
| 1117 | + |
|
| 1118 | + /** |
|
| 1119 | + * Gets PMD_ID |
|
| 1120 | + * |
|
| 1121 | + * @return int |
|
| 1122 | + * @throws EE_Error |
|
| 1123 | + * @throws InvalidArgumentException |
|
| 1124 | + * @throws InvalidDataTypeException |
|
| 1125 | + * @throws InvalidInterfaceException |
|
| 1126 | + * @throws ReflectionException |
|
| 1127 | + */ |
|
| 1128 | + public function payment_method_ID() |
|
| 1129 | + { |
|
| 1130 | + return $this->get('PMD_ID'); |
|
| 1131 | + } |
|
| 1132 | + |
|
| 1133 | + |
|
| 1134 | + /** |
|
| 1135 | + * Sets PMD_ID |
|
| 1136 | + * |
|
| 1137 | + * @param int $PMD_ID |
|
| 1138 | + * @throws EE_Error |
|
| 1139 | + * @throws InvalidArgumentException |
|
| 1140 | + * @throws InvalidDataTypeException |
|
| 1141 | + * @throws InvalidInterfaceException |
|
| 1142 | + * @throws ReflectionException |
|
| 1143 | + */ |
|
| 1144 | + public function set_payment_method_ID($PMD_ID) |
|
| 1145 | + { |
|
| 1146 | + $this->set('PMD_ID', $PMD_ID); |
|
| 1147 | + } |
|
| 1148 | + |
|
| 1149 | + |
|
| 1150 | + /** |
|
| 1151 | + * Gets the last-used payment method on this transaction |
|
| 1152 | + * (we COULD just use the last-made payment, but some payment methods, namely |
|
| 1153 | + * offline ones, dont' create payments) |
|
| 1154 | + * |
|
| 1155 | + * @return EE_Payment_Method |
|
| 1156 | + * @throws EE_Error |
|
| 1157 | + * @throws InvalidArgumentException |
|
| 1158 | + * @throws InvalidDataTypeException |
|
| 1159 | + * @throws InvalidInterfaceException |
|
| 1160 | + * @throws ReflectionException |
|
| 1161 | + */ |
|
| 1162 | + public function payment_method() |
|
| 1163 | + { |
|
| 1164 | + $pm = $this->get_first_related('Payment_Method'); |
|
| 1165 | + if ($pm instanceof EE_Payment_Method) { |
|
| 1166 | + return $pm; |
|
| 1167 | + } |
|
| 1168 | + $last_payment = $this->last_payment(); |
|
| 1169 | + if ($last_payment instanceof EE_Payment && $last_payment->payment_method()) { |
|
| 1170 | + return $last_payment->payment_method(); |
|
| 1171 | + } |
|
| 1172 | + return null; |
|
| 1173 | + } |
|
| 1174 | + |
|
| 1175 | + |
|
| 1176 | + /** |
|
| 1177 | + * Gets the last payment made |
|
| 1178 | + * |
|
| 1179 | + * @return EE_Base_Class|EE_Payment |
|
| 1180 | + * @throws EE_Error |
|
| 1181 | + * @throws InvalidArgumentException |
|
| 1182 | + * @throws InvalidDataTypeException |
|
| 1183 | + * @throws InvalidInterfaceException |
|
| 1184 | + * @throws ReflectionException |
|
| 1185 | + */ |
|
| 1186 | + public function last_payment() |
|
| 1187 | + { |
|
| 1188 | + return $this->get_first_related('Payment', array('order_by' => array('PAY_ID' => 'desc'))); |
|
| 1189 | + } |
|
| 1190 | + |
|
| 1191 | + |
|
| 1192 | + /** |
|
| 1193 | + * Gets all the line items which are unrelated to tickets on this transaction |
|
| 1194 | + * |
|
| 1195 | + * @return EE_Line_Item[] |
|
| 1196 | + * @throws EE_Error |
|
| 1197 | + * @throws InvalidArgumentException |
|
| 1198 | + * @throws InvalidDataTypeException |
|
| 1199 | + * @throws InvalidInterfaceException |
|
| 1200 | + * @throws ReflectionException |
|
| 1201 | + */ |
|
| 1202 | + public function non_ticket_line_items() |
|
| 1203 | + { |
|
| 1204 | + return EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction($this->ID()); |
|
| 1205 | + } |
|
| 1206 | + |
|
| 1207 | + |
|
| 1208 | + /** |
|
| 1209 | + * possibly toggles TXN status |
|
| 1210 | + * |
|
| 1211 | + * @param boolean $update whether to save the TXN |
|
| 1212 | + * @return bool whether the TXN was saved |
|
| 1213 | + * @throws EE_Error |
|
| 1214 | + * @throws InvalidArgumentException |
|
| 1215 | + * @throws InvalidDataTypeException |
|
| 1216 | + * @throws InvalidInterfaceException |
|
| 1217 | + * @throws ReflectionException |
|
| 1218 | + * @throws RuntimeException |
|
| 1219 | + */ |
|
| 1220 | + public function update_status_based_on_total_paid($update = true) |
|
| 1221 | + { |
|
| 1222 | + // set transaction status based on comparison of TXN_paid vs TXN_total |
|
| 1223 | + if (EEH_Money::compare_floats($this->paid(), $this->total(), '>')) { |
|
| 1224 | + $new_txn_status = EEM_Transaction::overpaid_status_code; |
|
| 1225 | + } elseif (EEH_Money::compare_floats($this->paid(), $this->total())) { |
|
| 1226 | + $new_txn_status = EEM_Transaction::complete_status_code; |
|
| 1227 | + } elseif (EEH_Money::compare_floats($this->paid(), $this->total(), '<')) { |
|
| 1228 | + $new_txn_status = EEM_Transaction::incomplete_status_code; |
|
| 1229 | + } else { |
|
| 1230 | + throw new RuntimeException( |
|
| 1231 | + __('The total paid calculation for this transaction is inaccurate.', 'event_espresso') |
|
| 1232 | + ); |
|
| 1233 | + } |
|
| 1234 | + if ($new_txn_status !== $this->status_ID()) { |
|
| 1235 | + $this->set_status($new_txn_status); |
|
| 1236 | + if ($update) { |
|
| 1237 | + return $this->save() ? true : false; |
|
| 1238 | + } |
|
| 1239 | + } |
|
| 1240 | + return false; |
|
| 1241 | + } |
|
| 1242 | + |
|
| 1243 | + |
|
| 1244 | + /** |
|
| 1245 | + * Updates the transaction's status and total_paid based on all the payments |
|
| 1246 | + * that apply to it |
|
| 1247 | + * |
|
| 1248 | + * @deprecated |
|
| 1249 | + * @return array|bool |
|
| 1250 | + * @throws EE_Error |
|
| 1251 | + * @throws InvalidArgumentException |
|
| 1252 | + * @throws ReflectionException |
|
| 1253 | + * @throws InvalidDataTypeException |
|
| 1254 | + * @throws InvalidInterfaceException |
|
| 1255 | + */ |
|
| 1256 | + public function update_based_on_payments() |
|
| 1257 | + { |
|
| 1258 | + EE_Error::doing_it_wrong( |
|
| 1259 | + __CLASS__ . '::' . __FUNCTION__, |
|
| 1260 | + sprintf( |
|
| 1261 | + __('This method is deprecated. Please use "%s" instead', 'event_espresso'), |
|
| 1262 | + 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()' |
|
| 1263 | + ), |
|
| 1264 | + '4.6.0' |
|
| 1265 | + ); |
|
| 1266 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 1267 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 1268 | + return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment($this); |
|
| 1269 | + } |
|
| 1270 | + |
|
| 1271 | + |
|
| 1272 | + /** |
|
| 1273 | + * @return string |
|
| 1274 | + */ |
|
| 1275 | + public function old_txn_status() |
|
| 1276 | + { |
|
| 1277 | + return $this->_old_txn_status; |
|
| 1278 | + } |
|
| 1279 | + |
|
| 1280 | + |
|
| 1281 | + /** |
|
| 1282 | + * @param string $old_txn_status |
|
| 1283 | + */ |
|
| 1284 | + public function set_old_txn_status($old_txn_status) |
|
| 1285 | + { |
|
| 1286 | + // only set the first time |
|
| 1287 | + if ($this->_old_txn_status === null) { |
|
| 1288 | + $this->_old_txn_status = $old_txn_status; |
|
| 1289 | + } |
|
| 1290 | + } |
|
| 1291 | + |
|
| 1292 | + |
|
| 1293 | + /** |
|
| 1294 | + * reg_status_updated |
|
| 1295 | + * |
|
| 1296 | + * @return bool |
|
| 1297 | + * @throws EE_Error |
|
| 1298 | + * @throws InvalidArgumentException |
|
| 1299 | + * @throws InvalidDataTypeException |
|
| 1300 | + * @throws InvalidInterfaceException |
|
| 1301 | + * @throws ReflectionException |
|
| 1302 | + */ |
|
| 1303 | + public function txn_status_updated() |
|
| 1304 | + { |
|
| 1305 | + return $this->status_ID() !== $this->_old_txn_status && $this->_old_txn_status !== null; |
|
| 1306 | + } |
|
| 1307 | + |
|
| 1308 | + |
|
| 1309 | + /** |
|
| 1310 | + * _reg_steps_completed |
|
| 1311 | + * if $check_all is TRUE, then returns TRUE if ALL reg steps have been marked as completed, |
|
| 1312 | + * if a $reg_step_slug is provided, then this step will be skipped when testing for completion |
|
| 1313 | + * if $check_all is FALSE and a $reg_step_slug is provided, then ONLY that reg step will be tested for completion |
|
| 1314 | + * |
|
| 1315 | + * @param string $reg_step_slug |
|
| 1316 | + * @param bool $check_all |
|
| 1317 | + * @return bool|int |
|
| 1318 | + * @throws EE_Error |
|
| 1319 | + * @throws InvalidArgumentException |
|
| 1320 | + * @throws InvalidDataTypeException |
|
| 1321 | + * @throws InvalidInterfaceException |
|
| 1322 | + * @throws ReflectionException |
|
| 1323 | + */ |
|
| 1324 | + private function _reg_steps_completed($reg_step_slug = '', $check_all = true) |
|
| 1325 | + { |
|
| 1326 | + $reg_steps = $this->reg_steps(); |
|
| 1327 | + if (! is_array($reg_steps) || empty($reg_steps)) { |
|
| 1328 | + return false; |
|
| 1329 | + } |
|
| 1330 | + // loop thru reg steps array) |
|
| 1331 | + foreach ($reg_steps as $slug => $reg_step_completed) { |
|
| 1332 | + // if NOT checking ALL steps (only checking one step) |
|
| 1333 | + if (! $check_all) { |
|
| 1334 | + // and this is the one |
|
| 1335 | + if ($slug === $reg_step_slug) { |
|
| 1336 | + return $reg_step_completed; |
|
| 1337 | + } |
|
| 1338 | + // skip to next reg step in loop |
|
| 1339 | + continue; |
|
| 1340 | + } |
|
| 1341 | + // $check_all must be true, else we would never have gotten to this point |
|
| 1342 | + if ($slug === $reg_step_slug) { |
|
| 1343 | + // if we reach this point, then we are testing either: |
|
| 1344 | + // all_reg_steps_completed_except() or |
|
| 1345 | + // all_reg_steps_completed_except_final_step(), |
|
| 1346 | + // and since this is the reg step EXCEPTION being tested |
|
| 1347 | + // we want to return true (yes true) if this reg step is NOT completed |
|
| 1348 | + // ie: "is everything completed except the final step?" |
|
| 1349 | + // "that is correct... the final step is not completed, but all others are." |
|
| 1350 | + return $reg_step_completed !== true; |
|
| 1351 | + } |
|
| 1352 | + if ($reg_step_completed !== true) { |
|
| 1353 | + // if any reg step is NOT completed, then ALL steps are not completed |
|
| 1354 | + return false; |
|
| 1355 | + } |
|
| 1356 | + } |
|
| 1357 | + return true; |
|
| 1358 | + } |
|
| 1359 | + |
|
| 1360 | + |
|
| 1361 | + /** |
|
| 1362 | + * all_reg_steps_completed |
|
| 1363 | + * returns: |
|
| 1364 | + * true if ALL reg steps have been marked as completed |
|
| 1365 | + * or false if any step is not completed |
|
| 1366 | + * |
|
| 1367 | + * @return bool |
|
| 1368 | + * @throws EE_Error |
|
| 1369 | + * @throws InvalidArgumentException |
|
| 1370 | + * @throws InvalidDataTypeException |
|
| 1371 | + * @throws InvalidInterfaceException |
|
| 1372 | + * @throws ReflectionException |
|
| 1373 | + */ |
|
| 1374 | + public function all_reg_steps_completed() |
|
| 1375 | + { |
|
| 1376 | + return $this->_reg_steps_completed(); |
|
| 1377 | + } |
|
| 1378 | + |
|
| 1379 | + |
|
| 1380 | + /** |
|
| 1381 | + * all_reg_steps_completed_except |
|
| 1382 | + * returns: |
|
| 1383 | + * true if ALL reg steps, except a particular step that you wish to skip over, have been marked as completed |
|
| 1384 | + * or false if any other step is not completed |
|
| 1385 | + * or false if ALL steps are completed including the exception you are testing !!! |
|
| 1386 | + * |
|
| 1387 | + * @param string $exception |
|
| 1388 | + * @return bool |
|
| 1389 | + * @throws EE_Error |
|
| 1390 | + * @throws InvalidArgumentException |
|
| 1391 | + * @throws InvalidDataTypeException |
|
| 1392 | + * @throws InvalidInterfaceException |
|
| 1393 | + * @throws ReflectionException |
|
| 1394 | + */ |
|
| 1395 | + public function all_reg_steps_completed_except($exception = '') |
|
| 1396 | + { |
|
| 1397 | + return $this->_reg_steps_completed($exception); |
|
| 1398 | + } |
|
| 1399 | + |
|
| 1400 | + |
|
| 1401 | + /** |
|
| 1402 | + * all_reg_steps_completed_except |
|
| 1403 | + * returns: |
|
| 1404 | + * true if ALL reg steps, except the final step, have been marked as completed |
|
| 1405 | + * or false if any step is not completed |
|
| 1406 | + * or false if ALL steps are completed including the final step !!! |
|
| 1407 | + * |
|
| 1408 | + * @return bool |
|
| 1409 | + * @throws EE_Error |
|
| 1410 | + * @throws InvalidArgumentException |
|
| 1411 | + * @throws InvalidDataTypeException |
|
| 1412 | + * @throws InvalidInterfaceException |
|
| 1413 | + * @throws ReflectionException |
|
| 1414 | + */ |
|
| 1415 | + public function all_reg_steps_completed_except_final_step() |
|
| 1416 | + { |
|
| 1417 | + return $this->_reg_steps_completed('finalize_registration'); |
|
| 1418 | + } |
|
| 1419 | + |
|
| 1420 | + |
|
| 1421 | + /** |
|
| 1422 | + * reg_step_completed |
|
| 1423 | + * returns: |
|
| 1424 | + * true if a specific reg step has been marked as completed |
|
| 1425 | + * a Unix timestamp if it has been initialized but not yet completed, |
|
| 1426 | + * or false if it has not yet been initialized |
|
| 1427 | + * |
|
| 1428 | + * @param string $reg_step_slug |
|
| 1429 | + * @return bool|int |
|
| 1430 | + * @throws EE_Error |
|
| 1431 | + * @throws InvalidArgumentException |
|
| 1432 | + * @throws InvalidDataTypeException |
|
| 1433 | + * @throws InvalidInterfaceException |
|
| 1434 | + * @throws ReflectionException |
|
| 1435 | + */ |
|
| 1436 | + public function reg_step_completed($reg_step_slug) |
|
| 1437 | + { |
|
| 1438 | + return $this->_reg_steps_completed($reg_step_slug, false); |
|
| 1439 | + } |
|
| 1440 | + |
|
| 1441 | + |
|
| 1442 | + /** |
|
| 1443 | + * completed_final_reg_step |
|
| 1444 | + * returns: |
|
| 1445 | + * true if the finalize_registration reg step has been marked as completed |
|
| 1446 | + * a Unix timestamp if it has been initialized but not yet completed, |
|
| 1447 | + * or false if it has not yet been initialized |
|
| 1448 | + * |
|
| 1449 | + * @return bool|int |
|
| 1450 | + * @throws EE_Error |
|
| 1451 | + * @throws InvalidArgumentException |
|
| 1452 | + * @throws InvalidDataTypeException |
|
| 1453 | + * @throws InvalidInterfaceException |
|
| 1454 | + * @throws ReflectionException |
|
| 1455 | + */ |
|
| 1456 | + public function final_reg_step_completed() |
|
| 1457 | + { |
|
| 1458 | + return $this->_reg_steps_completed('finalize_registration', false); |
|
| 1459 | + } |
|
| 1460 | + |
|
| 1461 | + |
|
| 1462 | + /** |
|
| 1463 | + * set_reg_step_initiated |
|
| 1464 | + * given a valid TXN_reg_step, this sets it's value to a unix timestamp |
|
| 1465 | + * |
|
| 1466 | + * @param string $reg_step_slug |
|
| 1467 | + * @return boolean |
|
| 1468 | + * @throws EE_Error |
|
| 1469 | + * @throws InvalidArgumentException |
|
| 1470 | + * @throws InvalidDataTypeException |
|
| 1471 | + * @throws InvalidInterfaceException |
|
| 1472 | + * @throws ReflectionException |
|
| 1473 | + */ |
|
| 1474 | + public function set_reg_step_initiated($reg_step_slug) |
|
| 1475 | + { |
|
| 1476 | + return $this->_set_reg_step_completed_status($reg_step_slug, time()); |
|
| 1477 | + } |
|
| 1478 | + |
|
| 1479 | + |
|
| 1480 | + /** |
|
| 1481 | + * set_reg_step_completed |
|
| 1482 | + * given a valid TXN_reg_step, this sets the step as completed |
|
| 1483 | + * |
|
| 1484 | + * @param string $reg_step_slug |
|
| 1485 | + * @return boolean |
|
| 1486 | + * @throws EE_Error |
|
| 1487 | + * @throws InvalidArgumentException |
|
| 1488 | + * @throws InvalidDataTypeException |
|
| 1489 | + * @throws InvalidInterfaceException |
|
| 1490 | + * @throws ReflectionException |
|
| 1491 | + */ |
|
| 1492 | + public function set_reg_step_completed($reg_step_slug) |
|
| 1493 | + { |
|
| 1494 | + return $this->_set_reg_step_completed_status($reg_step_slug, true); |
|
| 1495 | + } |
|
| 1496 | + |
|
| 1497 | + |
|
| 1498 | + /** |
|
| 1499 | + * set_reg_step_completed |
|
| 1500 | + * given a valid TXN_reg_step slug, this sets the step as NOT completed |
|
| 1501 | + * |
|
| 1502 | + * @param string $reg_step_slug |
|
| 1503 | + * @return boolean |
|
| 1504 | + * @throws EE_Error |
|
| 1505 | + * @throws InvalidArgumentException |
|
| 1506 | + * @throws InvalidDataTypeException |
|
| 1507 | + * @throws InvalidInterfaceException |
|
| 1508 | + * @throws ReflectionException |
|
| 1509 | + */ |
|
| 1510 | + public function set_reg_step_not_completed($reg_step_slug) |
|
| 1511 | + { |
|
| 1512 | + return $this->_set_reg_step_completed_status($reg_step_slug, false); |
|
| 1513 | + } |
|
| 1514 | + |
|
| 1515 | + |
|
| 1516 | + /** |
|
| 1517 | + * set_reg_step_completed |
|
| 1518 | + * given a valid reg step slug, this sets the TXN_reg_step completed status which is either: |
|
| 1519 | + * |
|
| 1520 | + * @param string $reg_step_slug |
|
| 1521 | + * @param boolean|int $status |
|
| 1522 | + * @return boolean |
|
| 1523 | + * @throws EE_Error |
|
| 1524 | + * @throws InvalidArgumentException |
|
| 1525 | + * @throws InvalidDataTypeException |
|
| 1526 | + * @throws InvalidInterfaceException |
|
| 1527 | + * @throws ReflectionException |
|
| 1528 | + */ |
|
| 1529 | + private function _set_reg_step_completed_status($reg_step_slug, $status) |
|
| 1530 | + { |
|
| 1531 | + // validate status |
|
| 1532 | + $status = is_bool($status) || is_int($status) ? $status : false; |
|
| 1533 | + // get reg steps array |
|
| 1534 | + $txn_reg_steps = $this->reg_steps(); |
|
| 1535 | + // if reg step does NOT exist |
|
| 1536 | + if (! isset($txn_reg_steps[ $reg_step_slug ])) { |
|
| 1537 | + return false; |
|
| 1538 | + } |
|
| 1539 | + // if we're trying to complete a step that is already completed |
|
| 1540 | + if ($txn_reg_steps[ $reg_step_slug ] === true) { |
|
| 1541 | + return true; |
|
| 1542 | + } |
|
| 1543 | + // if we're trying to complete a step that hasn't even started |
|
| 1544 | + if ($status === true && $txn_reg_steps[ $reg_step_slug ] === false) { |
|
| 1545 | + return false; |
|
| 1546 | + } |
|
| 1547 | + // if current status value matches the incoming value (no change) |
|
| 1548 | + // type casting as int means values should collapse to either 0, 1, or a timestamp like 1234567890 |
|
| 1549 | + if ((int) $txn_reg_steps[ $reg_step_slug ] === (int) $status) { |
|
| 1550 | + // this will happen in cases where multiple AJAX requests occur during the same step |
|
| 1551 | + return true; |
|
| 1552 | + } |
|
| 1553 | + // if we're trying to set a start time, but it has already been set... |
|
| 1554 | + if (is_numeric($status) && is_numeric($txn_reg_steps[ $reg_step_slug ])) { |
|
| 1555 | + // skip the update below, but don't return FALSE so that errors won't be displayed |
|
| 1556 | + return true; |
|
| 1557 | + } |
|
| 1558 | + // update completed status |
|
| 1559 | + $txn_reg_steps[ $reg_step_slug ] = $status; |
|
| 1560 | + $this->set_reg_steps($txn_reg_steps); |
|
| 1561 | + $this->save(); |
|
| 1562 | + return true; |
|
| 1563 | + } |
|
| 1564 | + |
|
| 1565 | + |
|
| 1566 | + /** |
|
| 1567 | + * remove_reg_step |
|
| 1568 | + * given a valid TXN_reg_step slug, this will remove (unset) |
|
| 1569 | + * the reg step from the TXN reg step array |
|
| 1570 | + * |
|
| 1571 | + * @param string $reg_step_slug |
|
| 1572 | + * @return void |
|
| 1573 | + * @throws EE_Error |
|
| 1574 | + * @throws InvalidArgumentException |
|
| 1575 | + * @throws InvalidDataTypeException |
|
| 1576 | + * @throws InvalidInterfaceException |
|
| 1577 | + * @throws ReflectionException |
|
| 1578 | + */ |
|
| 1579 | + public function remove_reg_step($reg_step_slug) |
|
| 1580 | + { |
|
| 1581 | + // get reg steps array |
|
| 1582 | + $txn_reg_steps = $this->reg_steps(); |
|
| 1583 | + unset($txn_reg_steps[ $reg_step_slug ]); |
|
| 1584 | + $this->set_reg_steps($txn_reg_steps); |
|
| 1585 | + } |
|
| 1586 | + |
|
| 1587 | + |
|
| 1588 | + /** |
|
| 1589 | + * toggle_failed_transaction_status |
|
| 1590 | + * upgrades a TXNs status from failed to abandoned, |
|
| 1591 | + * meaning that contact information has been captured for at least one registrant |
|
| 1592 | + * |
|
| 1593 | + * @param bool $save |
|
| 1594 | + * @return bool |
|
| 1595 | + * @throws EE_Error |
|
| 1596 | + * @throws InvalidArgumentException |
|
| 1597 | + * @throws InvalidDataTypeException |
|
| 1598 | + * @throws InvalidInterfaceException |
|
| 1599 | + * @throws ReflectionException |
|
| 1600 | + */ |
|
| 1601 | + public function toggle_failed_transaction_status($save = true) |
|
| 1602 | + { |
|
| 1603 | + // if TXN status is still set as "failed"... |
|
| 1604 | + if ($this->status_ID() === EEM_Transaction::failed_status_code) { |
|
| 1605 | + $this->set_status(EEM_Transaction::abandoned_status_code); |
|
| 1606 | + if ($save) { |
|
| 1607 | + $this->save(); |
|
| 1608 | + } |
|
| 1609 | + return true; |
|
| 1610 | + } |
|
| 1611 | + return false; |
|
| 1612 | + } |
|
| 1613 | + |
|
| 1614 | + |
|
| 1615 | + /** |
|
| 1616 | + * toggle_abandoned_transaction_status |
|
| 1617 | + * upgrades a TXNs status from failed or abandoned to incomplete |
|
| 1618 | + * |
|
| 1619 | + * @return bool |
|
| 1620 | + * @throws EE_Error |
|
| 1621 | + * @throws InvalidArgumentException |
|
| 1622 | + * @throws InvalidDataTypeException |
|
| 1623 | + * @throws InvalidInterfaceException |
|
| 1624 | + * @throws ReflectionException |
|
| 1625 | + */ |
|
| 1626 | + public function toggle_abandoned_transaction_status() |
|
| 1627 | + { |
|
| 1628 | + // if TXN status has not been updated already due to a payment, and is still set as "failed" or "abandoned"... |
|
| 1629 | + $txn_status = $this->status_ID(); |
|
| 1630 | + if ($txn_status === EEM_Transaction::failed_status_code |
|
| 1631 | + || $txn_status === EEM_Transaction::abandoned_status_code |
|
| 1632 | + ) { |
|
| 1633 | + // if a contact record for the primary registrant has been created |
|
| 1634 | + if ($this->primary_registration() instanceof EE_Registration |
|
| 1635 | + && $this->primary_registration()->attendee() instanceof EE_Attendee |
|
| 1636 | + ) { |
|
| 1637 | + $this->set_status(EEM_Transaction::incomplete_status_code); |
|
| 1638 | + } else { |
|
| 1639 | + // no contact record? yer abandoned! |
|
| 1640 | + $this->set_status(EEM_Transaction::abandoned_status_code); |
|
| 1641 | + } |
|
| 1642 | + return true; |
|
| 1643 | + } |
|
| 1644 | + return false; |
|
| 1645 | + } |
|
| 1646 | + |
|
| 1647 | + |
|
| 1648 | + /** |
|
| 1649 | + * checks if an Abandoned TXN has any related payments, and if so, |
|
| 1650 | + * updates the TXN status based on the amount paid |
|
| 1651 | + * |
|
| 1652 | + * @throws EE_Error |
|
| 1653 | + * @throws InvalidDataTypeException |
|
| 1654 | + * @throws InvalidInterfaceException |
|
| 1655 | + * @throws InvalidArgumentException |
|
| 1656 | + * @throws RuntimeException |
|
| 1657 | + * @throws ReflectionException |
|
| 1658 | + */ |
|
| 1659 | + public function verify_abandoned_transaction_status() |
|
| 1660 | + { |
|
| 1661 | + if ($this->status_ID() !== EEM_Transaction::abandoned_status_code) { |
|
| 1662 | + return; |
|
| 1663 | + } |
|
| 1664 | + $payments = $this->get_many_related('Payment'); |
|
| 1665 | + if (! empty($payments)) { |
|
| 1666 | + foreach ($payments as $payment) { |
|
| 1667 | + if ($payment instanceof EE_Payment) { |
|
| 1668 | + // kk this TXN should NOT be abandoned |
|
| 1669 | + $this->update_status_based_on_total_paid(); |
|
| 1670 | + if (! (defined('DOING_AJAX') && DOING_AJAX) && is_admin()) { |
|
| 1671 | + EE_Error::add_attention( |
|
| 1672 | + sprintf( |
|
| 1673 | + esc_html__( |
|
| 1674 | + 'The status for Transaction #%1$d has been updated from "Abandoned" to "%2$s", because at least one payment has been made towards it. If the payment appears in the "Payment Details" table below, you may need to edit its status and/or other details as well.', |
|
| 1675 | + 'event_espresso' |
|
| 1676 | + ), |
|
| 1677 | + $this->ID(), |
|
| 1678 | + $this->pretty_status() |
|
| 1679 | + ) |
|
| 1680 | + ); |
|
| 1681 | + } |
|
| 1682 | + // get final reg step status |
|
| 1683 | + $finalized = $this->final_reg_step_completed(); |
|
| 1684 | + // if the 'finalize_registration' step has been initiated (has a timestamp) |
|
| 1685 | + // but has not yet been fully completed (TRUE) |
|
| 1686 | + if (is_int($finalized) && $finalized !== false && $finalized !== true) { |
|
| 1687 | + $this->set_reg_step_completed('finalize_registration'); |
|
| 1688 | + $this->save(); |
|
| 1689 | + } |
|
| 1690 | + } |
|
| 1691 | + } |
|
| 1692 | + } |
|
| 1693 | + } |
|
| 1694 | 1694 | } |
@@ -16,1259 +16,1259 @@ |
||
| 16 | 16 | { |
| 17 | 17 | |
| 18 | 18 | |
| 19 | - /** |
|
| 20 | - * This is used to hold the reports template data which is setup early in the request. |
|
| 21 | - * |
|
| 22 | - * @type array |
|
| 23 | - */ |
|
| 24 | - protected $_reports_template_data = array(); |
|
| 19 | + /** |
|
| 20 | + * This is used to hold the reports template data which is setup early in the request. |
|
| 21 | + * |
|
| 22 | + * @type array |
|
| 23 | + */ |
|
| 24 | + protected $_reports_template_data = array(); |
|
| 25 | 25 | |
| 26 | 26 | |
| 27 | - /** |
|
| 28 | - * Extend_Registrations_Admin_Page constructor. |
|
| 29 | - * |
|
| 30 | - * @param bool $routing |
|
| 31 | - */ |
|
| 32 | - public function __construct($routing = true) |
|
| 33 | - { |
|
| 34 | - parent::__construct($routing); |
|
| 35 | - if (! defined('REG_CAF_TEMPLATE_PATH')) { |
|
| 36 | - define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/'); |
|
| 37 | - define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/'); |
|
| 38 | - define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/'); |
|
| 39 | - } |
|
| 40 | - } |
|
| 27 | + /** |
|
| 28 | + * Extend_Registrations_Admin_Page constructor. |
|
| 29 | + * |
|
| 30 | + * @param bool $routing |
|
| 31 | + */ |
|
| 32 | + public function __construct($routing = true) |
|
| 33 | + { |
|
| 34 | + parent::__construct($routing); |
|
| 35 | + if (! defined('REG_CAF_TEMPLATE_PATH')) { |
|
| 36 | + define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/'); |
|
| 37 | + define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/'); |
|
| 38 | + define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/'); |
|
| 39 | + } |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | 42 | |
| 43 | - /** |
|
| 44 | - * Extending page configuration. |
|
| 45 | - */ |
|
| 46 | - protected function _extend_page_config() |
|
| 47 | - { |
|
| 48 | - $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations'; |
|
| 49 | - $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID']) |
|
| 50 | - ? $this->_req_data['_REG_ID'] |
|
| 51 | - : 0; |
|
| 52 | - $new_page_routes = array( |
|
| 53 | - 'reports' => array( |
|
| 54 | - 'func' => '_registration_reports', |
|
| 55 | - 'capability' => 'ee_read_registrations', |
|
| 56 | - ), |
|
| 57 | - 'registration_checkins' => array( |
|
| 58 | - 'func' => '_registration_checkin_list_table', |
|
| 59 | - 'capability' => 'ee_read_checkins', |
|
| 60 | - ), |
|
| 61 | - 'newsletter_selected_send' => array( |
|
| 62 | - 'func' => '_newsletter_selected_send', |
|
| 63 | - 'noheader' => true, |
|
| 64 | - 'capability' => 'ee_send_message', |
|
| 65 | - ), |
|
| 66 | - 'delete_checkin_rows' => array( |
|
| 67 | - 'func' => '_delete_checkin_rows', |
|
| 68 | - 'noheader' => true, |
|
| 69 | - 'capability' => 'ee_delete_checkins', |
|
| 70 | - ), |
|
| 71 | - 'delete_checkin_row' => array( |
|
| 72 | - 'func' => '_delete_checkin_row', |
|
| 73 | - 'noheader' => true, |
|
| 74 | - 'capability' => 'ee_delete_checkin', |
|
| 75 | - 'obj_id' => $reg_id, |
|
| 76 | - ), |
|
| 77 | - 'toggle_checkin_status' => array( |
|
| 78 | - 'func' => '_toggle_checkin_status', |
|
| 79 | - 'noheader' => true, |
|
| 80 | - 'capability' => 'ee_edit_checkin', |
|
| 81 | - 'obj_id' => $reg_id, |
|
| 82 | - ), |
|
| 83 | - 'toggle_checkin_status_bulk' => array( |
|
| 84 | - 'func' => '_toggle_checkin_status', |
|
| 85 | - 'noheader' => true, |
|
| 86 | - 'capability' => 'ee_edit_checkins', |
|
| 87 | - ), |
|
| 88 | - 'event_registrations' => array( |
|
| 89 | - 'func' => '_event_registrations_list_table', |
|
| 90 | - 'capability' => 'ee_read_checkins', |
|
| 91 | - ), |
|
| 92 | - 'registrations_checkin_report' => array( |
|
| 93 | - 'func' => '_registrations_checkin_report', |
|
| 94 | - 'noheader' => true, |
|
| 95 | - 'capability' => 'ee_read_registrations', |
|
| 96 | - ), |
|
| 97 | - ); |
|
| 98 | - $this->_page_routes = array_merge($this->_page_routes, $new_page_routes); |
|
| 99 | - $new_page_config = array( |
|
| 100 | - 'reports' => array( |
|
| 101 | - 'nav' => array( |
|
| 102 | - 'label' => esc_html__('Reports', 'event_espresso'), |
|
| 103 | - 'order' => 30, |
|
| 104 | - ), |
|
| 105 | - 'help_tabs' => array( |
|
| 106 | - 'registrations_reports_help_tab' => array( |
|
| 107 | - 'title' => esc_html__('Registration Reports', 'event_espresso'), |
|
| 108 | - 'filename' => 'registrations_reports', |
|
| 109 | - ), |
|
| 110 | - ), |
|
| 111 | - /*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/ |
|
| 112 | - 'require_nonce' => false, |
|
| 113 | - ), |
|
| 114 | - 'event_registrations' => array( |
|
| 115 | - 'nav' => array( |
|
| 116 | - 'label' => esc_html__('Event Check-In', 'event_espresso'), |
|
| 117 | - 'order' => 10, |
|
| 118 | - 'persistent' => true, |
|
| 119 | - ), |
|
| 120 | - 'help_tabs' => array( |
|
| 121 | - 'registrations_event_checkin_help_tab' => array( |
|
| 122 | - 'title' => esc_html__('Registrations Event Check-In', 'event_espresso'), |
|
| 123 | - 'filename' => 'registrations_event_checkin', |
|
| 124 | - ), |
|
| 125 | - 'registrations_event_checkin_table_column_headings_help_tab' => array( |
|
| 126 | - 'title' => esc_html__('Event Check-In Table Column Headings', 'event_espresso'), |
|
| 127 | - 'filename' => 'registrations_event_checkin_table_column_headings', |
|
| 128 | - ), |
|
| 129 | - 'registrations_event_checkin_filters_help_tab' => array( |
|
| 130 | - 'title' => esc_html__('Event Check-In Filters', 'event_espresso'), |
|
| 131 | - 'filename' => 'registrations_event_checkin_filters', |
|
| 132 | - ), |
|
| 133 | - 'registrations_event_checkin_views_help_tab' => array( |
|
| 134 | - 'title' => esc_html__('Event Check-In Views', 'event_espresso'), |
|
| 135 | - 'filename' => 'registrations_event_checkin_views', |
|
| 136 | - ), |
|
| 137 | - 'registrations_event_checkin_other_help_tab' => array( |
|
| 138 | - 'title' => esc_html__('Event Check-In Other', 'event_espresso'), |
|
| 139 | - 'filename' => 'registrations_event_checkin_other', |
|
| 140 | - ), |
|
| 141 | - ), |
|
| 142 | - 'help_tour' => array('Event_Checkin_Help_Tour'), |
|
| 143 | - 'qtips' => array('Registration_List_Table_Tips'), |
|
| 144 | - 'list_table' => 'EE_Event_Registrations_List_Table', |
|
| 145 | - 'metaboxes' => array(), |
|
| 146 | - 'require_nonce' => false, |
|
| 147 | - ), |
|
| 148 | - 'registration_checkins' => array( |
|
| 149 | - 'nav' => array( |
|
| 150 | - 'label' => esc_html__('Check-In Records', 'event_espresso'), |
|
| 151 | - 'order' => 15, |
|
| 152 | - 'persistent' => false, |
|
| 153 | - 'url' => '', |
|
| 154 | - ), |
|
| 155 | - 'list_table' => 'EE_Registration_CheckIn_List_Table', |
|
| 156 | - // 'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ), |
|
| 157 | - 'metaboxes' => array(), |
|
| 158 | - 'require_nonce' => false, |
|
| 159 | - ), |
|
| 160 | - ); |
|
| 161 | - $this->_page_config = array_merge($this->_page_config, $new_page_config); |
|
| 162 | - $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table'; |
|
| 163 | - $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table'; |
|
| 164 | - } |
|
| 43 | + /** |
|
| 44 | + * Extending page configuration. |
|
| 45 | + */ |
|
| 46 | + protected function _extend_page_config() |
|
| 47 | + { |
|
| 48 | + $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations'; |
|
| 49 | + $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID']) |
|
| 50 | + ? $this->_req_data['_REG_ID'] |
|
| 51 | + : 0; |
|
| 52 | + $new_page_routes = array( |
|
| 53 | + 'reports' => array( |
|
| 54 | + 'func' => '_registration_reports', |
|
| 55 | + 'capability' => 'ee_read_registrations', |
|
| 56 | + ), |
|
| 57 | + 'registration_checkins' => array( |
|
| 58 | + 'func' => '_registration_checkin_list_table', |
|
| 59 | + 'capability' => 'ee_read_checkins', |
|
| 60 | + ), |
|
| 61 | + 'newsletter_selected_send' => array( |
|
| 62 | + 'func' => '_newsletter_selected_send', |
|
| 63 | + 'noheader' => true, |
|
| 64 | + 'capability' => 'ee_send_message', |
|
| 65 | + ), |
|
| 66 | + 'delete_checkin_rows' => array( |
|
| 67 | + 'func' => '_delete_checkin_rows', |
|
| 68 | + 'noheader' => true, |
|
| 69 | + 'capability' => 'ee_delete_checkins', |
|
| 70 | + ), |
|
| 71 | + 'delete_checkin_row' => array( |
|
| 72 | + 'func' => '_delete_checkin_row', |
|
| 73 | + 'noheader' => true, |
|
| 74 | + 'capability' => 'ee_delete_checkin', |
|
| 75 | + 'obj_id' => $reg_id, |
|
| 76 | + ), |
|
| 77 | + 'toggle_checkin_status' => array( |
|
| 78 | + 'func' => '_toggle_checkin_status', |
|
| 79 | + 'noheader' => true, |
|
| 80 | + 'capability' => 'ee_edit_checkin', |
|
| 81 | + 'obj_id' => $reg_id, |
|
| 82 | + ), |
|
| 83 | + 'toggle_checkin_status_bulk' => array( |
|
| 84 | + 'func' => '_toggle_checkin_status', |
|
| 85 | + 'noheader' => true, |
|
| 86 | + 'capability' => 'ee_edit_checkins', |
|
| 87 | + ), |
|
| 88 | + 'event_registrations' => array( |
|
| 89 | + 'func' => '_event_registrations_list_table', |
|
| 90 | + 'capability' => 'ee_read_checkins', |
|
| 91 | + ), |
|
| 92 | + 'registrations_checkin_report' => array( |
|
| 93 | + 'func' => '_registrations_checkin_report', |
|
| 94 | + 'noheader' => true, |
|
| 95 | + 'capability' => 'ee_read_registrations', |
|
| 96 | + ), |
|
| 97 | + ); |
|
| 98 | + $this->_page_routes = array_merge($this->_page_routes, $new_page_routes); |
|
| 99 | + $new_page_config = array( |
|
| 100 | + 'reports' => array( |
|
| 101 | + 'nav' => array( |
|
| 102 | + 'label' => esc_html__('Reports', 'event_espresso'), |
|
| 103 | + 'order' => 30, |
|
| 104 | + ), |
|
| 105 | + 'help_tabs' => array( |
|
| 106 | + 'registrations_reports_help_tab' => array( |
|
| 107 | + 'title' => esc_html__('Registration Reports', 'event_espresso'), |
|
| 108 | + 'filename' => 'registrations_reports', |
|
| 109 | + ), |
|
| 110 | + ), |
|
| 111 | + /*'help_tour' => array( 'Registration_Reports_Help_Tour' ),*/ |
|
| 112 | + 'require_nonce' => false, |
|
| 113 | + ), |
|
| 114 | + 'event_registrations' => array( |
|
| 115 | + 'nav' => array( |
|
| 116 | + 'label' => esc_html__('Event Check-In', 'event_espresso'), |
|
| 117 | + 'order' => 10, |
|
| 118 | + 'persistent' => true, |
|
| 119 | + ), |
|
| 120 | + 'help_tabs' => array( |
|
| 121 | + 'registrations_event_checkin_help_tab' => array( |
|
| 122 | + 'title' => esc_html__('Registrations Event Check-In', 'event_espresso'), |
|
| 123 | + 'filename' => 'registrations_event_checkin', |
|
| 124 | + ), |
|
| 125 | + 'registrations_event_checkin_table_column_headings_help_tab' => array( |
|
| 126 | + 'title' => esc_html__('Event Check-In Table Column Headings', 'event_espresso'), |
|
| 127 | + 'filename' => 'registrations_event_checkin_table_column_headings', |
|
| 128 | + ), |
|
| 129 | + 'registrations_event_checkin_filters_help_tab' => array( |
|
| 130 | + 'title' => esc_html__('Event Check-In Filters', 'event_espresso'), |
|
| 131 | + 'filename' => 'registrations_event_checkin_filters', |
|
| 132 | + ), |
|
| 133 | + 'registrations_event_checkin_views_help_tab' => array( |
|
| 134 | + 'title' => esc_html__('Event Check-In Views', 'event_espresso'), |
|
| 135 | + 'filename' => 'registrations_event_checkin_views', |
|
| 136 | + ), |
|
| 137 | + 'registrations_event_checkin_other_help_tab' => array( |
|
| 138 | + 'title' => esc_html__('Event Check-In Other', 'event_espresso'), |
|
| 139 | + 'filename' => 'registrations_event_checkin_other', |
|
| 140 | + ), |
|
| 141 | + ), |
|
| 142 | + 'help_tour' => array('Event_Checkin_Help_Tour'), |
|
| 143 | + 'qtips' => array('Registration_List_Table_Tips'), |
|
| 144 | + 'list_table' => 'EE_Event_Registrations_List_Table', |
|
| 145 | + 'metaboxes' => array(), |
|
| 146 | + 'require_nonce' => false, |
|
| 147 | + ), |
|
| 148 | + 'registration_checkins' => array( |
|
| 149 | + 'nav' => array( |
|
| 150 | + 'label' => esc_html__('Check-In Records', 'event_espresso'), |
|
| 151 | + 'order' => 15, |
|
| 152 | + 'persistent' => false, |
|
| 153 | + 'url' => '', |
|
| 154 | + ), |
|
| 155 | + 'list_table' => 'EE_Registration_CheckIn_List_Table', |
|
| 156 | + // 'help_tour' => array( 'Checkin_Toggle_View_Help_Tour' ), |
|
| 157 | + 'metaboxes' => array(), |
|
| 158 | + 'require_nonce' => false, |
|
| 159 | + ), |
|
| 160 | + ); |
|
| 161 | + $this->_page_config = array_merge($this->_page_config, $new_page_config); |
|
| 162 | + $this->_page_config['contact_list']['list_table'] = 'Extend_EE_Attendee_Contact_List_Table'; |
|
| 163 | + $this->_page_config['default']['list_table'] = 'Extend_EE_Registrations_List_Table'; |
|
| 164 | + } |
|
| 165 | 165 | |
| 166 | 166 | |
| 167 | - /** |
|
| 168 | - * Ajax hooks for all routes in this page. |
|
| 169 | - */ |
|
| 170 | - protected function _ajax_hooks() |
|
| 171 | - { |
|
| 172 | - parent::_ajax_hooks(); |
|
| 173 | - add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content')); |
|
| 174 | - } |
|
| 167 | + /** |
|
| 168 | + * Ajax hooks for all routes in this page. |
|
| 169 | + */ |
|
| 170 | + protected function _ajax_hooks() |
|
| 171 | + { |
|
| 172 | + parent::_ajax_hooks(); |
|
| 173 | + add_action('wp_ajax_get_newsletter_form_content', array($this, 'get_newsletter_form_content')); |
|
| 174 | + } |
|
| 175 | 175 | |
| 176 | 176 | |
| 177 | - /** |
|
| 178 | - * Global scripts for all routes in this page. |
|
| 179 | - */ |
|
| 180 | - public function load_scripts_styles() |
|
| 181 | - { |
|
| 182 | - parent::load_scripts_styles(); |
|
| 183 | - // if newsletter message type is active then let's add filter and load js for it. |
|
| 184 | - if (EEH_MSG_Template::is_mt_active('newsletter')) { |
|
| 185 | - // enqueue newsletter js |
|
| 186 | - wp_enqueue_script( |
|
| 187 | - 'ee-newsletter-trigger', |
|
| 188 | - REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js', |
|
| 189 | - array('ee-dialog'), |
|
| 190 | - EVENT_ESPRESSO_VERSION, |
|
| 191 | - true |
|
| 192 | - ); |
|
| 193 | - wp_enqueue_style( |
|
| 194 | - 'ee-newsletter-trigger-css', |
|
| 195 | - REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css', |
|
| 196 | - array(), |
|
| 197 | - EVENT_ESPRESSO_VERSION |
|
| 198 | - ); |
|
| 199 | - // hook in buttons for newsletter message type trigger. |
|
| 200 | - add_action( |
|
| 201 | - 'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', |
|
| 202 | - array($this, 'add_newsletter_action_buttons'), |
|
| 203 | - 10 |
|
| 204 | - ); |
|
| 205 | - } |
|
| 206 | - } |
|
| 177 | + /** |
|
| 178 | + * Global scripts for all routes in this page. |
|
| 179 | + */ |
|
| 180 | + public function load_scripts_styles() |
|
| 181 | + { |
|
| 182 | + parent::load_scripts_styles(); |
|
| 183 | + // if newsletter message type is active then let's add filter and load js for it. |
|
| 184 | + if (EEH_MSG_Template::is_mt_active('newsletter')) { |
|
| 185 | + // enqueue newsletter js |
|
| 186 | + wp_enqueue_script( |
|
| 187 | + 'ee-newsletter-trigger', |
|
| 188 | + REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js', |
|
| 189 | + array('ee-dialog'), |
|
| 190 | + EVENT_ESPRESSO_VERSION, |
|
| 191 | + true |
|
| 192 | + ); |
|
| 193 | + wp_enqueue_style( |
|
| 194 | + 'ee-newsletter-trigger-css', |
|
| 195 | + REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css', |
|
| 196 | + array(), |
|
| 197 | + EVENT_ESPRESSO_VERSION |
|
| 198 | + ); |
|
| 199 | + // hook in buttons for newsletter message type trigger. |
|
| 200 | + add_action( |
|
| 201 | + 'AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons', |
|
| 202 | + array($this, 'add_newsletter_action_buttons'), |
|
| 203 | + 10 |
|
| 204 | + ); |
|
| 205 | + } |
|
| 206 | + } |
|
| 207 | 207 | |
| 208 | 208 | |
| 209 | - /** |
|
| 210 | - * Scripts and styles for just the reports route. |
|
| 211 | - */ |
|
| 212 | - public function load_scripts_styles_reports() |
|
| 213 | - { |
|
| 214 | - wp_register_script( |
|
| 215 | - 'ee-reg-reports-js', |
|
| 216 | - REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js', |
|
| 217 | - array('google-charts'), |
|
| 218 | - EVENT_ESPRESSO_VERSION, |
|
| 219 | - true |
|
| 220 | - ); |
|
| 221 | - wp_enqueue_script('ee-reg-reports-js'); |
|
| 222 | - $this->_registration_reports_js_setup(); |
|
| 223 | - } |
|
| 209 | + /** |
|
| 210 | + * Scripts and styles for just the reports route. |
|
| 211 | + */ |
|
| 212 | + public function load_scripts_styles_reports() |
|
| 213 | + { |
|
| 214 | + wp_register_script( |
|
| 215 | + 'ee-reg-reports-js', |
|
| 216 | + REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js', |
|
| 217 | + array('google-charts'), |
|
| 218 | + EVENT_ESPRESSO_VERSION, |
|
| 219 | + true |
|
| 220 | + ); |
|
| 221 | + wp_enqueue_script('ee-reg-reports-js'); |
|
| 222 | + $this->_registration_reports_js_setup(); |
|
| 223 | + } |
|
| 224 | 224 | |
| 225 | 225 | |
| 226 | - /** |
|
| 227 | - * Register screen options for event_registrations route. |
|
| 228 | - */ |
|
| 229 | - protected function _add_screen_options_event_registrations() |
|
| 230 | - { |
|
| 231 | - $this->_per_page_screen_option(); |
|
| 232 | - } |
|
| 226 | + /** |
|
| 227 | + * Register screen options for event_registrations route. |
|
| 228 | + */ |
|
| 229 | + protected function _add_screen_options_event_registrations() |
|
| 230 | + { |
|
| 231 | + $this->_per_page_screen_option(); |
|
| 232 | + } |
|
| 233 | 233 | |
| 234 | 234 | |
| 235 | - /** |
|
| 236 | - * Register screen options for registration_checkins route |
|
| 237 | - */ |
|
| 238 | - protected function _add_screen_options_registration_checkins() |
|
| 239 | - { |
|
| 240 | - $page_title = $this->_admin_page_title; |
|
| 241 | - $this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso'); |
|
| 242 | - $this->_per_page_screen_option(); |
|
| 243 | - $this->_admin_page_title = $page_title; |
|
| 244 | - } |
|
| 235 | + /** |
|
| 236 | + * Register screen options for registration_checkins route |
|
| 237 | + */ |
|
| 238 | + protected function _add_screen_options_registration_checkins() |
|
| 239 | + { |
|
| 240 | + $page_title = $this->_admin_page_title; |
|
| 241 | + $this->_admin_page_title = esc_html__('Check-In Records', 'event_espresso'); |
|
| 242 | + $this->_per_page_screen_option(); |
|
| 243 | + $this->_admin_page_title = $page_title; |
|
| 244 | + } |
|
| 245 | 245 | |
| 246 | 246 | |
| 247 | - /** |
|
| 248 | - * Set views property for event_registrations route. |
|
| 249 | - */ |
|
| 250 | - protected function _set_list_table_views_event_registrations() |
|
| 251 | - { |
|
| 252 | - $this->_views = array( |
|
| 253 | - 'all' => array( |
|
| 254 | - 'slug' => 'all', |
|
| 255 | - 'label' => esc_html__('All', 'event_espresso'), |
|
| 256 | - 'count' => 0, |
|
| 257 | - 'bulk_action' => ! isset($this->_req_data['event_id']) |
|
| 258 | - ? array() |
|
| 259 | - : array( |
|
| 260 | - 'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'), |
|
| 261 | - ), |
|
| 262 | - ), |
|
| 263 | - ); |
|
| 264 | - } |
|
| 247 | + /** |
|
| 248 | + * Set views property for event_registrations route. |
|
| 249 | + */ |
|
| 250 | + protected function _set_list_table_views_event_registrations() |
|
| 251 | + { |
|
| 252 | + $this->_views = array( |
|
| 253 | + 'all' => array( |
|
| 254 | + 'slug' => 'all', |
|
| 255 | + 'label' => esc_html__('All', 'event_espresso'), |
|
| 256 | + 'count' => 0, |
|
| 257 | + 'bulk_action' => ! isset($this->_req_data['event_id']) |
|
| 258 | + ? array() |
|
| 259 | + : array( |
|
| 260 | + 'toggle_checkin_status_bulk' => esc_html__('Toggle Check-In', 'event_espresso'), |
|
| 261 | + ), |
|
| 262 | + ), |
|
| 263 | + ); |
|
| 264 | + } |
|
| 265 | 265 | |
| 266 | 266 | |
| 267 | - /** |
|
| 268 | - * Set views property for registration_checkins route. |
|
| 269 | - */ |
|
| 270 | - protected function _set_list_table_views_registration_checkins() |
|
| 271 | - { |
|
| 272 | - $this->_views = array( |
|
| 273 | - 'all' => array( |
|
| 274 | - 'slug' => 'all', |
|
| 275 | - 'label' => esc_html__('All', 'event_espresso'), |
|
| 276 | - 'count' => 0, |
|
| 277 | - 'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')), |
|
| 278 | - ), |
|
| 279 | - ); |
|
| 280 | - } |
|
| 267 | + /** |
|
| 268 | + * Set views property for registration_checkins route. |
|
| 269 | + */ |
|
| 270 | + protected function _set_list_table_views_registration_checkins() |
|
| 271 | + { |
|
| 272 | + $this->_views = array( |
|
| 273 | + 'all' => array( |
|
| 274 | + 'slug' => 'all', |
|
| 275 | + 'label' => esc_html__('All', 'event_espresso'), |
|
| 276 | + 'count' => 0, |
|
| 277 | + 'bulk_action' => array('delete_checkin_rows' => esc_html__('Delete Check-In Rows', 'event_espresso')), |
|
| 278 | + ), |
|
| 279 | + ); |
|
| 280 | + } |
|
| 281 | 281 | |
| 282 | 282 | |
| 283 | - /** |
|
| 284 | - * callback for ajax action. |
|
| 285 | - * |
|
| 286 | - * @since 4.3.0 |
|
| 287 | - * @return void (JSON) |
|
| 288 | - * @throws EE_Error |
|
| 289 | - * @throws InvalidArgumentException |
|
| 290 | - * @throws InvalidDataTypeException |
|
| 291 | - * @throws InvalidInterfaceException |
|
| 292 | - */ |
|
| 293 | - public function get_newsletter_form_content() |
|
| 294 | - { |
|
| 295 | - // do a nonce check cause we're not coming in from an normal route here. |
|
| 296 | - $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field( |
|
| 297 | - $this->_req_data['get_newsletter_form_content_nonce'] |
|
| 298 | - ) : ''; |
|
| 299 | - $nonce_ref = 'get_newsletter_form_content_nonce'; |
|
| 300 | - $this->_verify_nonce($nonce, $nonce_ref); |
|
| 301 | - // let's get the mtp for the incoming MTP_ ID |
|
| 302 | - if (! isset($this->_req_data['GRP_ID'])) { |
|
| 303 | - EE_Error::add_error( |
|
| 304 | - esc_html__( |
|
| 305 | - 'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).', |
|
| 306 | - 'event_espresso' |
|
| 307 | - ), |
|
| 308 | - __FILE__, |
|
| 309 | - __FUNCTION__, |
|
| 310 | - __LINE__ |
|
| 311 | - ); |
|
| 312 | - $this->_template_args['success'] = false; |
|
| 313 | - $this->_template_args['error'] = true; |
|
| 314 | - $this->_return_json(); |
|
| 315 | - } |
|
| 316 | - $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']); |
|
| 317 | - if (! $MTPG instanceof EE_Message_Template_Group) { |
|
| 318 | - EE_Error::add_error( |
|
| 319 | - sprintf( |
|
| 320 | - esc_html__( |
|
| 321 | - 'The GRP_ID given (%d) does not appear to have a corresponding row in the database.', |
|
| 322 | - 'event_espresso' |
|
| 323 | - ), |
|
| 324 | - $this->_req_data['GRP_ID'] |
|
| 325 | - ), |
|
| 326 | - __FILE__, |
|
| 327 | - __FUNCTION__, |
|
| 328 | - __LINE__ |
|
| 329 | - ); |
|
| 330 | - $this->_template_args['success'] = false; |
|
| 331 | - $this->_template_args['error'] = true; |
|
| 332 | - $this->_return_json(); |
|
| 333 | - } |
|
| 334 | - $MTPs = $MTPG->context_templates(); |
|
| 335 | - $MTPs = $MTPs['attendee']; |
|
| 336 | - $template_fields = array(); |
|
| 337 | - /** @var EE_Message_Template $MTP */ |
|
| 338 | - foreach ($MTPs as $MTP) { |
|
| 339 | - $field = $MTP->get('MTP_template_field'); |
|
| 340 | - if ($field === 'content') { |
|
| 341 | - $content = $MTP->get('MTP_content'); |
|
| 342 | - if (! empty($content['newsletter_content'])) { |
|
| 343 | - $template_fields['newsletter_content'] = $content['newsletter_content']; |
|
| 344 | - } |
|
| 345 | - continue; |
|
| 346 | - } |
|
| 347 | - $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content'); |
|
| 348 | - } |
|
| 349 | - $this->_template_args['success'] = true; |
|
| 350 | - $this->_template_args['error'] = false; |
|
| 351 | - $this->_template_args['data'] = array( |
|
| 352 | - 'batch_message_from' => isset($template_fields['from']) |
|
| 353 | - ? $template_fields['from'] |
|
| 354 | - : '', |
|
| 355 | - 'batch_message_subject' => isset($template_fields['subject']) |
|
| 356 | - ? $template_fields['subject'] |
|
| 357 | - : '', |
|
| 358 | - 'batch_message_content' => isset($template_fields['newsletter_content']) |
|
| 359 | - ? $template_fields['newsletter_content'] |
|
| 360 | - : '', |
|
| 361 | - ); |
|
| 362 | - $this->_return_json(); |
|
| 363 | - } |
|
| 283 | + /** |
|
| 284 | + * callback for ajax action. |
|
| 285 | + * |
|
| 286 | + * @since 4.3.0 |
|
| 287 | + * @return void (JSON) |
|
| 288 | + * @throws EE_Error |
|
| 289 | + * @throws InvalidArgumentException |
|
| 290 | + * @throws InvalidDataTypeException |
|
| 291 | + * @throws InvalidInterfaceException |
|
| 292 | + */ |
|
| 293 | + public function get_newsletter_form_content() |
|
| 294 | + { |
|
| 295 | + // do a nonce check cause we're not coming in from an normal route here. |
|
| 296 | + $nonce = isset($this->_req_data['get_newsletter_form_content_nonce']) ? sanitize_text_field( |
|
| 297 | + $this->_req_data['get_newsletter_form_content_nonce'] |
|
| 298 | + ) : ''; |
|
| 299 | + $nonce_ref = 'get_newsletter_form_content_nonce'; |
|
| 300 | + $this->_verify_nonce($nonce, $nonce_ref); |
|
| 301 | + // let's get the mtp for the incoming MTP_ ID |
|
| 302 | + if (! isset($this->_req_data['GRP_ID'])) { |
|
| 303 | + EE_Error::add_error( |
|
| 304 | + esc_html__( |
|
| 305 | + 'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).', |
|
| 306 | + 'event_espresso' |
|
| 307 | + ), |
|
| 308 | + __FILE__, |
|
| 309 | + __FUNCTION__, |
|
| 310 | + __LINE__ |
|
| 311 | + ); |
|
| 312 | + $this->_template_args['success'] = false; |
|
| 313 | + $this->_template_args['error'] = true; |
|
| 314 | + $this->_return_json(); |
|
| 315 | + } |
|
| 316 | + $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']); |
|
| 317 | + if (! $MTPG instanceof EE_Message_Template_Group) { |
|
| 318 | + EE_Error::add_error( |
|
| 319 | + sprintf( |
|
| 320 | + esc_html__( |
|
| 321 | + 'The GRP_ID given (%d) does not appear to have a corresponding row in the database.', |
|
| 322 | + 'event_espresso' |
|
| 323 | + ), |
|
| 324 | + $this->_req_data['GRP_ID'] |
|
| 325 | + ), |
|
| 326 | + __FILE__, |
|
| 327 | + __FUNCTION__, |
|
| 328 | + __LINE__ |
|
| 329 | + ); |
|
| 330 | + $this->_template_args['success'] = false; |
|
| 331 | + $this->_template_args['error'] = true; |
|
| 332 | + $this->_return_json(); |
|
| 333 | + } |
|
| 334 | + $MTPs = $MTPG->context_templates(); |
|
| 335 | + $MTPs = $MTPs['attendee']; |
|
| 336 | + $template_fields = array(); |
|
| 337 | + /** @var EE_Message_Template $MTP */ |
|
| 338 | + foreach ($MTPs as $MTP) { |
|
| 339 | + $field = $MTP->get('MTP_template_field'); |
|
| 340 | + if ($field === 'content') { |
|
| 341 | + $content = $MTP->get('MTP_content'); |
|
| 342 | + if (! empty($content['newsletter_content'])) { |
|
| 343 | + $template_fields['newsletter_content'] = $content['newsletter_content']; |
|
| 344 | + } |
|
| 345 | + continue; |
|
| 346 | + } |
|
| 347 | + $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content'); |
|
| 348 | + } |
|
| 349 | + $this->_template_args['success'] = true; |
|
| 350 | + $this->_template_args['error'] = false; |
|
| 351 | + $this->_template_args['data'] = array( |
|
| 352 | + 'batch_message_from' => isset($template_fields['from']) |
|
| 353 | + ? $template_fields['from'] |
|
| 354 | + : '', |
|
| 355 | + 'batch_message_subject' => isset($template_fields['subject']) |
|
| 356 | + ? $template_fields['subject'] |
|
| 357 | + : '', |
|
| 358 | + 'batch_message_content' => isset($template_fields['newsletter_content']) |
|
| 359 | + ? $template_fields['newsletter_content'] |
|
| 360 | + : '', |
|
| 361 | + ); |
|
| 362 | + $this->_return_json(); |
|
| 363 | + } |
|
| 364 | 364 | |
| 365 | 365 | |
| 366 | - /** |
|
| 367 | - * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action |
|
| 368 | - * |
|
| 369 | - * @since 4.3.0 |
|
| 370 | - * @param EE_Admin_List_Table $list_table |
|
| 371 | - * @return void |
|
| 372 | - * @throws InvalidArgumentException |
|
| 373 | - * @throws InvalidDataTypeException |
|
| 374 | - * @throws InvalidInterfaceException |
|
| 375 | - */ |
|
| 376 | - public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table) |
|
| 377 | - { |
|
| 378 | - if (! EE_Registry::instance()->CAP->current_user_can( |
|
| 379 | - 'ee_send_message', |
|
| 380 | - 'espresso_registrations_newsletter_selected_send' |
|
| 381 | - ) |
|
| 382 | - ) { |
|
| 383 | - return; |
|
| 384 | - } |
|
| 385 | - $routes_to_add_to = array( |
|
| 386 | - 'contact_list', |
|
| 387 | - 'event_registrations', |
|
| 388 | - 'default', |
|
| 389 | - ); |
|
| 390 | - if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) { |
|
| 391 | - if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id'])) |
|
| 392 | - || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash') |
|
| 393 | - ) { |
|
| 394 | - echo ''; |
|
| 395 | - } else { |
|
| 396 | - $button_text = sprintf( |
|
| 397 | - esc_html__('Send Batch Message (%s selected)', 'event_espresso'), |
|
| 398 | - '<span class="send-selected-newsletter-count">0</span>' |
|
| 399 | - ); |
|
| 400 | - echo '<button id="selected-batch-send-trigger" class="button secondary-button">' |
|
| 401 | - . '<span class="dashicons dashicons-email "></span>' |
|
| 402 | - . $button_text |
|
| 403 | - . '</button>'; |
|
| 404 | - add_action('admin_footer', array($this, 'newsletter_send_form_skeleton')); |
|
| 405 | - } |
|
| 406 | - } |
|
| 407 | - } |
|
| 366 | + /** |
|
| 367 | + * callback for AHEE__EE_Admin_List_Table__extra_tablenav__after_bottom_buttons action |
|
| 368 | + * |
|
| 369 | + * @since 4.3.0 |
|
| 370 | + * @param EE_Admin_List_Table $list_table |
|
| 371 | + * @return void |
|
| 372 | + * @throws InvalidArgumentException |
|
| 373 | + * @throws InvalidDataTypeException |
|
| 374 | + * @throws InvalidInterfaceException |
|
| 375 | + */ |
|
| 376 | + public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table) |
|
| 377 | + { |
|
| 378 | + if (! EE_Registry::instance()->CAP->current_user_can( |
|
| 379 | + 'ee_send_message', |
|
| 380 | + 'espresso_registrations_newsletter_selected_send' |
|
| 381 | + ) |
|
| 382 | + ) { |
|
| 383 | + return; |
|
| 384 | + } |
|
| 385 | + $routes_to_add_to = array( |
|
| 386 | + 'contact_list', |
|
| 387 | + 'event_registrations', |
|
| 388 | + 'default', |
|
| 389 | + ); |
|
| 390 | + if ($this->_current_page === 'espresso_registrations' && in_array($this->_req_action, $routes_to_add_to)) { |
|
| 391 | + if (($this->_req_action === 'event_registrations' && empty($this->_req_data['event_id'])) |
|
| 392 | + || (isset($this->_req_data['status']) && $this->_req_data['status'] === 'trash') |
|
| 393 | + ) { |
|
| 394 | + echo ''; |
|
| 395 | + } else { |
|
| 396 | + $button_text = sprintf( |
|
| 397 | + esc_html__('Send Batch Message (%s selected)', 'event_espresso'), |
|
| 398 | + '<span class="send-selected-newsletter-count">0</span>' |
|
| 399 | + ); |
|
| 400 | + echo '<button id="selected-batch-send-trigger" class="button secondary-button">' |
|
| 401 | + . '<span class="dashicons dashicons-email "></span>' |
|
| 402 | + . $button_text |
|
| 403 | + . '</button>'; |
|
| 404 | + add_action('admin_footer', array($this, 'newsletter_send_form_skeleton')); |
|
| 405 | + } |
|
| 406 | + } |
|
| 407 | + } |
|
| 408 | 408 | |
| 409 | 409 | |
| 410 | - /** |
|
| 411 | - * @throws DomainException |
|
| 412 | - * @throws EE_Error |
|
| 413 | - * @throws InvalidArgumentException |
|
| 414 | - * @throws InvalidDataTypeException |
|
| 415 | - * @throws InvalidInterfaceException |
|
| 416 | - */ |
|
| 417 | - public function newsletter_send_form_skeleton() |
|
| 418 | - { |
|
| 419 | - $list_table = $this->_list_table_object; |
|
| 420 | - $codes = array(); |
|
| 421 | - // need to templates for the newsletter message type for the template selector. |
|
| 422 | - $values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0); |
|
| 423 | - $mtps = EEM_Message_Template_Group::instance()->get_all( |
|
| 424 | - array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email')) |
|
| 425 | - ); |
|
| 426 | - foreach ($mtps as $mtp) { |
|
| 427 | - $name = $mtp->name(); |
|
| 428 | - $values[] = array( |
|
| 429 | - 'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name, |
|
| 430 | - 'id' => $mtp->ID(), |
|
| 431 | - ); |
|
| 432 | - } |
|
| 433 | - // need to get a list of shortcodes that are available for the newsletter message type. |
|
| 434 | - $shortcodes = EEH_MSG_Template::get_shortcodes( |
|
| 435 | - 'newsletter', |
|
| 436 | - 'email', |
|
| 437 | - array(), |
|
| 438 | - 'attendee', |
|
| 439 | - false |
|
| 440 | - ); |
|
| 441 | - foreach ($shortcodes as $field => $shortcode_array) { |
|
| 442 | - $available_shortcodes = array(); |
|
| 443 | - foreach ($shortcode_array as $shortcode => $shortcode_details) { |
|
| 444 | - $field_id = $field === '[NEWSLETTER_CONTENT]' |
|
| 445 | - ? 'content' |
|
| 446 | - : $field; |
|
| 447 | - $field_id = 'batch-message-' . strtolower($field_id); |
|
| 448 | - $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="' |
|
| 449 | - . $shortcode |
|
| 450 | - . '" data-linked-input-id="' . $field_id . '">' |
|
| 451 | - . $shortcode |
|
| 452 | - . '</span>'; |
|
| 453 | - } |
|
| 454 | - $codes[ $field ] = implode(', ', $available_shortcodes); |
|
| 455 | - } |
|
| 456 | - $shortcodes = $codes; |
|
| 457 | - $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php'; |
|
| 458 | - $form_template_args = array( |
|
| 459 | - 'form_action' => admin_url('admin.php?page=espresso_registrations'), |
|
| 460 | - 'form_route' => 'newsletter_selected_send', |
|
| 461 | - 'form_nonce_name' => 'newsletter_selected_send_nonce', |
|
| 462 | - 'form_nonce' => wp_create_nonce('newsletter_selected_send_nonce'), |
|
| 463 | - 'redirect_back_to' => $this->_req_action, |
|
| 464 | - 'ajax_nonce' => wp_create_nonce('get_newsletter_form_content_nonce'), |
|
| 465 | - 'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values), |
|
| 466 | - 'shortcodes' => $shortcodes, |
|
| 467 | - 'id_type' => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration', |
|
| 468 | - ); |
|
| 469 | - EEH_Template::display_template($form_template, $form_template_args); |
|
| 470 | - } |
|
| 410 | + /** |
|
| 411 | + * @throws DomainException |
|
| 412 | + * @throws EE_Error |
|
| 413 | + * @throws InvalidArgumentException |
|
| 414 | + * @throws InvalidDataTypeException |
|
| 415 | + * @throws InvalidInterfaceException |
|
| 416 | + */ |
|
| 417 | + public function newsletter_send_form_skeleton() |
|
| 418 | + { |
|
| 419 | + $list_table = $this->_list_table_object; |
|
| 420 | + $codes = array(); |
|
| 421 | + // need to templates for the newsletter message type for the template selector. |
|
| 422 | + $values[] = array('text' => esc_html__('Select Template to Use', 'event_espresso'), 'id' => 0); |
|
| 423 | + $mtps = EEM_Message_Template_Group::instance()->get_all( |
|
| 424 | + array(array('MTP_message_type' => 'newsletter', 'MTP_messenger' => 'email')) |
|
| 425 | + ); |
|
| 426 | + foreach ($mtps as $mtp) { |
|
| 427 | + $name = $mtp->name(); |
|
| 428 | + $values[] = array( |
|
| 429 | + 'text' => empty($name) ? esc_html__('Global', 'event_espresso') : $name, |
|
| 430 | + 'id' => $mtp->ID(), |
|
| 431 | + ); |
|
| 432 | + } |
|
| 433 | + // need to get a list of shortcodes that are available for the newsletter message type. |
|
| 434 | + $shortcodes = EEH_MSG_Template::get_shortcodes( |
|
| 435 | + 'newsletter', |
|
| 436 | + 'email', |
|
| 437 | + array(), |
|
| 438 | + 'attendee', |
|
| 439 | + false |
|
| 440 | + ); |
|
| 441 | + foreach ($shortcodes as $field => $shortcode_array) { |
|
| 442 | + $available_shortcodes = array(); |
|
| 443 | + foreach ($shortcode_array as $shortcode => $shortcode_details) { |
|
| 444 | + $field_id = $field === '[NEWSLETTER_CONTENT]' |
|
| 445 | + ? 'content' |
|
| 446 | + : $field; |
|
| 447 | + $field_id = 'batch-message-' . strtolower($field_id); |
|
| 448 | + $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="' |
|
| 449 | + . $shortcode |
|
| 450 | + . '" data-linked-input-id="' . $field_id . '">' |
|
| 451 | + . $shortcode |
|
| 452 | + . '</span>'; |
|
| 453 | + } |
|
| 454 | + $codes[ $field ] = implode(', ', $available_shortcodes); |
|
| 455 | + } |
|
| 456 | + $shortcodes = $codes; |
|
| 457 | + $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php'; |
|
| 458 | + $form_template_args = array( |
|
| 459 | + 'form_action' => admin_url('admin.php?page=espresso_registrations'), |
|
| 460 | + 'form_route' => 'newsletter_selected_send', |
|
| 461 | + 'form_nonce_name' => 'newsletter_selected_send_nonce', |
|
| 462 | + 'form_nonce' => wp_create_nonce('newsletter_selected_send_nonce'), |
|
| 463 | + 'redirect_back_to' => $this->_req_action, |
|
| 464 | + 'ajax_nonce' => wp_create_nonce('get_newsletter_form_content_nonce'), |
|
| 465 | + 'template_selector' => EEH_Form_Fields::select_input('newsletter_mtp_selected', $values), |
|
| 466 | + 'shortcodes' => $shortcodes, |
|
| 467 | + 'id_type' => $list_table instanceof EE_Attendee_Contact_List_Table ? 'contact' : 'registration', |
|
| 468 | + ); |
|
| 469 | + EEH_Template::display_template($form_template, $form_template_args); |
|
| 470 | + } |
|
| 471 | 471 | |
| 472 | 472 | |
| 473 | - /** |
|
| 474 | - * Handles sending selected registrations/contacts a newsletter. |
|
| 475 | - * |
|
| 476 | - * @since 4.3.0 |
|
| 477 | - * @return void |
|
| 478 | - * @throws EE_Error |
|
| 479 | - * @throws InvalidArgumentException |
|
| 480 | - * @throws InvalidDataTypeException |
|
| 481 | - * @throws InvalidInterfaceException |
|
| 482 | - */ |
|
| 483 | - protected function _newsletter_selected_send() |
|
| 484 | - { |
|
| 485 | - $success = true; |
|
| 486 | - // first we need to make sure we have a GRP_ID so we know what template we're sending and updating! |
|
| 487 | - if (empty($this->_req_data['newsletter_mtp_selected'])) { |
|
| 488 | - EE_Error::add_error( |
|
| 489 | - esc_html__( |
|
| 490 | - 'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.', |
|
| 491 | - 'event_espresso' |
|
| 492 | - ), |
|
| 493 | - __FILE__, |
|
| 494 | - __FUNCTION__, |
|
| 495 | - __LINE__ |
|
| 496 | - ); |
|
| 497 | - $success = false; |
|
| 498 | - } |
|
| 499 | - if ($success) { |
|
| 500 | - // update Message template in case there are any changes |
|
| 501 | - $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID( |
|
| 502 | - $this->_req_data['newsletter_mtp_selected'] |
|
| 503 | - ); |
|
| 504 | - $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group |
|
| 505 | - ? $Message_Template_Group->context_templates() |
|
| 506 | - : array(); |
|
| 507 | - if (empty($Message_Templates)) { |
|
| 508 | - EE_Error::add_error( |
|
| 509 | - esc_html__( |
|
| 510 | - 'Unable to retrieve message template fields from the db. Messages not sent.', |
|
| 511 | - 'event_espresso' |
|
| 512 | - ), |
|
| 513 | - __FILE__, |
|
| 514 | - __FUNCTION__, |
|
| 515 | - __LINE__ |
|
| 516 | - ); |
|
| 517 | - } |
|
| 518 | - // let's just update the specific fields |
|
| 519 | - foreach ($Message_Templates['attendee'] as $Message_Template) { |
|
| 520 | - if ($Message_Template instanceof EE_Message_Template) { |
|
| 521 | - $field = $Message_Template->get('MTP_template_field'); |
|
| 522 | - $content = $Message_Template->get('MTP_content'); |
|
| 523 | - $new_content = $content; |
|
| 524 | - switch ($field) { |
|
| 525 | - case 'from': |
|
| 526 | - $new_content = ! empty($this->_req_data['batch_message']['from']) |
|
| 527 | - ? $this->_req_data['batch_message']['from'] |
|
| 528 | - : $content; |
|
| 529 | - break; |
|
| 530 | - case 'subject': |
|
| 531 | - $new_content = ! empty($this->_req_data['batch_message']['subject']) |
|
| 532 | - ? $this->_req_data['batch_message']['subject'] |
|
| 533 | - : $content; |
|
| 534 | - break; |
|
| 535 | - case 'content': |
|
| 536 | - $new_content = $content; |
|
| 537 | - $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content']) |
|
| 538 | - ? $this->_req_data['batch_message']['content'] |
|
| 539 | - : $content['newsletter_content']; |
|
| 540 | - break; |
|
| 541 | - default: |
|
| 542 | - // continue the foreach loop, we don't want to set $new_content nor save. |
|
| 543 | - continue 2; |
|
| 544 | - } |
|
| 545 | - $Message_Template->set('MTP_content', $new_content); |
|
| 546 | - $Message_Template->save(); |
|
| 547 | - } |
|
| 548 | - } |
|
| 549 | - // great fields are updated! now let's make sure we just have contact objects (EE_Attendee). |
|
| 550 | - $id_type = ! empty($this->_req_data['batch_message']['id_type']) |
|
| 551 | - ? $this->_req_data['batch_message']['id_type'] |
|
| 552 | - : 'registration'; |
|
| 553 | - // id_type will affect how we assemble the ids. |
|
| 554 | - $ids = ! empty($this->_req_data['batch_message']['ids']) |
|
| 555 | - ? json_decode(stripslashes($this->_req_data['batch_message']['ids'])) |
|
| 556 | - : array(); |
|
| 557 | - $registrations_used_for_contact_data = array(); |
|
| 558 | - // using switch because eventually we'll have other contexts that will be used for generating messages. |
|
| 559 | - switch ($id_type) { |
|
| 560 | - case 'registration': |
|
| 561 | - $registrations_used_for_contact_data = EEM_Registration::instance()->get_all( |
|
| 562 | - array( |
|
| 563 | - array( |
|
| 564 | - 'REG_ID' => array('IN', $ids), |
|
| 565 | - ), |
|
| 566 | - ) |
|
| 567 | - ); |
|
| 568 | - break; |
|
| 569 | - case 'contact': |
|
| 570 | - $registrations_used_for_contact_data = EEM_Registration::instance() |
|
| 571 | - ->get_latest_registration_for_each_of_given_contacts( |
|
| 572 | - $ids |
|
| 573 | - ); |
|
| 574 | - break; |
|
| 575 | - } |
|
| 576 | - do_action_ref_array( |
|
| 577 | - 'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations', |
|
| 578 | - array( |
|
| 579 | - $registrations_used_for_contact_data, |
|
| 580 | - $Message_Template_Group->ID(), |
|
| 581 | - ) |
|
| 582 | - ); |
|
| 583 | - // kept for backward compat, internally we no longer use this action. |
|
| 584 | - // @deprecated 4.8.36.rc.002 |
|
| 585 | - $contacts = $id_type === 'registration' |
|
| 586 | - ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids) |
|
| 587 | - : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids)))); |
|
| 588 | - do_action_ref_array( |
|
| 589 | - 'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send', |
|
| 590 | - array( |
|
| 591 | - $contacts, |
|
| 592 | - $Message_Template_Group->ID(), |
|
| 593 | - ) |
|
| 594 | - ); |
|
| 595 | - } |
|
| 596 | - $query_args = array( |
|
| 597 | - 'action' => ! empty($this->_req_data['redirect_back_to']) |
|
| 598 | - ? $this->_req_data['redirect_back_to'] |
|
| 599 | - : 'default', |
|
| 600 | - ); |
|
| 601 | - $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 602 | - } |
|
| 473 | + /** |
|
| 474 | + * Handles sending selected registrations/contacts a newsletter. |
|
| 475 | + * |
|
| 476 | + * @since 4.3.0 |
|
| 477 | + * @return void |
|
| 478 | + * @throws EE_Error |
|
| 479 | + * @throws InvalidArgumentException |
|
| 480 | + * @throws InvalidDataTypeException |
|
| 481 | + * @throws InvalidInterfaceException |
|
| 482 | + */ |
|
| 483 | + protected function _newsletter_selected_send() |
|
| 484 | + { |
|
| 485 | + $success = true; |
|
| 486 | + // first we need to make sure we have a GRP_ID so we know what template we're sending and updating! |
|
| 487 | + if (empty($this->_req_data['newsletter_mtp_selected'])) { |
|
| 488 | + EE_Error::add_error( |
|
| 489 | + esc_html__( |
|
| 490 | + 'In order to send a message, a Message Template GRP_ID is needed. It was not provided so messages were not sent.', |
|
| 491 | + 'event_espresso' |
|
| 492 | + ), |
|
| 493 | + __FILE__, |
|
| 494 | + __FUNCTION__, |
|
| 495 | + __LINE__ |
|
| 496 | + ); |
|
| 497 | + $success = false; |
|
| 498 | + } |
|
| 499 | + if ($success) { |
|
| 500 | + // update Message template in case there are any changes |
|
| 501 | + $Message_Template_Group = EEM_Message_Template_Group::instance()->get_one_by_ID( |
|
| 502 | + $this->_req_data['newsletter_mtp_selected'] |
|
| 503 | + ); |
|
| 504 | + $Message_Templates = $Message_Template_Group instanceof EE_Message_Template_Group |
|
| 505 | + ? $Message_Template_Group->context_templates() |
|
| 506 | + : array(); |
|
| 507 | + if (empty($Message_Templates)) { |
|
| 508 | + EE_Error::add_error( |
|
| 509 | + esc_html__( |
|
| 510 | + 'Unable to retrieve message template fields from the db. Messages not sent.', |
|
| 511 | + 'event_espresso' |
|
| 512 | + ), |
|
| 513 | + __FILE__, |
|
| 514 | + __FUNCTION__, |
|
| 515 | + __LINE__ |
|
| 516 | + ); |
|
| 517 | + } |
|
| 518 | + // let's just update the specific fields |
|
| 519 | + foreach ($Message_Templates['attendee'] as $Message_Template) { |
|
| 520 | + if ($Message_Template instanceof EE_Message_Template) { |
|
| 521 | + $field = $Message_Template->get('MTP_template_field'); |
|
| 522 | + $content = $Message_Template->get('MTP_content'); |
|
| 523 | + $new_content = $content; |
|
| 524 | + switch ($field) { |
|
| 525 | + case 'from': |
|
| 526 | + $new_content = ! empty($this->_req_data['batch_message']['from']) |
|
| 527 | + ? $this->_req_data['batch_message']['from'] |
|
| 528 | + : $content; |
|
| 529 | + break; |
|
| 530 | + case 'subject': |
|
| 531 | + $new_content = ! empty($this->_req_data['batch_message']['subject']) |
|
| 532 | + ? $this->_req_data['batch_message']['subject'] |
|
| 533 | + : $content; |
|
| 534 | + break; |
|
| 535 | + case 'content': |
|
| 536 | + $new_content = $content; |
|
| 537 | + $new_content['newsletter_content'] = ! empty($this->_req_data['batch_message']['content']) |
|
| 538 | + ? $this->_req_data['batch_message']['content'] |
|
| 539 | + : $content['newsletter_content']; |
|
| 540 | + break; |
|
| 541 | + default: |
|
| 542 | + // continue the foreach loop, we don't want to set $new_content nor save. |
|
| 543 | + continue 2; |
|
| 544 | + } |
|
| 545 | + $Message_Template->set('MTP_content', $new_content); |
|
| 546 | + $Message_Template->save(); |
|
| 547 | + } |
|
| 548 | + } |
|
| 549 | + // great fields are updated! now let's make sure we just have contact objects (EE_Attendee). |
|
| 550 | + $id_type = ! empty($this->_req_data['batch_message']['id_type']) |
|
| 551 | + ? $this->_req_data['batch_message']['id_type'] |
|
| 552 | + : 'registration'; |
|
| 553 | + // id_type will affect how we assemble the ids. |
|
| 554 | + $ids = ! empty($this->_req_data['batch_message']['ids']) |
|
| 555 | + ? json_decode(stripslashes($this->_req_data['batch_message']['ids'])) |
|
| 556 | + : array(); |
|
| 557 | + $registrations_used_for_contact_data = array(); |
|
| 558 | + // using switch because eventually we'll have other contexts that will be used for generating messages. |
|
| 559 | + switch ($id_type) { |
|
| 560 | + case 'registration': |
|
| 561 | + $registrations_used_for_contact_data = EEM_Registration::instance()->get_all( |
|
| 562 | + array( |
|
| 563 | + array( |
|
| 564 | + 'REG_ID' => array('IN', $ids), |
|
| 565 | + ), |
|
| 566 | + ) |
|
| 567 | + ); |
|
| 568 | + break; |
|
| 569 | + case 'contact': |
|
| 570 | + $registrations_used_for_contact_data = EEM_Registration::instance() |
|
| 571 | + ->get_latest_registration_for_each_of_given_contacts( |
|
| 572 | + $ids |
|
| 573 | + ); |
|
| 574 | + break; |
|
| 575 | + } |
|
| 576 | + do_action_ref_array( |
|
| 577 | + 'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations', |
|
| 578 | + array( |
|
| 579 | + $registrations_used_for_contact_data, |
|
| 580 | + $Message_Template_Group->ID(), |
|
| 581 | + ) |
|
| 582 | + ); |
|
| 583 | + // kept for backward compat, internally we no longer use this action. |
|
| 584 | + // @deprecated 4.8.36.rc.002 |
|
| 585 | + $contacts = $id_type === 'registration' |
|
| 586 | + ? EEM_Attendee::instance()->get_array_of_contacts_from_reg_ids($ids) |
|
| 587 | + : EEM_Attendee::instance()->get_all(array(array('ATT_ID' => array('in', $ids)))); |
|
| 588 | + do_action_ref_array( |
|
| 589 | + 'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send', |
|
| 590 | + array( |
|
| 591 | + $contacts, |
|
| 592 | + $Message_Template_Group->ID(), |
|
| 593 | + ) |
|
| 594 | + ); |
|
| 595 | + } |
|
| 596 | + $query_args = array( |
|
| 597 | + 'action' => ! empty($this->_req_data['redirect_back_to']) |
|
| 598 | + ? $this->_req_data['redirect_back_to'] |
|
| 599 | + : 'default', |
|
| 600 | + ); |
|
| 601 | + $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 602 | + } |
|
| 603 | 603 | |
| 604 | 604 | |
| 605 | - /** |
|
| 606 | - * This is called when javascript is being enqueued to setup the various data needed for the reports js. |
|
| 607 | - * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method. |
|
| 608 | - */ |
|
| 609 | - protected function _registration_reports_js_setup() |
|
| 610 | - { |
|
| 611 | - $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report(); |
|
| 612 | - $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report(); |
|
| 613 | - } |
|
| 605 | + /** |
|
| 606 | + * This is called when javascript is being enqueued to setup the various data needed for the reports js. |
|
| 607 | + * Also $this->{$_reports_template_data} property is set for later usage by the _registration_reports method. |
|
| 608 | + */ |
|
| 609 | + protected function _registration_reports_js_setup() |
|
| 610 | + { |
|
| 611 | + $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_day_report(); |
|
| 612 | + $this->_reports_template_data['admin_reports'][] = $this->_registrations_per_event_report(); |
|
| 613 | + } |
|
| 614 | 614 | |
| 615 | 615 | |
| 616 | - /** |
|
| 617 | - * generates Business Reports regarding Registrations |
|
| 618 | - * |
|
| 619 | - * @access protected |
|
| 620 | - * @return void |
|
| 621 | - * @throws DomainException |
|
| 622 | - */ |
|
| 623 | - protected function _registration_reports() |
|
| 624 | - { |
|
| 625 | - $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php'; |
|
| 626 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
| 627 | - $template_path, |
|
| 628 | - $this->_reports_template_data, |
|
| 629 | - true |
|
| 630 | - ); |
|
| 631 | - // the final template wrapper |
|
| 632 | - $this->display_admin_page_with_no_sidebar(); |
|
| 633 | - } |
|
| 616 | + /** |
|
| 617 | + * generates Business Reports regarding Registrations |
|
| 618 | + * |
|
| 619 | + * @access protected |
|
| 620 | + * @return void |
|
| 621 | + * @throws DomainException |
|
| 622 | + */ |
|
| 623 | + protected function _registration_reports() |
|
| 624 | + { |
|
| 625 | + $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php'; |
|
| 626 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
| 627 | + $template_path, |
|
| 628 | + $this->_reports_template_data, |
|
| 629 | + true |
|
| 630 | + ); |
|
| 631 | + // the final template wrapper |
|
| 632 | + $this->display_admin_page_with_no_sidebar(); |
|
| 633 | + } |
|
| 634 | 634 | |
| 635 | 635 | |
| 636 | - /** |
|
| 637 | - * Generates Business Report showing total registrations per day. |
|
| 638 | - * |
|
| 639 | - * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated. |
|
| 640 | - * @return string |
|
| 641 | - * @throws EE_Error |
|
| 642 | - * @throws InvalidArgumentException |
|
| 643 | - * @throws InvalidDataTypeException |
|
| 644 | - * @throws InvalidInterfaceException |
|
| 645 | - */ |
|
| 646 | - private function _registrations_per_day_report($period = '-1 month') |
|
| 647 | - { |
|
| 648 | - $report_ID = 'reg-admin-registrations-per-day-report-dv'; |
|
| 649 | - $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period); |
|
| 650 | - $results = (array) $results; |
|
| 651 | - $regs = array(); |
|
| 652 | - $subtitle = ''; |
|
| 653 | - if ($results) { |
|
| 654 | - $column_titles = array(); |
|
| 655 | - $tracker = 0; |
|
| 656 | - foreach ($results as $result) { |
|
| 657 | - $report_column_values = array(); |
|
| 658 | - foreach ($result as $property_name => $property_value) { |
|
| 659 | - $property_value = $property_name === 'Registration_REG_date' ? $property_value |
|
| 660 | - : (int) $property_value; |
|
| 661 | - $report_column_values[] = $property_value; |
|
| 662 | - if ($tracker === 0) { |
|
| 663 | - if ($property_name === 'Registration_REG_date') { |
|
| 664 | - $column_titles[] = esc_html__( |
|
| 665 | - 'Date (only days with registrations are shown)', |
|
| 666 | - 'event_espresso' |
|
| 667 | - ); |
|
| 668 | - } else { |
|
| 669 | - $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence'); |
|
| 670 | - } |
|
| 671 | - } |
|
| 672 | - } |
|
| 673 | - $tracker++; |
|
| 674 | - $regs[] = $report_column_values; |
|
| 675 | - } |
|
| 676 | - // make sure the column_titles is pushed to the beginning of the array |
|
| 677 | - array_unshift($regs, $column_titles); |
|
| 678 | - // setup the date range. |
|
| 679 | - $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); |
|
| 680 | - $beginning_date = new DateTime("now " . $period, $DateTimeZone); |
|
| 681 | - $ending_date = new DateTime("now", $DateTimeZone); |
|
| 682 | - $subtitle = sprintf( |
|
| 683 | - _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'), |
|
| 684 | - $beginning_date->format('Y-m-d'), |
|
| 685 | - $ending_date->format('Y-m-d') |
|
| 686 | - ); |
|
| 687 | - } |
|
| 688 | - $report_title = esc_html__('Total Registrations per Day', 'event_espresso'); |
|
| 689 | - $report_params = array( |
|
| 690 | - 'title' => $report_title, |
|
| 691 | - 'subtitle' => $subtitle, |
|
| 692 | - 'id' => $report_ID, |
|
| 693 | - 'regs' => $regs, |
|
| 694 | - 'noResults' => empty($regs), |
|
| 695 | - 'noRegsMsg' => sprintf( |
|
| 696 | - esc_html__( |
|
| 697 | - '%sThere are currently no registration records in the last month for this report.%s', |
|
| 698 | - 'event_espresso' |
|
| 699 | - ), |
|
| 700 | - '<h2>' . $report_title . '</h2><p>', |
|
| 701 | - '</p>' |
|
| 702 | - ), |
|
| 703 | - ); |
|
| 704 | - wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params); |
|
| 705 | - return $report_ID; |
|
| 706 | - } |
|
| 636 | + /** |
|
| 637 | + * Generates Business Report showing total registrations per day. |
|
| 638 | + * |
|
| 639 | + * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated. |
|
| 640 | + * @return string |
|
| 641 | + * @throws EE_Error |
|
| 642 | + * @throws InvalidArgumentException |
|
| 643 | + * @throws InvalidDataTypeException |
|
| 644 | + * @throws InvalidInterfaceException |
|
| 645 | + */ |
|
| 646 | + private function _registrations_per_day_report($period = '-1 month') |
|
| 647 | + { |
|
| 648 | + $report_ID = 'reg-admin-registrations-per-day-report-dv'; |
|
| 649 | + $results = EEM_Registration::instance()->get_registrations_per_day_and_per_status_report($period); |
|
| 650 | + $results = (array) $results; |
|
| 651 | + $regs = array(); |
|
| 652 | + $subtitle = ''; |
|
| 653 | + if ($results) { |
|
| 654 | + $column_titles = array(); |
|
| 655 | + $tracker = 0; |
|
| 656 | + foreach ($results as $result) { |
|
| 657 | + $report_column_values = array(); |
|
| 658 | + foreach ($result as $property_name => $property_value) { |
|
| 659 | + $property_value = $property_name === 'Registration_REG_date' ? $property_value |
|
| 660 | + : (int) $property_value; |
|
| 661 | + $report_column_values[] = $property_value; |
|
| 662 | + if ($tracker === 0) { |
|
| 663 | + if ($property_name === 'Registration_REG_date') { |
|
| 664 | + $column_titles[] = esc_html__( |
|
| 665 | + 'Date (only days with registrations are shown)', |
|
| 666 | + 'event_espresso' |
|
| 667 | + ); |
|
| 668 | + } else { |
|
| 669 | + $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence'); |
|
| 670 | + } |
|
| 671 | + } |
|
| 672 | + } |
|
| 673 | + $tracker++; |
|
| 674 | + $regs[] = $report_column_values; |
|
| 675 | + } |
|
| 676 | + // make sure the column_titles is pushed to the beginning of the array |
|
| 677 | + array_unshift($regs, $column_titles); |
|
| 678 | + // setup the date range. |
|
| 679 | + $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); |
|
| 680 | + $beginning_date = new DateTime("now " . $period, $DateTimeZone); |
|
| 681 | + $ending_date = new DateTime("now", $DateTimeZone); |
|
| 682 | + $subtitle = sprintf( |
|
| 683 | + _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'), |
|
| 684 | + $beginning_date->format('Y-m-d'), |
|
| 685 | + $ending_date->format('Y-m-d') |
|
| 686 | + ); |
|
| 687 | + } |
|
| 688 | + $report_title = esc_html__('Total Registrations per Day', 'event_espresso'); |
|
| 689 | + $report_params = array( |
|
| 690 | + 'title' => $report_title, |
|
| 691 | + 'subtitle' => $subtitle, |
|
| 692 | + 'id' => $report_ID, |
|
| 693 | + 'regs' => $regs, |
|
| 694 | + 'noResults' => empty($regs), |
|
| 695 | + 'noRegsMsg' => sprintf( |
|
| 696 | + esc_html__( |
|
| 697 | + '%sThere are currently no registration records in the last month for this report.%s', |
|
| 698 | + 'event_espresso' |
|
| 699 | + ), |
|
| 700 | + '<h2>' . $report_title . '</h2><p>', |
|
| 701 | + '</p>' |
|
| 702 | + ), |
|
| 703 | + ); |
|
| 704 | + wp_localize_script('ee-reg-reports-js', 'regPerDay', $report_params); |
|
| 705 | + return $report_ID; |
|
| 706 | + } |
|
| 707 | 707 | |
| 708 | 708 | |
| 709 | - /** |
|
| 710 | - * Generates Business Report showing total registrations per event. |
|
| 711 | - * |
|
| 712 | - * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated. |
|
| 713 | - * @return string |
|
| 714 | - * @throws EE_Error |
|
| 715 | - * @throws InvalidArgumentException |
|
| 716 | - * @throws InvalidDataTypeException |
|
| 717 | - * @throws InvalidInterfaceException |
|
| 718 | - */ |
|
| 719 | - private function _registrations_per_event_report($period = '-1 month') |
|
| 720 | - { |
|
| 721 | - $report_ID = 'reg-admin-registrations-per-event-report-dv'; |
|
| 722 | - $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period); |
|
| 723 | - $results = (array) $results; |
|
| 724 | - $regs = array(); |
|
| 725 | - $subtitle = ''; |
|
| 726 | - if ($results) { |
|
| 727 | - $column_titles = array(); |
|
| 728 | - $tracker = 0; |
|
| 729 | - foreach ($results as $result) { |
|
| 730 | - $report_column_values = array(); |
|
| 731 | - foreach ($result as $property_name => $property_value) { |
|
| 732 | - $property_value = $property_name === 'Registration_Event' ? wp_trim_words( |
|
| 733 | - $property_value, |
|
| 734 | - 4, |
|
| 735 | - '...' |
|
| 736 | - ) : (int) $property_value; |
|
| 737 | - $report_column_values[] = $property_value; |
|
| 738 | - if ($tracker === 0) { |
|
| 739 | - if ($property_name === 'Registration_Event') { |
|
| 740 | - $column_titles[] = esc_html__('Event', 'event_espresso'); |
|
| 741 | - } else { |
|
| 742 | - $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence'); |
|
| 743 | - } |
|
| 744 | - } |
|
| 745 | - } |
|
| 746 | - $tracker++; |
|
| 747 | - $regs[] = $report_column_values; |
|
| 748 | - } |
|
| 749 | - // make sure the column_titles is pushed to the beginning of the array |
|
| 750 | - array_unshift($regs, $column_titles); |
|
| 751 | - // setup the date range. |
|
| 752 | - $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); |
|
| 753 | - $beginning_date = new DateTime("now " . $period, $DateTimeZone); |
|
| 754 | - $ending_date = new DateTime("now", $DateTimeZone); |
|
| 755 | - $subtitle = sprintf( |
|
| 756 | - _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'), |
|
| 757 | - $beginning_date->format('Y-m-d'), |
|
| 758 | - $ending_date->format('Y-m-d') |
|
| 759 | - ); |
|
| 760 | - } |
|
| 761 | - $report_title = esc_html__('Total Registrations per Event', 'event_espresso'); |
|
| 762 | - $report_params = array( |
|
| 763 | - 'title' => $report_title, |
|
| 764 | - 'subtitle' => $subtitle, |
|
| 765 | - 'id' => $report_ID, |
|
| 766 | - 'regs' => $regs, |
|
| 767 | - 'noResults' => empty($regs), |
|
| 768 | - 'noRegsMsg' => sprintf( |
|
| 769 | - esc_html__( |
|
| 770 | - '%sThere are currently no registration records in the last month for this report.%s', |
|
| 771 | - 'event_espresso' |
|
| 772 | - ), |
|
| 773 | - '<h2>' . $report_title . '</h2><p>', |
|
| 774 | - '</p>' |
|
| 775 | - ), |
|
| 776 | - ); |
|
| 777 | - wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params); |
|
| 778 | - return $report_ID; |
|
| 779 | - } |
|
| 709 | + /** |
|
| 710 | + * Generates Business Report showing total registrations per event. |
|
| 711 | + * |
|
| 712 | + * @param string $period The period (acceptable by PHP Datetime constructor) for which the report is generated. |
|
| 713 | + * @return string |
|
| 714 | + * @throws EE_Error |
|
| 715 | + * @throws InvalidArgumentException |
|
| 716 | + * @throws InvalidDataTypeException |
|
| 717 | + * @throws InvalidInterfaceException |
|
| 718 | + */ |
|
| 719 | + private function _registrations_per_event_report($period = '-1 month') |
|
| 720 | + { |
|
| 721 | + $report_ID = 'reg-admin-registrations-per-event-report-dv'; |
|
| 722 | + $results = EEM_Registration::instance()->get_registrations_per_event_and_per_status_report($period); |
|
| 723 | + $results = (array) $results; |
|
| 724 | + $regs = array(); |
|
| 725 | + $subtitle = ''; |
|
| 726 | + if ($results) { |
|
| 727 | + $column_titles = array(); |
|
| 728 | + $tracker = 0; |
|
| 729 | + foreach ($results as $result) { |
|
| 730 | + $report_column_values = array(); |
|
| 731 | + foreach ($result as $property_name => $property_value) { |
|
| 732 | + $property_value = $property_name === 'Registration_Event' ? wp_trim_words( |
|
| 733 | + $property_value, |
|
| 734 | + 4, |
|
| 735 | + '...' |
|
| 736 | + ) : (int) $property_value; |
|
| 737 | + $report_column_values[] = $property_value; |
|
| 738 | + if ($tracker === 0) { |
|
| 739 | + if ($property_name === 'Registration_Event') { |
|
| 740 | + $column_titles[] = esc_html__('Event', 'event_espresso'); |
|
| 741 | + } else { |
|
| 742 | + $column_titles[] = EEH_Template::pretty_status($property_name, false, 'sentence'); |
|
| 743 | + } |
|
| 744 | + } |
|
| 745 | + } |
|
| 746 | + $tracker++; |
|
| 747 | + $regs[] = $report_column_values; |
|
| 748 | + } |
|
| 749 | + // make sure the column_titles is pushed to the beginning of the array |
|
| 750 | + array_unshift($regs, $column_titles); |
|
| 751 | + // setup the date range. |
|
| 752 | + $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); |
|
| 753 | + $beginning_date = new DateTime("now " . $period, $DateTimeZone); |
|
| 754 | + $ending_date = new DateTime("now", $DateTimeZone); |
|
| 755 | + $subtitle = sprintf( |
|
| 756 | + _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'), |
|
| 757 | + $beginning_date->format('Y-m-d'), |
|
| 758 | + $ending_date->format('Y-m-d') |
|
| 759 | + ); |
|
| 760 | + } |
|
| 761 | + $report_title = esc_html__('Total Registrations per Event', 'event_espresso'); |
|
| 762 | + $report_params = array( |
|
| 763 | + 'title' => $report_title, |
|
| 764 | + 'subtitle' => $subtitle, |
|
| 765 | + 'id' => $report_ID, |
|
| 766 | + 'regs' => $regs, |
|
| 767 | + 'noResults' => empty($regs), |
|
| 768 | + 'noRegsMsg' => sprintf( |
|
| 769 | + esc_html__( |
|
| 770 | + '%sThere are currently no registration records in the last month for this report.%s', |
|
| 771 | + 'event_espresso' |
|
| 772 | + ), |
|
| 773 | + '<h2>' . $report_title . '</h2><p>', |
|
| 774 | + '</p>' |
|
| 775 | + ), |
|
| 776 | + ); |
|
| 777 | + wp_localize_script('ee-reg-reports-js', 'regPerEvent', $report_params); |
|
| 778 | + return $report_ID; |
|
| 779 | + } |
|
| 780 | 780 | |
| 781 | 781 | |
| 782 | - /** |
|
| 783 | - * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration) |
|
| 784 | - * |
|
| 785 | - * @access protected |
|
| 786 | - * @return void |
|
| 787 | - * @throws EE_Error |
|
| 788 | - * @throws InvalidArgumentException |
|
| 789 | - * @throws InvalidDataTypeException |
|
| 790 | - * @throws InvalidInterfaceException |
|
| 791 | - * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 792 | - */ |
|
| 793 | - protected function _registration_checkin_list_table() |
|
| 794 | - { |
|
| 795 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 796 | - $reg_id = isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : null; |
|
| 797 | - /** @var EE_Registration $registration */ |
|
| 798 | - $registration = EEM_Registration::instance()->get_one_by_ID($reg_id); |
|
| 799 | - $attendee = $registration->attendee(); |
|
| 800 | - $this->_admin_page_title .= $this->get_action_link_or_button( |
|
| 801 | - 'new_registration', |
|
| 802 | - 'add-registrant', |
|
| 803 | - array('event_id' => $registration->event_ID()), |
|
| 804 | - 'add-new-h2' |
|
| 805 | - ); |
|
| 806 | - $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in); |
|
| 807 | - $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out); |
|
| 808 | - $legend_items = array( |
|
| 809 | - 'checkin' => array( |
|
| 810 | - 'class' => $checked_in->cssClasses(), |
|
| 811 | - 'desc' => $checked_in->legendLabel(), |
|
| 812 | - ), |
|
| 813 | - 'checkout' => array( |
|
| 814 | - 'class' => $checked_out->cssClasses(), |
|
| 815 | - 'desc' => $checked_out->legendLabel(), |
|
| 816 | - ), |
|
| 817 | - ); |
|
| 818 | - $this->_template_args['after_list_table'] = $this->_display_legend($legend_items); |
|
| 819 | - $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null; |
|
| 820 | - /** @var EE_Datetime $datetime */ |
|
| 821 | - $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id); |
|
| 822 | - $datetime_label = ''; |
|
| 823 | - if ($datetime instanceof EE_Datetime) { |
|
| 824 | - $datetime_label = $datetime->get_dtt_display_name(true); |
|
| 825 | - $datetime_label .= ! empty($datetime_label) |
|
| 826 | - ? ' (' . $datetime->get_dtt_display_name() . ')' |
|
| 827 | - : $datetime->get_dtt_display_name(); |
|
| 828 | - } |
|
| 829 | - $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration |
|
| 830 | - ? EE_Admin_Page::add_query_args_and_nonce( |
|
| 831 | - array( |
|
| 832 | - 'action' => 'event_registrations', |
|
| 833 | - 'event_id' => $registration->event_ID(), |
|
| 834 | - 'DTT_ID' => $dtt_id, |
|
| 835 | - ), |
|
| 836 | - $this->_admin_base_url |
|
| 837 | - ) |
|
| 838 | - : ''; |
|
| 839 | - $datetime_link = ! empty($datetime_link) |
|
| 840 | - ? '<a href="' . $datetime_link . '">' |
|
| 841 | - . '<span id="checkin-dtt">' |
|
| 842 | - . $datetime_label |
|
| 843 | - . '</span></a>' |
|
| 844 | - : $datetime_label; |
|
| 845 | - $attendee_name = $attendee instanceof EE_Attendee |
|
| 846 | - ? $attendee->full_name() |
|
| 847 | - : ''; |
|
| 848 | - $attendee_link = $attendee instanceof EE_Attendee |
|
| 849 | - ? $attendee->get_admin_details_link() |
|
| 850 | - : ''; |
|
| 851 | - $attendee_link = ! empty($attendee_link) |
|
| 852 | - ? '<a href="' . $attendee->get_admin_details_link() . '"' |
|
| 853 | - . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">' |
|
| 854 | - . '<span id="checkin-attendee-name">' |
|
| 855 | - . $attendee_name |
|
| 856 | - . '</span></a>' |
|
| 857 | - : ''; |
|
| 858 | - $event_link = $registration->event() instanceof EE_Event |
|
| 859 | - ? $registration->event()->get_admin_details_link() |
|
| 860 | - : ''; |
|
| 861 | - $event_link = ! empty($event_link) |
|
| 862 | - ? '<a href="' . $event_link . '"' |
|
| 863 | - . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">' |
|
| 864 | - . '<span id="checkin-event-name">' |
|
| 865 | - . $registration->event_name() |
|
| 866 | - . '</span>' |
|
| 867 | - . '</a>' |
|
| 868 | - : ''; |
|
| 869 | - $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id) |
|
| 870 | - ? '<h2>' . sprintf( |
|
| 871 | - esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'), |
|
| 872 | - $attendee_link, |
|
| 873 | - $datetime_link, |
|
| 874 | - $event_link |
|
| 875 | - ) . '</h2>' |
|
| 876 | - : ''; |
|
| 877 | - $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id) |
|
| 878 | - ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : ''; |
|
| 879 | - $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id) |
|
| 880 | - ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : ''; |
|
| 881 | - $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 882 | - } |
|
| 782 | + /** |
|
| 783 | + * generates HTML for the Registration Check-in list table (showing all Check-ins for a specific registration) |
|
| 784 | + * |
|
| 785 | + * @access protected |
|
| 786 | + * @return void |
|
| 787 | + * @throws EE_Error |
|
| 788 | + * @throws InvalidArgumentException |
|
| 789 | + * @throws InvalidDataTypeException |
|
| 790 | + * @throws InvalidInterfaceException |
|
| 791 | + * @throws \EventEspresso\core\exceptions\EntityNotFoundException |
|
| 792 | + */ |
|
| 793 | + protected function _registration_checkin_list_table() |
|
| 794 | + { |
|
| 795 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 796 | + $reg_id = isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : null; |
|
| 797 | + /** @var EE_Registration $registration */ |
|
| 798 | + $registration = EEM_Registration::instance()->get_one_by_ID($reg_id); |
|
| 799 | + $attendee = $registration->attendee(); |
|
| 800 | + $this->_admin_page_title .= $this->get_action_link_or_button( |
|
| 801 | + 'new_registration', |
|
| 802 | + 'add-registrant', |
|
| 803 | + array('event_id' => $registration->event_ID()), |
|
| 804 | + 'add-new-h2' |
|
| 805 | + ); |
|
| 806 | + $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in); |
|
| 807 | + $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out); |
|
| 808 | + $legend_items = array( |
|
| 809 | + 'checkin' => array( |
|
| 810 | + 'class' => $checked_in->cssClasses(), |
|
| 811 | + 'desc' => $checked_in->legendLabel(), |
|
| 812 | + ), |
|
| 813 | + 'checkout' => array( |
|
| 814 | + 'class' => $checked_out->cssClasses(), |
|
| 815 | + 'desc' => $checked_out->legendLabel(), |
|
| 816 | + ), |
|
| 817 | + ); |
|
| 818 | + $this->_template_args['after_list_table'] = $this->_display_legend($legend_items); |
|
| 819 | + $dtt_id = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null; |
|
| 820 | + /** @var EE_Datetime $datetime */ |
|
| 821 | + $datetime = EEM_Datetime::instance()->get_one_by_ID($dtt_id); |
|
| 822 | + $datetime_label = ''; |
|
| 823 | + if ($datetime instanceof EE_Datetime) { |
|
| 824 | + $datetime_label = $datetime->get_dtt_display_name(true); |
|
| 825 | + $datetime_label .= ! empty($datetime_label) |
|
| 826 | + ? ' (' . $datetime->get_dtt_display_name() . ')' |
|
| 827 | + : $datetime->get_dtt_display_name(); |
|
| 828 | + } |
|
| 829 | + $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration |
|
| 830 | + ? EE_Admin_Page::add_query_args_and_nonce( |
|
| 831 | + array( |
|
| 832 | + 'action' => 'event_registrations', |
|
| 833 | + 'event_id' => $registration->event_ID(), |
|
| 834 | + 'DTT_ID' => $dtt_id, |
|
| 835 | + ), |
|
| 836 | + $this->_admin_base_url |
|
| 837 | + ) |
|
| 838 | + : ''; |
|
| 839 | + $datetime_link = ! empty($datetime_link) |
|
| 840 | + ? '<a href="' . $datetime_link . '">' |
|
| 841 | + . '<span id="checkin-dtt">' |
|
| 842 | + . $datetime_label |
|
| 843 | + . '</span></a>' |
|
| 844 | + : $datetime_label; |
|
| 845 | + $attendee_name = $attendee instanceof EE_Attendee |
|
| 846 | + ? $attendee->full_name() |
|
| 847 | + : ''; |
|
| 848 | + $attendee_link = $attendee instanceof EE_Attendee |
|
| 849 | + ? $attendee->get_admin_details_link() |
|
| 850 | + : ''; |
|
| 851 | + $attendee_link = ! empty($attendee_link) |
|
| 852 | + ? '<a href="' . $attendee->get_admin_details_link() . '"' |
|
| 853 | + . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">' |
|
| 854 | + . '<span id="checkin-attendee-name">' |
|
| 855 | + . $attendee_name |
|
| 856 | + . '</span></a>' |
|
| 857 | + : ''; |
|
| 858 | + $event_link = $registration->event() instanceof EE_Event |
|
| 859 | + ? $registration->event()->get_admin_details_link() |
|
| 860 | + : ''; |
|
| 861 | + $event_link = ! empty($event_link) |
|
| 862 | + ? '<a href="' . $event_link . '"' |
|
| 863 | + . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">' |
|
| 864 | + . '<span id="checkin-event-name">' |
|
| 865 | + . $registration->event_name() |
|
| 866 | + . '</span>' |
|
| 867 | + . '</a>' |
|
| 868 | + : ''; |
|
| 869 | + $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id) |
|
| 870 | + ? '<h2>' . sprintf( |
|
| 871 | + esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'), |
|
| 872 | + $attendee_link, |
|
| 873 | + $datetime_link, |
|
| 874 | + $event_link |
|
| 875 | + ) . '</h2>' |
|
| 876 | + : ''; |
|
| 877 | + $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id) |
|
| 878 | + ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : ''; |
|
| 879 | + $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id) |
|
| 880 | + ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : ''; |
|
| 881 | + $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 882 | + } |
|
| 883 | 883 | |
| 884 | 884 | |
| 885 | - /** |
|
| 886 | - * toggle the Check-in status for the given registration (coming from ajax) |
|
| 887 | - * |
|
| 888 | - * @return void (JSON) |
|
| 889 | - * @throws EE_Error |
|
| 890 | - * @throws InvalidArgumentException |
|
| 891 | - * @throws InvalidDataTypeException |
|
| 892 | - * @throws InvalidInterfaceException |
|
| 893 | - */ |
|
| 894 | - public function toggle_checkin_status() |
|
| 895 | - { |
|
| 896 | - // first make sure we have the necessary data |
|
| 897 | - if (! isset($this->_req_data['_regid'])) { |
|
| 898 | - EE_Error::add_error( |
|
| 899 | - esc_html__( |
|
| 900 | - 'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax', |
|
| 901 | - 'event_espresso' |
|
| 902 | - ), |
|
| 903 | - __FILE__, |
|
| 904 | - __FUNCTION__, |
|
| 905 | - __LINE__ |
|
| 906 | - ); |
|
| 907 | - $this->_template_args['success'] = false; |
|
| 908 | - $this->_template_args['error'] = true; |
|
| 909 | - $this->_return_json(); |
|
| 910 | - }; |
|
| 911 | - // do a nonce check cause we're not coming in from an normal route here. |
|
| 912 | - $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce']) |
|
| 913 | - : ''; |
|
| 914 | - $nonce_ref = 'checkin_nonce'; |
|
| 915 | - $this->_verify_nonce($nonce, $nonce_ref); |
|
| 916 | - // beautiful! Made it this far so let's get the status. |
|
| 917 | - $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status()); |
|
| 918 | - // setup new class to return via ajax |
|
| 919 | - $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses(); |
|
| 920 | - $this->_template_args['success'] = true; |
|
| 921 | - $this->_return_json(); |
|
| 922 | - } |
|
| 885 | + /** |
|
| 886 | + * toggle the Check-in status for the given registration (coming from ajax) |
|
| 887 | + * |
|
| 888 | + * @return void (JSON) |
|
| 889 | + * @throws EE_Error |
|
| 890 | + * @throws InvalidArgumentException |
|
| 891 | + * @throws InvalidDataTypeException |
|
| 892 | + * @throws InvalidInterfaceException |
|
| 893 | + */ |
|
| 894 | + public function toggle_checkin_status() |
|
| 895 | + { |
|
| 896 | + // first make sure we have the necessary data |
|
| 897 | + if (! isset($this->_req_data['_regid'])) { |
|
| 898 | + EE_Error::add_error( |
|
| 899 | + esc_html__( |
|
| 900 | + 'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax', |
|
| 901 | + 'event_espresso' |
|
| 902 | + ), |
|
| 903 | + __FILE__, |
|
| 904 | + __FUNCTION__, |
|
| 905 | + __LINE__ |
|
| 906 | + ); |
|
| 907 | + $this->_template_args['success'] = false; |
|
| 908 | + $this->_template_args['error'] = true; |
|
| 909 | + $this->_return_json(); |
|
| 910 | + }; |
|
| 911 | + // do a nonce check cause we're not coming in from an normal route here. |
|
| 912 | + $nonce = isset($this->_req_data['checkinnonce']) ? sanitize_text_field($this->_req_data['checkinnonce']) |
|
| 913 | + : ''; |
|
| 914 | + $nonce_ref = 'checkin_nonce'; |
|
| 915 | + $this->_verify_nonce($nonce, $nonce_ref); |
|
| 916 | + // beautiful! Made it this far so let's get the status. |
|
| 917 | + $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status()); |
|
| 918 | + // setup new class to return via ajax |
|
| 919 | + $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses(); |
|
| 920 | + $this->_template_args['success'] = true; |
|
| 921 | + $this->_return_json(); |
|
| 922 | + } |
|
| 923 | 923 | |
| 924 | 924 | |
| 925 | - /** |
|
| 926 | - * handles toggling the checkin status for the registration, |
|
| 927 | - * |
|
| 928 | - * @access protected |
|
| 929 | - * @return int|void |
|
| 930 | - * @throws EE_Error |
|
| 931 | - * @throws InvalidArgumentException |
|
| 932 | - * @throws InvalidDataTypeException |
|
| 933 | - * @throws InvalidInterfaceException |
|
| 934 | - */ |
|
| 935 | - protected function _toggle_checkin_status() |
|
| 936 | - { |
|
| 937 | - // first let's get the query args out of the way for the redirect |
|
| 938 | - $query_args = array( |
|
| 939 | - 'action' => 'event_registrations', |
|
| 940 | - 'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null, |
|
| 941 | - 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null, |
|
| 942 | - ); |
|
| 943 | - $new_status = false; |
|
| 944 | - // bulk action check in toggle |
|
| 945 | - if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 946 | - // cycle thru checkboxes |
|
| 947 | - while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 948 | - $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null; |
|
| 949 | - $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID); |
|
| 950 | - } |
|
| 951 | - } elseif (isset($this->_req_data['_regid'])) { |
|
| 952 | - // coming from ajax request |
|
| 953 | - $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null; |
|
| 954 | - $query_args['DTT_ID'] = $DTT_ID; |
|
| 955 | - $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID); |
|
| 956 | - } else { |
|
| 957 | - EE_Error::add_error( |
|
| 958 | - esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'), |
|
| 959 | - __FILE__, |
|
| 960 | - __FUNCTION__, |
|
| 961 | - __LINE__ |
|
| 962 | - ); |
|
| 963 | - } |
|
| 964 | - if (defined('DOING_AJAX')) { |
|
| 965 | - return $new_status; |
|
| 966 | - } |
|
| 967 | - $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 968 | - } |
|
| 925 | + /** |
|
| 926 | + * handles toggling the checkin status for the registration, |
|
| 927 | + * |
|
| 928 | + * @access protected |
|
| 929 | + * @return int|void |
|
| 930 | + * @throws EE_Error |
|
| 931 | + * @throws InvalidArgumentException |
|
| 932 | + * @throws InvalidDataTypeException |
|
| 933 | + * @throws InvalidInterfaceException |
|
| 934 | + */ |
|
| 935 | + protected function _toggle_checkin_status() |
|
| 936 | + { |
|
| 937 | + // first let's get the query args out of the way for the redirect |
|
| 938 | + $query_args = array( |
|
| 939 | + 'action' => 'event_registrations', |
|
| 940 | + 'event_id' => isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null, |
|
| 941 | + 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null, |
|
| 942 | + ); |
|
| 943 | + $new_status = false; |
|
| 944 | + // bulk action check in toggle |
|
| 945 | + if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 946 | + // cycle thru checkboxes |
|
| 947 | + while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 948 | + $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null; |
|
| 949 | + $new_status = $this->_toggle_checkin($REG_ID, $DTT_ID); |
|
| 950 | + } |
|
| 951 | + } elseif (isset($this->_req_data['_regid'])) { |
|
| 952 | + // coming from ajax request |
|
| 953 | + $DTT_ID = isset($this->_req_data['dttid']) ? $this->_req_data['dttid'] : null; |
|
| 954 | + $query_args['DTT_ID'] = $DTT_ID; |
|
| 955 | + $new_status = $this->_toggle_checkin($this->_req_data['_regid'], $DTT_ID); |
|
| 956 | + } else { |
|
| 957 | + EE_Error::add_error( |
|
| 958 | + esc_html__('Missing some required data to toggle the Check-in', 'event_espresso'), |
|
| 959 | + __FILE__, |
|
| 960 | + __FUNCTION__, |
|
| 961 | + __LINE__ |
|
| 962 | + ); |
|
| 963 | + } |
|
| 964 | + if (defined('DOING_AJAX')) { |
|
| 965 | + return $new_status; |
|
| 966 | + } |
|
| 967 | + $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 968 | + } |
|
| 969 | 969 | |
| 970 | 970 | |
| 971 | - /** |
|
| 972 | - * This is toggles a single Check-in for the given registration and datetime. |
|
| 973 | - * |
|
| 974 | - * @param int $REG_ID The registration we're toggling |
|
| 975 | - * @param int $DTT_ID The datetime we're toggling |
|
| 976 | - * @return int The new status toggled to. |
|
| 977 | - * @throws EE_Error |
|
| 978 | - * @throws InvalidArgumentException |
|
| 979 | - * @throws InvalidDataTypeException |
|
| 980 | - * @throws InvalidInterfaceException |
|
| 981 | - */ |
|
| 982 | - private function _toggle_checkin($REG_ID, $DTT_ID) |
|
| 983 | - { |
|
| 984 | - /** @var EE_Registration $REG */ |
|
| 985 | - $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID); |
|
| 986 | - $new_status = $REG->toggle_checkin_status($DTT_ID); |
|
| 987 | - if ($new_status !== false) { |
|
| 988 | - EE_Error::add_success($REG->get_checkin_msg($DTT_ID)); |
|
| 989 | - } else { |
|
| 990 | - EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__); |
|
| 991 | - $new_status = false; |
|
| 992 | - } |
|
| 993 | - return $new_status; |
|
| 994 | - } |
|
| 971 | + /** |
|
| 972 | + * This is toggles a single Check-in for the given registration and datetime. |
|
| 973 | + * |
|
| 974 | + * @param int $REG_ID The registration we're toggling |
|
| 975 | + * @param int $DTT_ID The datetime we're toggling |
|
| 976 | + * @return int The new status toggled to. |
|
| 977 | + * @throws EE_Error |
|
| 978 | + * @throws InvalidArgumentException |
|
| 979 | + * @throws InvalidDataTypeException |
|
| 980 | + * @throws InvalidInterfaceException |
|
| 981 | + */ |
|
| 982 | + private function _toggle_checkin($REG_ID, $DTT_ID) |
|
| 983 | + { |
|
| 984 | + /** @var EE_Registration $REG */ |
|
| 985 | + $REG = EEM_Registration::instance()->get_one_by_ID($REG_ID); |
|
| 986 | + $new_status = $REG->toggle_checkin_status($DTT_ID); |
|
| 987 | + if ($new_status !== false) { |
|
| 988 | + EE_Error::add_success($REG->get_checkin_msg($DTT_ID)); |
|
| 989 | + } else { |
|
| 990 | + EE_Error::add_error($REG->get_checkin_msg($DTT_ID, true), __FILE__, __FUNCTION__, __LINE__); |
|
| 991 | + $new_status = false; |
|
| 992 | + } |
|
| 993 | + return $new_status; |
|
| 994 | + } |
|
| 995 | 995 | |
| 996 | 996 | |
| 997 | - /** |
|
| 998 | - * Takes care of deleting multiple EE_Checkin table rows |
|
| 999 | - * |
|
| 1000 | - * @access protected |
|
| 1001 | - * @return void |
|
| 1002 | - * @throws EE_Error |
|
| 1003 | - * @throws InvalidArgumentException |
|
| 1004 | - * @throws InvalidDataTypeException |
|
| 1005 | - * @throws InvalidInterfaceException |
|
| 1006 | - */ |
|
| 1007 | - protected function _delete_checkin_rows() |
|
| 1008 | - { |
|
| 1009 | - $query_args = array( |
|
| 1010 | - 'action' => 'registration_checkins', |
|
| 1011 | - 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0, |
|
| 1012 | - '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0, |
|
| 1013 | - ); |
|
| 1014 | - $errors = 0; |
|
| 1015 | - if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 1016 | - while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 1017 | - if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) { |
|
| 1018 | - $errors++; |
|
| 1019 | - } |
|
| 1020 | - } |
|
| 1021 | - } else { |
|
| 1022 | - EE_Error::add_error( |
|
| 1023 | - esc_html__( |
|
| 1024 | - 'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!', |
|
| 1025 | - 'event_espresso' |
|
| 1026 | - ), |
|
| 1027 | - __FILE__, |
|
| 1028 | - __FUNCTION__, |
|
| 1029 | - __LINE__ |
|
| 1030 | - ); |
|
| 1031 | - $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 1032 | - } |
|
| 1033 | - if ($errors > 0) { |
|
| 1034 | - EE_Error::add_error( |
|
| 1035 | - sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors), |
|
| 1036 | - __FILE__, |
|
| 1037 | - __FUNCTION__, |
|
| 1038 | - __LINE__ |
|
| 1039 | - ); |
|
| 1040 | - } else { |
|
| 1041 | - EE_Error::add_success(__('Records were successfully deleted', 'event_espresso')); |
|
| 1042 | - } |
|
| 1043 | - $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 1044 | - } |
|
| 997 | + /** |
|
| 998 | + * Takes care of deleting multiple EE_Checkin table rows |
|
| 999 | + * |
|
| 1000 | + * @access protected |
|
| 1001 | + * @return void |
|
| 1002 | + * @throws EE_Error |
|
| 1003 | + * @throws InvalidArgumentException |
|
| 1004 | + * @throws InvalidDataTypeException |
|
| 1005 | + * @throws InvalidInterfaceException |
|
| 1006 | + */ |
|
| 1007 | + protected function _delete_checkin_rows() |
|
| 1008 | + { |
|
| 1009 | + $query_args = array( |
|
| 1010 | + 'action' => 'registration_checkins', |
|
| 1011 | + 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0, |
|
| 1012 | + '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0, |
|
| 1013 | + ); |
|
| 1014 | + $errors = 0; |
|
| 1015 | + if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 1016 | + while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 1017 | + if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) { |
|
| 1018 | + $errors++; |
|
| 1019 | + } |
|
| 1020 | + } |
|
| 1021 | + } else { |
|
| 1022 | + EE_Error::add_error( |
|
| 1023 | + esc_html__( |
|
| 1024 | + 'So, something went wrong with the bulk delete because there was no data received for instructions on WHAT to delete!', |
|
| 1025 | + 'event_espresso' |
|
| 1026 | + ), |
|
| 1027 | + __FILE__, |
|
| 1028 | + __FUNCTION__, |
|
| 1029 | + __LINE__ |
|
| 1030 | + ); |
|
| 1031 | + $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 1032 | + } |
|
| 1033 | + if ($errors > 0) { |
|
| 1034 | + EE_Error::add_error( |
|
| 1035 | + sprintf(__('There were %d records that did not delete successfully', 'event_espresso'), $errors), |
|
| 1036 | + __FILE__, |
|
| 1037 | + __FUNCTION__, |
|
| 1038 | + __LINE__ |
|
| 1039 | + ); |
|
| 1040 | + } else { |
|
| 1041 | + EE_Error::add_success(__('Records were successfully deleted', 'event_espresso')); |
|
| 1042 | + } |
|
| 1043 | + $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 1044 | + } |
|
| 1045 | 1045 | |
| 1046 | 1046 | |
| 1047 | - /** |
|
| 1048 | - * Deletes a single EE_Checkin row |
|
| 1049 | - * |
|
| 1050 | - * @return void |
|
| 1051 | - * @throws EE_Error |
|
| 1052 | - * @throws InvalidArgumentException |
|
| 1053 | - * @throws InvalidDataTypeException |
|
| 1054 | - * @throws InvalidInterfaceException |
|
| 1055 | - */ |
|
| 1056 | - protected function _delete_checkin_row() |
|
| 1057 | - { |
|
| 1058 | - $query_args = array( |
|
| 1059 | - 'action' => 'registration_checkins', |
|
| 1060 | - 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0, |
|
| 1061 | - '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0, |
|
| 1062 | - ); |
|
| 1063 | - if (! empty($this->_req_data['CHK_ID'])) { |
|
| 1064 | - if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) { |
|
| 1065 | - EE_Error::add_error( |
|
| 1066 | - esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'), |
|
| 1067 | - __FILE__, |
|
| 1068 | - __FUNCTION__, |
|
| 1069 | - __LINE__ |
|
| 1070 | - ); |
|
| 1071 | - } else { |
|
| 1072 | - EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso')); |
|
| 1073 | - } |
|
| 1074 | - } else { |
|
| 1075 | - EE_Error::add_error( |
|
| 1076 | - esc_html__( |
|
| 1077 | - 'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code', |
|
| 1078 | - 'event_espresso' |
|
| 1079 | - ), |
|
| 1080 | - __FILE__, |
|
| 1081 | - __FUNCTION__, |
|
| 1082 | - __LINE__ |
|
| 1083 | - ); |
|
| 1084 | - } |
|
| 1085 | - $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 1086 | - } |
|
| 1047 | + /** |
|
| 1048 | + * Deletes a single EE_Checkin row |
|
| 1049 | + * |
|
| 1050 | + * @return void |
|
| 1051 | + * @throws EE_Error |
|
| 1052 | + * @throws InvalidArgumentException |
|
| 1053 | + * @throws InvalidDataTypeException |
|
| 1054 | + * @throws InvalidInterfaceException |
|
| 1055 | + */ |
|
| 1056 | + protected function _delete_checkin_row() |
|
| 1057 | + { |
|
| 1058 | + $query_args = array( |
|
| 1059 | + 'action' => 'registration_checkins', |
|
| 1060 | + 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0, |
|
| 1061 | + '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0, |
|
| 1062 | + ); |
|
| 1063 | + if (! empty($this->_req_data['CHK_ID'])) { |
|
| 1064 | + if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) { |
|
| 1065 | + EE_Error::add_error( |
|
| 1066 | + esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'), |
|
| 1067 | + __FILE__, |
|
| 1068 | + __FUNCTION__, |
|
| 1069 | + __LINE__ |
|
| 1070 | + ); |
|
| 1071 | + } else { |
|
| 1072 | + EE_Error::add_success(__('Check-In record successfully deleted', 'event_espresso')); |
|
| 1073 | + } |
|
| 1074 | + } else { |
|
| 1075 | + EE_Error::add_error( |
|
| 1076 | + esc_html__( |
|
| 1077 | + 'In order to delete a Check-in record, there must be a Check-In ID available. There is not. It is not your fault, there is just a gremlin living in the code', |
|
| 1078 | + 'event_espresso' |
|
| 1079 | + ), |
|
| 1080 | + __FILE__, |
|
| 1081 | + __FUNCTION__, |
|
| 1082 | + __LINE__ |
|
| 1083 | + ); |
|
| 1084 | + } |
|
| 1085 | + $this->_redirect_after_action(false, '', '', $query_args, true); |
|
| 1086 | + } |
|
| 1087 | 1087 | |
| 1088 | 1088 | |
| 1089 | - /** |
|
| 1090 | - * generates HTML for the Event Registrations List Table |
|
| 1091 | - * |
|
| 1092 | - * @access protected |
|
| 1093 | - * @return void |
|
| 1094 | - * @throws EE_Error |
|
| 1095 | - * @throws InvalidArgumentException |
|
| 1096 | - * @throws InvalidDataTypeException |
|
| 1097 | - * @throws InvalidInterfaceException |
|
| 1098 | - */ |
|
| 1099 | - protected function _event_registrations_list_table() |
|
| 1100 | - { |
|
| 1101 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 1102 | - $this->_admin_page_title .= isset($this->_req_data['event_id']) |
|
| 1103 | - ? $this->get_action_link_or_button( |
|
| 1104 | - 'new_registration', |
|
| 1105 | - 'add-registrant', |
|
| 1106 | - array('event_id' => $this->_req_data['event_id']), |
|
| 1107 | - 'add-new-h2', |
|
| 1108 | - '', |
|
| 1109 | - false |
|
| 1110 | - ) |
|
| 1111 | - : ''; |
|
| 1112 | - $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in); |
|
| 1113 | - $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out); |
|
| 1114 | - $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never); |
|
| 1115 | - $legend_items = array( |
|
| 1116 | - 'star-icon' => array( |
|
| 1117 | - 'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8', |
|
| 1118 | - 'desc' => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'), |
|
| 1119 | - ), |
|
| 1120 | - 'checkin' => array( |
|
| 1121 | - 'class' => $checked_in->cssClasses(), |
|
| 1122 | - 'desc' => $checked_in->legendLabel(), |
|
| 1123 | - ), |
|
| 1124 | - 'checkout' => array( |
|
| 1125 | - 'class' => $checked_out->cssClasses(), |
|
| 1126 | - 'desc' => $checked_out->legendLabel(), |
|
| 1127 | - ), |
|
| 1128 | - 'nocheckinrecord' => array( |
|
| 1129 | - 'class' => $checked_never->cssClasses(), |
|
| 1130 | - 'desc' => $checked_never->legendLabel(), |
|
| 1131 | - ), |
|
| 1132 | - 'approved_status' => array( |
|
| 1133 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved, |
|
| 1134 | - 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'), |
|
| 1135 | - ), |
|
| 1136 | - 'cancelled_status' => array( |
|
| 1137 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled, |
|
| 1138 | - 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'), |
|
| 1139 | - ), |
|
| 1140 | - 'declined_status' => array( |
|
| 1141 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined, |
|
| 1142 | - 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'), |
|
| 1143 | - ), |
|
| 1144 | - 'not_approved' => array( |
|
| 1145 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved, |
|
| 1146 | - 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'), |
|
| 1147 | - ), |
|
| 1148 | - 'pending_status' => array( |
|
| 1149 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment, |
|
| 1150 | - 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'), |
|
| 1151 | - ), |
|
| 1152 | - 'wait_list' => array( |
|
| 1153 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list, |
|
| 1154 | - 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'), |
|
| 1155 | - ), |
|
| 1156 | - ); |
|
| 1157 | - $this->_template_args['after_list_table'] = $this->_display_legend($legend_items); |
|
| 1158 | - $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null; |
|
| 1159 | - /** @var EE_Event $event */ |
|
| 1160 | - $event = EEM_Event::instance()->get_one_by_ID($event_id); |
|
| 1161 | - $this->_template_args['before_list_table'] = $event instanceof EE_Event |
|
| 1162 | - ? '<h2>' . sprintf( |
|
| 1163 | - esc_html__('Viewing Registrations for Event: %s', 'event_espresso'), |
|
| 1164 | - EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name') |
|
| 1165 | - ) . '</h2>' |
|
| 1166 | - : ''; |
|
| 1167 | - // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on |
|
| 1168 | - // the event. |
|
| 1169 | - $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0; |
|
| 1170 | - $datetime = null; |
|
| 1171 | - if ($event instanceof EE_Event) { |
|
| 1172 | - $datetimes_on_event = $event->datetimes(); |
|
| 1173 | - if (count($datetimes_on_event) === 1) { |
|
| 1174 | - $datetime = reset($datetimes_on_event); |
|
| 1175 | - } |
|
| 1176 | - } |
|
| 1177 | - $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID); |
|
| 1178 | - if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') { |
|
| 1179 | - $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5); |
|
| 1180 | - $this->_template_args['before_list_table'] .= ' <span class="drk-grey-text">'; |
|
| 1181 | - $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>'; |
|
| 1182 | - $this->_template_args['before_list_table'] .= $datetime->name(); |
|
| 1183 | - $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )'; |
|
| 1184 | - $this->_template_args['before_list_table'] .= '</span></h2>'; |
|
| 1185 | - } |
|
| 1186 | - // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status |
|
| 1187 | - // column represents |
|
| 1188 | - if (! $datetime instanceof EE_Datetime) { |
|
| 1189 | - $this->_template_args['before_list_table'] .= '<br><p class="description">' |
|
| 1190 | - . esc_html__( |
|
| 1191 | - 'In this view, the check-in status represents the latest check-in record for the registration in that row.', |
|
| 1192 | - 'event_espresso' |
|
| 1193 | - ) |
|
| 1194 | - . '</p>'; |
|
| 1195 | - } |
|
| 1196 | - $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 1197 | - } |
|
| 1089 | + /** |
|
| 1090 | + * generates HTML for the Event Registrations List Table |
|
| 1091 | + * |
|
| 1092 | + * @access protected |
|
| 1093 | + * @return void |
|
| 1094 | + * @throws EE_Error |
|
| 1095 | + * @throws InvalidArgumentException |
|
| 1096 | + * @throws InvalidDataTypeException |
|
| 1097 | + * @throws InvalidInterfaceException |
|
| 1098 | + */ |
|
| 1099 | + protected function _event_registrations_list_table() |
|
| 1100 | + { |
|
| 1101 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 1102 | + $this->_admin_page_title .= isset($this->_req_data['event_id']) |
|
| 1103 | + ? $this->get_action_link_or_button( |
|
| 1104 | + 'new_registration', |
|
| 1105 | + 'add-registrant', |
|
| 1106 | + array('event_id' => $this->_req_data['event_id']), |
|
| 1107 | + 'add-new-h2', |
|
| 1108 | + '', |
|
| 1109 | + false |
|
| 1110 | + ) |
|
| 1111 | + : ''; |
|
| 1112 | + $checked_in = new CheckinStatusDashicon(EE_Checkin::status_checked_in); |
|
| 1113 | + $checked_out = new CheckinStatusDashicon(EE_Checkin::status_checked_out); |
|
| 1114 | + $checked_never = new CheckinStatusDashicon(EE_Checkin::status_checked_never); |
|
| 1115 | + $legend_items = array( |
|
| 1116 | + 'star-icon' => array( |
|
| 1117 | + 'class' => 'dashicons dashicons-star-filled lt-blue-icon ee-icon-size-8', |
|
| 1118 | + 'desc' => esc_html__('This Registrant is the Primary Registrant', 'event_espresso'), |
|
| 1119 | + ), |
|
| 1120 | + 'checkin' => array( |
|
| 1121 | + 'class' => $checked_in->cssClasses(), |
|
| 1122 | + 'desc' => $checked_in->legendLabel(), |
|
| 1123 | + ), |
|
| 1124 | + 'checkout' => array( |
|
| 1125 | + 'class' => $checked_out->cssClasses(), |
|
| 1126 | + 'desc' => $checked_out->legendLabel(), |
|
| 1127 | + ), |
|
| 1128 | + 'nocheckinrecord' => array( |
|
| 1129 | + 'class' => $checked_never->cssClasses(), |
|
| 1130 | + 'desc' => $checked_never->legendLabel(), |
|
| 1131 | + ), |
|
| 1132 | + 'approved_status' => array( |
|
| 1133 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved, |
|
| 1134 | + 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'), |
|
| 1135 | + ), |
|
| 1136 | + 'cancelled_status' => array( |
|
| 1137 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled, |
|
| 1138 | + 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'), |
|
| 1139 | + ), |
|
| 1140 | + 'declined_status' => array( |
|
| 1141 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined, |
|
| 1142 | + 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'), |
|
| 1143 | + ), |
|
| 1144 | + 'not_approved' => array( |
|
| 1145 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved, |
|
| 1146 | + 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'), |
|
| 1147 | + ), |
|
| 1148 | + 'pending_status' => array( |
|
| 1149 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment, |
|
| 1150 | + 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'), |
|
| 1151 | + ), |
|
| 1152 | + 'wait_list' => array( |
|
| 1153 | + 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list, |
|
| 1154 | + 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'), |
|
| 1155 | + ), |
|
| 1156 | + ); |
|
| 1157 | + $this->_template_args['after_list_table'] = $this->_display_legend($legend_items); |
|
| 1158 | + $event_id = isset($this->_req_data['event_id']) ? $this->_req_data['event_id'] : null; |
|
| 1159 | + /** @var EE_Event $event */ |
|
| 1160 | + $event = EEM_Event::instance()->get_one_by_ID($event_id); |
|
| 1161 | + $this->_template_args['before_list_table'] = $event instanceof EE_Event |
|
| 1162 | + ? '<h2>' . sprintf( |
|
| 1163 | + esc_html__('Viewing Registrations for Event: %s', 'event_espresso'), |
|
| 1164 | + EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name') |
|
| 1165 | + ) . '</h2>' |
|
| 1166 | + : ''; |
|
| 1167 | + // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on |
|
| 1168 | + // the event. |
|
| 1169 | + $DTT_ID = ! empty($this->_req_data['DTT_ID']) ? absint($this->_req_data['DTT_ID']) : 0; |
|
| 1170 | + $datetime = null; |
|
| 1171 | + if ($event instanceof EE_Event) { |
|
| 1172 | + $datetimes_on_event = $event->datetimes(); |
|
| 1173 | + if (count($datetimes_on_event) === 1) { |
|
| 1174 | + $datetime = reset($datetimes_on_event); |
|
| 1175 | + } |
|
| 1176 | + } |
|
| 1177 | + $datetime = $datetime instanceof EE_Datetime ? $datetime : EEM_Datetime::instance()->get_one_by_ID($DTT_ID); |
|
| 1178 | + if ($datetime instanceof EE_Datetime && $this->_template_args['before_list_table'] !== '') { |
|
| 1179 | + $this->_template_args['before_list_table'] = substr($this->_template_args['before_list_table'], 0, -5); |
|
| 1180 | + $this->_template_args['before_list_table'] .= ' <span class="drk-grey-text">'; |
|
| 1181 | + $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>'; |
|
| 1182 | + $this->_template_args['before_list_table'] .= $datetime->name(); |
|
| 1183 | + $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )'; |
|
| 1184 | + $this->_template_args['before_list_table'] .= '</span></h2>'; |
|
| 1185 | + } |
|
| 1186 | + // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status |
|
| 1187 | + // column represents |
|
| 1188 | + if (! $datetime instanceof EE_Datetime) { |
|
| 1189 | + $this->_template_args['before_list_table'] .= '<br><p class="description">' |
|
| 1190 | + . esc_html__( |
|
| 1191 | + 'In this view, the check-in status represents the latest check-in record for the registration in that row.', |
|
| 1192 | + 'event_espresso' |
|
| 1193 | + ) |
|
| 1194 | + . '</p>'; |
|
| 1195 | + } |
|
| 1196 | + $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 1197 | + } |
|
| 1198 | 1198 | |
| 1199 | - /** |
|
| 1200 | - * Download the registrations check-in report (same as the normal registration report, but with different where |
|
| 1201 | - * conditions) |
|
| 1202 | - * |
|
| 1203 | - * @return void ends the request by a redirect or download |
|
| 1204 | - */ |
|
| 1205 | - public function _registrations_checkin_report() |
|
| 1206 | - { |
|
| 1207 | - $this->_registrations_report_base('_get_checkin_query_params_from_request'); |
|
| 1208 | - } |
|
| 1199 | + /** |
|
| 1200 | + * Download the registrations check-in report (same as the normal registration report, but with different where |
|
| 1201 | + * conditions) |
|
| 1202 | + * |
|
| 1203 | + * @return void ends the request by a redirect or download |
|
| 1204 | + */ |
|
| 1205 | + public function _registrations_checkin_report() |
|
| 1206 | + { |
|
| 1207 | + $this->_registrations_report_base('_get_checkin_query_params_from_request'); |
|
| 1208 | + } |
|
| 1209 | 1209 | |
| 1210 | - /** |
|
| 1211 | - * Gets the query params from the request, plus adds a where condition for the registration status, |
|
| 1212 | - * because on the checkin page we only ever want to see approved and pending-approval registrations |
|
| 1213 | - * |
|
| 1214 | - * @param array $request |
|
| 1215 | - * @param int $per_page |
|
| 1216 | - * @param bool $count |
|
| 1217 | - * @return array |
|
| 1218 | - * @throws EE_Error |
|
| 1219 | - */ |
|
| 1220 | - protected function _get_checkin_query_params_from_request( |
|
| 1221 | - $request, |
|
| 1222 | - $per_page = 10, |
|
| 1223 | - $count = false |
|
| 1224 | - ) { |
|
| 1225 | - $query_params = $this->_get_registration_query_parameters($request, $per_page, $count); |
|
| 1226 | - // unlike the regular registrations list table, |
|
| 1227 | - $status_ids_array = apply_filters( |
|
| 1228 | - 'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array', |
|
| 1229 | - array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved) |
|
| 1230 | - ); |
|
| 1231 | - $query_params[0]['STS_ID'] = array('IN', $status_ids_array); |
|
| 1232 | - return $query_params; |
|
| 1233 | - } |
|
| 1210 | + /** |
|
| 1211 | + * Gets the query params from the request, plus adds a where condition for the registration status, |
|
| 1212 | + * because on the checkin page we only ever want to see approved and pending-approval registrations |
|
| 1213 | + * |
|
| 1214 | + * @param array $request |
|
| 1215 | + * @param int $per_page |
|
| 1216 | + * @param bool $count |
|
| 1217 | + * @return array |
|
| 1218 | + * @throws EE_Error |
|
| 1219 | + */ |
|
| 1220 | + protected function _get_checkin_query_params_from_request( |
|
| 1221 | + $request, |
|
| 1222 | + $per_page = 10, |
|
| 1223 | + $count = false |
|
| 1224 | + ) { |
|
| 1225 | + $query_params = $this->_get_registration_query_parameters($request, $per_page, $count); |
|
| 1226 | + // unlike the regular registrations list table, |
|
| 1227 | + $status_ids_array = apply_filters( |
|
| 1228 | + 'FHEE__Extend_Registrations_Admin_Page__get_event_attendees__status_ids_array', |
|
| 1229 | + array(EEM_Registration::status_id_pending_payment, EEM_Registration::status_id_approved) |
|
| 1230 | + ); |
|
| 1231 | + $query_params[0]['STS_ID'] = array('IN', $status_ids_array); |
|
| 1232 | + return $query_params; |
|
| 1233 | + } |
|
| 1234 | 1234 | |
| 1235 | 1235 | |
| 1236 | - /** |
|
| 1237 | - * Gets registrations for an event |
|
| 1238 | - * |
|
| 1239 | - * @param int $per_page |
|
| 1240 | - * @param bool $count whether to return count or data. |
|
| 1241 | - * @param bool $trash |
|
| 1242 | - * @param string $orderby |
|
| 1243 | - * @return EE_Registration[]|int |
|
| 1244 | - * @throws EE_Error |
|
| 1245 | - * @throws InvalidArgumentException |
|
| 1246 | - * @throws InvalidDataTypeException |
|
| 1247 | - * @throws InvalidInterfaceException |
|
| 1248 | - */ |
|
| 1249 | - public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname') |
|
| 1250 | - { |
|
| 1251 | - // normalize some request params that get setup by the parent `get_registrations` method. |
|
| 1252 | - $request = $this->_req_data; |
|
| 1253 | - $request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby; |
|
| 1254 | - $request['order'] = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC'; |
|
| 1255 | - if ($trash) { |
|
| 1256 | - $request['status'] = 'trash'; |
|
| 1257 | - } |
|
| 1258 | - $query_params = $this->_get_checkin_query_params_from_request($request, $per_page, $count); |
|
| 1259 | - /** |
|
| 1260 | - * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected |
|
| 1261 | - * |
|
| 1262 | - * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093 |
|
| 1263 | - * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1264 | - * or if you have the development copy of EE you can view this at the path: |
|
| 1265 | - * /docs/G--Model-System/model-query-params.md |
|
| 1266 | - */ |
|
| 1267 | - $query_params['group_by'] = ''; |
|
| 1236 | + /** |
|
| 1237 | + * Gets registrations for an event |
|
| 1238 | + * |
|
| 1239 | + * @param int $per_page |
|
| 1240 | + * @param bool $count whether to return count or data. |
|
| 1241 | + * @param bool $trash |
|
| 1242 | + * @param string $orderby |
|
| 1243 | + * @return EE_Registration[]|int |
|
| 1244 | + * @throws EE_Error |
|
| 1245 | + * @throws InvalidArgumentException |
|
| 1246 | + * @throws InvalidDataTypeException |
|
| 1247 | + * @throws InvalidInterfaceException |
|
| 1248 | + */ |
|
| 1249 | + public function get_event_attendees($per_page = 10, $count = false, $trash = false, $orderby = 'ATT_fname') |
|
| 1250 | + { |
|
| 1251 | + // normalize some request params that get setup by the parent `get_registrations` method. |
|
| 1252 | + $request = $this->_req_data; |
|
| 1253 | + $request['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : $orderby; |
|
| 1254 | + $request['order'] = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'ASC'; |
|
| 1255 | + if ($trash) { |
|
| 1256 | + $request['status'] = 'trash'; |
|
| 1257 | + } |
|
| 1258 | + $query_params = $this->_get_checkin_query_params_from_request($request, $per_page, $count); |
|
| 1259 | + /** |
|
| 1260 | + * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected |
|
| 1261 | + * |
|
| 1262 | + * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093 |
|
| 1263 | + * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1264 | + * or if you have the development copy of EE you can view this at the path: |
|
| 1265 | + * /docs/G--Model-System/model-query-params.md |
|
| 1266 | + */ |
|
| 1267 | + $query_params['group_by'] = ''; |
|
| 1268 | 1268 | |
| 1269 | - return $count |
|
| 1270 | - ? EEM_Registration::instance()->count($query_params) |
|
| 1271 | - /** @type EE_Registration[] */ |
|
| 1272 | - : EEM_Registration::instance()->get_all($query_params); |
|
| 1273 | - } |
|
| 1269 | + return $count |
|
| 1270 | + ? EEM_Registration::instance()->count($query_params) |
|
| 1271 | + /** @type EE_Registration[] */ |
|
| 1272 | + : EEM_Registration::instance()->get_all($query_params); |
|
| 1273 | + } |
|
| 1274 | 1274 | } |
@@ -32,10 +32,10 @@ discard block |
||
| 32 | 32 | public function __construct($routing = true) |
| 33 | 33 | { |
| 34 | 34 | parent::__construct($routing); |
| 35 | - if (! defined('REG_CAF_TEMPLATE_PATH')) { |
|
| 36 | - define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/templates/'); |
|
| 37 | - define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'registrations/assets/'); |
|
| 38 | - define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registrations/assets/'); |
|
| 35 | + if ( ! defined('REG_CAF_TEMPLATE_PATH')) { |
|
| 36 | + define('REG_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'registrations/templates/'); |
|
| 37 | + define('REG_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'registrations/assets/'); |
|
| 38 | + define('REG_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'registrations/assets/'); |
|
| 39 | 39 | } |
| 40 | 40 | } |
| 41 | 41 | |
@@ -45,7 +45,7 @@ discard block |
||
| 45 | 45 | */ |
| 46 | 46 | protected function _extend_page_config() |
| 47 | 47 | { |
| 48 | - $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'registrations'; |
|
| 48 | + $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'registrations'; |
|
| 49 | 49 | $reg_id = ! empty($this->_req_data['_REG_ID']) && ! is_array($this->_req_data['_REG_ID']) |
| 50 | 50 | ? $this->_req_data['_REG_ID'] |
| 51 | 51 | : 0; |
@@ -185,14 +185,14 @@ discard block |
||
| 185 | 185 | // enqueue newsletter js |
| 186 | 186 | wp_enqueue_script( |
| 187 | 187 | 'ee-newsletter-trigger', |
| 188 | - REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.js', |
|
| 188 | + REG_CAF_ASSETS_URL.'ee-newsletter-trigger.js', |
|
| 189 | 189 | array('ee-dialog'), |
| 190 | 190 | EVENT_ESPRESSO_VERSION, |
| 191 | 191 | true |
| 192 | 192 | ); |
| 193 | 193 | wp_enqueue_style( |
| 194 | 194 | 'ee-newsletter-trigger-css', |
| 195 | - REG_CAF_ASSETS_URL . 'ee-newsletter-trigger.css', |
|
| 195 | + REG_CAF_ASSETS_URL.'ee-newsletter-trigger.css', |
|
| 196 | 196 | array(), |
| 197 | 197 | EVENT_ESPRESSO_VERSION |
| 198 | 198 | ); |
@@ -213,7 +213,7 @@ discard block |
||
| 213 | 213 | { |
| 214 | 214 | wp_register_script( |
| 215 | 215 | 'ee-reg-reports-js', |
| 216 | - REG_CAF_ASSETS_URL . 'ee-registration-admin-reports.js', |
|
| 216 | + REG_CAF_ASSETS_URL.'ee-registration-admin-reports.js', |
|
| 217 | 217 | array('google-charts'), |
| 218 | 218 | EVENT_ESPRESSO_VERSION, |
| 219 | 219 | true |
@@ -299,7 +299,7 @@ discard block |
||
| 299 | 299 | $nonce_ref = 'get_newsletter_form_content_nonce'; |
| 300 | 300 | $this->_verify_nonce($nonce, $nonce_ref); |
| 301 | 301 | // let's get the mtp for the incoming MTP_ ID |
| 302 | - if (! isset($this->_req_data['GRP_ID'])) { |
|
| 302 | + if ( ! isset($this->_req_data['GRP_ID'])) { |
|
| 303 | 303 | EE_Error::add_error( |
| 304 | 304 | esc_html__( |
| 305 | 305 | 'There must be something broken with the js or html structure because the required data for getting a message template group is not present (need an GRP_ID).', |
@@ -314,7 +314,7 @@ discard block |
||
| 314 | 314 | $this->_return_json(); |
| 315 | 315 | } |
| 316 | 316 | $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID($this->_req_data['GRP_ID']); |
| 317 | - if (! $MTPG instanceof EE_Message_Template_Group) { |
|
| 317 | + if ( ! $MTPG instanceof EE_Message_Template_Group) { |
|
| 318 | 318 | EE_Error::add_error( |
| 319 | 319 | sprintf( |
| 320 | 320 | esc_html__( |
@@ -339,12 +339,12 @@ discard block |
||
| 339 | 339 | $field = $MTP->get('MTP_template_field'); |
| 340 | 340 | if ($field === 'content') { |
| 341 | 341 | $content = $MTP->get('MTP_content'); |
| 342 | - if (! empty($content['newsletter_content'])) { |
|
| 342 | + if ( ! empty($content['newsletter_content'])) { |
|
| 343 | 343 | $template_fields['newsletter_content'] = $content['newsletter_content']; |
| 344 | 344 | } |
| 345 | 345 | continue; |
| 346 | 346 | } |
| 347 | - $template_fields[ $MTP->get('MTP_template_field') ] = $MTP->get('MTP_content'); |
|
| 347 | + $template_fields[$MTP->get('MTP_template_field')] = $MTP->get('MTP_content'); |
|
| 348 | 348 | } |
| 349 | 349 | $this->_template_args['success'] = true; |
| 350 | 350 | $this->_template_args['error'] = false; |
@@ -375,7 +375,7 @@ discard block |
||
| 375 | 375 | */ |
| 376 | 376 | public function add_newsletter_action_buttons(EE_Admin_List_Table $list_table) |
| 377 | 377 | { |
| 378 | - if (! EE_Registry::instance()->CAP->current_user_can( |
|
| 378 | + if ( ! EE_Registry::instance()->CAP->current_user_can( |
|
| 379 | 379 | 'ee_send_message', |
| 380 | 380 | 'espresso_registrations_newsletter_selected_send' |
| 381 | 381 | ) |
@@ -444,17 +444,17 @@ discard block |
||
| 444 | 444 | $field_id = $field === '[NEWSLETTER_CONTENT]' |
| 445 | 445 | ? 'content' |
| 446 | 446 | : $field; |
| 447 | - $field_id = 'batch-message-' . strtolower($field_id); |
|
| 447 | + $field_id = 'batch-message-'.strtolower($field_id); |
|
| 448 | 448 | $available_shortcodes[] = '<span class="js-shortcode-selection" data-value="' |
| 449 | 449 | . $shortcode |
| 450 | - . '" data-linked-input-id="' . $field_id . '">' |
|
| 450 | + . '" data-linked-input-id="'.$field_id.'">' |
|
| 451 | 451 | . $shortcode |
| 452 | 452 | . '</span>'; |
| 453 | 453 | } |
| 454 | - $codes[ $field ] = implode(', ', $available_shortcodes); |
|
| 454 | + $codes[$field] = implode(', ', $available_shortcodes); |
|
| 455 | 455 | } |
| 456 | 456 | $shortcodes = $codes; |
| 457 | - $form_template = REG_CAF_TEMPLATE_PATH . 'newsletter-send-form.template.php'; |
|
| 457 | + $form_template = REG_CAF_TEMPLATE_PATH.'newsletter-send-form.template.php'; |
|
| 458 | 458 | $form_template_args = array( |
| 459 | 459 | 'form_action' => admin_url('admin.php?page=espresso_registrations'), |
| 460 | 460 | 'form_route' => 'newsletter_selected_send', |
@@ -622,7 +622,7 @@ discard block |
||
| 622 | 622 | */ |
| 623 | 623 | protected function _registration_reports() |
| 624 | 624 | { |
| 625 | - $template_path = EE_ADMIN_TEMPLATE . 'admin_reports.template.php'; |
|
| 625 | + $template_path = EE_ADMIN_TEMPLATE.'admin_reports.template.php'; |
|
| 626 | 626 | $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
| 627 | 627 | $template_path, |
| 628 | 628 | $this->_reports_template_data, |
@@ -677,7 +677,7 @@ discard block |
||
| 677 | 677 | array_unshift($regs, $column_titles); |
| 678 | 678 | // setup the date range. |
| 679 | 679 | $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); |
| 680 | - $beginning_date = new DateTime("now " . $period, $DateTimeZone); |
|
| 680 | + $beginning_date = new DateTime("now ".$period, $DateTimeZone); |
|
| 681 | 681 | $ending_date = new DateTime("now", $DateTimeZone); |
| 682 | 682 | $subtitle = sprintf( |
| 683 | 683 | _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'), |
@@ -697,7 +697,7 @@ discard block |
||
| 697 | 697 | '%sThere are currently no registration records in the last month for this report.%s', |
| 698 | 698 | 'event_espresso' |
| 699 | 699 | ), |
| 700 | - '<h2>' . $report_title . '</h2><p>', |
|
| 700 | + '<h2>'.$report_title.'</h2><p>', |
|
| 701 | 701 | '</p>' |
| 702 | 702 | ), |
| 703 | 703 | ); |
@@ -750,7 +750,7 @@ discard block |
||
| 750 | 750 | array_unshift($regs, $column_titles); |
| 751 | 751 | // setup the date range. |
| 752 | 752 | $DateTimeZone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); |
| 753 | - $beginning_date = new DateTime("now " . $period, $DateTimeZone); |
|
| 753 | + $beginning_date = new DateTime("now ".$period, $DateTimeZone); |
|
| 754 | 754 | $ending_date = new DateTime("now", $DateTimeZone); |
| 755 | 755 | $subtitle = sprintf( |
| 756 | 756 | _x('For the period: %1$s to %2$s', 'Used to give date range', 'event_espresso'), |
@@ -770,7 +770,7 @@ discard block |
||
| 770 | 770 | '%sThere are currently no registration records in the last month for this report.%s', |
| 771 | 771 | 'event_espresso' |
| 772 | 772 | ), |
| 773 | - '<h2>' . $report_title . '</h2><p>', |
|
| 773 | + '<h2>'.$report_title.'</h2><p>', |
|
| 774 | 774 | '</p>' |
| 775 | 775 | ), |
| 776 | 776 | ); |
@@ -823,7 +823,7 @@ discard block |
||
| 823 | 823 | if ($datetime instanceof EE_Datetime) { |
| 824 | 824 | $datetime_label = $datetime->get_dtt_display_name(true); |
| 825 | 825 | $datetime_label .= ! empty($datetime_label) |
| 826 | - ? ' (' . $datetime->get_dtt_display_name() . ')' |
|
| 826 | + ? ' ('.$datetime->get_dtt_display_name().')' |
|
| 827 | 827 | : $datetime->get_dtt_display_name(); |
| 828 | 828 | } |
| 829 | 829 | $datetime_link = ! empty($dtt_id) && $registration instanceof EE_Registration |
@@ -837,7 +837,7 @@ discard block |
||
| 837 | 837 | ) |
| 838 | 838 | : ''; |
| 839 | 839 | $datetime_link = ! empty($datetime_link) |
| 840 | - ? '<a href="' . $datetime_link . '">' |
|
| 840 | + ? '<a href="'.$datetime_link.'">' |
|
| 841 | 841 | . '<span id="checkin-dtt">' |
| 842 | 842 | . $datetime_label |
| 843 | 843 | . '</span></a>' |
@@ -849,8 +849,8 @@ discard block |
||
| 849 | 849 | ? $attendee->get_admin_details_link() |
| 850 | 850 | : ''; |
| 851 | 851 | $attendee_link = ! empty($attendee_link) |
| 852 | - ? '<a href="' . $attendee->get_admin_details_link() . '"' |
|
| 853 | - . ' title="' . esc_html__('Click for attendee details', 'event_espresso') . '">' |
|
| 852 | + ? '<a href="'.$attendee->get_admin_details_link().'"' |
|
| 853 | + . ' title="'.esc_html__('Click for attendee details', 'event_espresso').'">' |
|
| 854 | 854 | . '<span id="checkin-attendee-name">' |
| 855 | 855 | . $attendee_name |
| 856 | 856 | . '</span></a>' |
@@ -859,25 +859,25 @@ discard block |
||
| 859 | 859 | ? $registration->event()->get_admin_details_link() |
| 860 | 860 | : ''; |
| 861 | 861 | $event_link = ! empty($event_link) |
| 862 | - ? '<a href="' . $event_link . '"' |
|
| 863 | - . ' title="' . esc_html__('Click here to edit event.', 'event_espresso') . '">' |
|
| 862 | + ? '<a href="'.$event_link.'"' |
|
| 863 | + . ' title="'.esc_html__('Click here to edit event.', 'event_espresso').'">' |
|
| 864 | 864 | . '<span id="checkin-event-name">' |
| 865 | 865 | . $registration->event_name() |
| 866 | 866 | . '</span>' |
| 867 | 867 | . '</a>' |
| 868 | 868 | : ''; |
| 869 | 869 | $this->_template_args['before_list_table'] = ! empty($reg_id) && ! empty($dtt_id) |
| 870 | - ? '<h2>' . sprintf( |
|
| 870 | + ? '<h2>'.sprintf( |
|
| 871 | 871 | esc_html__('Displaying check in records for %1$s for %2$s at the event, %3$s', 'event_espresso'), |
| 872 | 872 | $attendee_link, |
| 873 | 873 | $datetime_link, |
| 874 | 874 | $event_link |
| 875 | - ) . '</h2>' |
|
| 875 | + ).'</h2>' |
|
| 876 | 876 | : ''; |
| 877 | 877 | $this->_template_args['list_table_hidden_fields'] = ! empty($reg_id) |
| 878 | - ? '<input type="hidden" name="_REG_ID" value="' . $reg_id . '">' : ''; |
|
| 878 | + ? '<input type="hidden" name="_REG_ID" value="'.$reg_id.'">' : ''; |
|
| 879 | 879 | $this->_template_args['list_table_hidden_fields'] .= ! empty($dtt_id) |
| 880 | - ? '<input type="hidden" name="DTT_ID" value="' . $dtt_id . '">' : ''; |
|
| 880 | + ? '<input type="hidden" name="DTT_ID" value="'.$dtt_id.'">' : ''; |
|
| 881 | 881 | $this->display_admin_list_table_page_with_no_sidebar(); |
| 882 | 882 | } |
| 883 | 883 | |
@@ -894,7 +894,7 @@ discard block |
||
| 894 | 894 | public function toggle_checkin_status() |
| 895 | 895 | { |
| 896 | 896 | // first make sure we have the necessary data |
| 897 | - if (! isset($this->_req_data['_regid'])) { |
|
| 897 | + if ( ! isset($this->_req_data['_regid'])) { |
|
| 898 | 898 | EE_Error::add_error( |
| 899 | 899 | esc_html__( |
| 900 | 900 | 'There must be something broken with the html structure because the required data for toggling the Check-in status is not being sent via ajax', |
@@ -916,7 +916,7 @@ discard block |
||
| 916 | 916 | // beautiful! Made it this far so let's get the status. |
| 917 | 917 | $new_status = new CheckinStatusDashicon($this->_toggle_checkin_status()); |
| 918 | 918 | // setup new class to return via ajax |
| 919 | - $this->_template_args['admin_page_content'] = 'clickable trigger-checkin ' . $new_status->cssClasses(); |
|
| 919 | + $this->_template_args['admin_page_content'] = 'clickable trigger-checkin '.$new_status->cssClasses(); |
|
| 920 | 920 | $this->_template_args['success'] = true; |
| 921 | 921 | $this->_return_json(); |
| 922 | 922 | } |
@@ -942,7 +942,7 @@ discard block |
||
| 942 | 942 | ); |
| 943 | 943 | $new_status = false; |
| 944 | 944 | // bulk action check in toggle |
| 945 | - if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 945 | + if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 946 | 946 | // cycle thru checkboxes |
| 947 | 947 | while (list($REG_ID, $value) = each($this->_req_data['checkbox'])) { |
| 948 | 948 | $DTT_ID = isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : null; |
@@ -1012,9 +1012,9 @@ discard block |
||
| 1012 | 1012 | '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0, |
| 1013 | 1013 | ); |
| 1014 | 1014 | $errors = 0; |
| 1015 | - if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 1015 | + if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 1016 | 1016 | while (list($CHK_ID, $value) = each($this->_req_data['checkbox'])) { |
| 1017 | - if (! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) { |
|
| 1017 | + if ( ! EEM_Checkin::instance()->delete_by_ID($CHK_ID)) { |
|
| 1018 | 1018 | $errors++; |
| 1019 | 1019 | } |
| 1020 | 1020 | } |
@@ -1060,8 +1060,8 @@ discard block |
||
| 1060 | 1060 | 'DTT_ID' => isset($this->_req_data['DTT_ID']) ? $this->_req_data['DTT_ID'] : 0, |
| 1061 | 1061 | '_REG_ID' => isset($this->_req_data['_REG_ID']) ? $this->_req_data['_REG_ID'] : 0, |
| 1062 | 1062 | ); |
| 1063 | - if (! empty($this->_req_data['CHK_ID'])) { |
|
| 1064 | - if (! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) { |
|
| 1063 | + if ( ! empty($this->_req_data['CHK_ID'])) { |
|
| 1064 | + if ( ! EEM_Checkin::instance()->delete_by_ID($this->_req_data['CHK_ID'])) { |
|
| 1065 | 1065 | EE_Error::add_error( |
| 1066 | 1066 | esc_html__('Something went wrong and this check-in record was not deleted', 'event_espresso'), |
| 1067 | 1067 | __FILE__, |
@@ -1130,27 +1130,27 @@ discard block |
||
| 1130 | 1130 | 'desc' => $checked_never->legendLabel(), |
| 1131 | 1131 | ), |
| 1132 | 1132 | 'approved_status' => array( |
| 1133 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_approved, |
|
| 1133 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_approved, |
|
| 1134 | 1134 | 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'), |
| 1135 | 1135 | ), |
| 1136 | 1136 | 'cancelled_status' => array( |
| 1137 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_cancelled, |
|
| 1137 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_cancelled, |
|
| 1138 | 1138 | 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'), |
| 1139 | 1139 | ), |
| 1140 | 1140 | 'declined_status' => array( |
| 1141 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_declined, |
|
| 1141 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_declined, |
|
| 1142 | 1142 | 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'), |
| 1143 | 1143 | ), |
| 1144 | 1144 | 'not_approved' => array( |
| 1145 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_not_approved, |
|
| 1145 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_not_approved, |
|
| 1146 | 1146 | 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'), |
| 1147 | 1147 | ), |
| 1148 | 1148 | 'pending_status' => array( |
| 1149 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_pending_payment, |
|
| 1149 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_pending_payment, |
|
| 1150 | 1150 | 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'), |
| 1151 | 1151 | ), |
| 1152 | 1152 | 'wait_list' => array( |
| 1153 | - 'class' => 'ee-status-legend ee-status-legend-' . EEM_Registration::status_id_wait_list, |
|
| 1153 | + 'class' => 'ee-status-legend ee-status-legend-'.EEM_Registration::status_id_wait_list, |
|
| 1154 | 1154 | 'desc' => EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'), |
| 1155 | 1155 | ), |
| 1156 | 1156 | ); |
@@ -1159,10 +1159,10 @@ discard block |
||
| 1159 | 1159 | /** @var EE_Event $event */ |
| 1160 | 1160 | $event = EEM_Event::instance()->get_one_by_ID($event_id); |
| 1161 | 1161 | $this->_template_args['before_list_table'] = $event instanceof EE_Event |
| 1162 | - ? '<h2>' . sprintf( |
|
| 1162 | + ? '<h2>'.sprintf( |
|
| 1163 | 1163 | esc_html__('Viewing Registrations for Event: %s', 'event_espresso'), |
| 1164 | 1164 | EEM_Event::instance()->get_one_by_ID($event_id)->get('EVT_name') |
| 1165 | - ) . '</h2>' |
|
| 1165 | + ).'</h2>' |
|
| 1166 | 1166 | : ''; |
| 1167 | 1167 | // need to get the number of datetimes on the event and set default datetime_id if there is only one datetime on |
| 1168 | 1168 | // the event. |
@@ -1180,12 +1180,12 @@ discard block |
||
| 1180 | 1180 | $this->_template_args['before_list_table'] .= ' <span class="drk-grey-text">'; |
| 1181 | 1181 | $this->_template_args['before_list_table'] .= '<span class="dashicons dashicons-calendar"></span>'; |
| 1182 | 1182 | $this->_template_args['before_list_table'] .= $datetime->name(); |
| 1183 | - $this->_template_args['before_list_table'] .= ' ( ' . $datetime->date_and_time_range() . ' )'; |
|
| 1183 | + $this->_template_args['before_list_table'] .= ' ( '.$datetime->date_and_time_range().' )'; |
|
| 1184 | 1184 | $this->_template_args['before_list_table'] .= '</span></h2>'; |
| 1185 | 1185 | } |
| 1186 | 1186 | // if no datetime, then we're on the initial view, so let's give some helpful instructions on what the status |
| 1187 | 1187 | // column represents |
| 1188 | - if (! $datetime instanceof EE_Datetime) { |
|
| 1188 | + if ( ! $datetime instanceof EE_Datetime) { |
|
| 1189 | 1189 | $this->_template_args['before_list_table'] .= '<br><p class="description">' |
| 1190 | 1190 | . esc_html__( |
| 1191 | 1191 | 'In this view, the check-in status represents the latest check-in record for the registration in that row.', |
@@ -468,7 +468,7 @@ discard block |
||
| 468 | 468 | * there's a single shared message template group among all the events. Otherwise it returns null. |
| 469 | 469 | * |
| 470 | 470 | * @param array $event_ids |
| 471 | - * @return EE_Message_Template_Group|null |
|
| 471 | + * @return null|EE_Base_Class |
|
| 472 | 472 | * @throws EE_Error |
| 473 | 473 | * @throws InvalidArgumentException |
| 474 | 474 | * @throws InvalidDataTypeException |
@@ -504,7 +504,7 @@ discard block |
||
| 504 | 504 | /** |
| 505 | 505 | * Retrieves the global message template group for the current messenger and message type. |
| 506 | 506 | * |
| 507 | - * @return EE_Message_Template_Group|null |
|
| 507 | + * @return null|EE_Base_Class |
|
| 508 | 508 | * @throws EE_Error |
| 509 | 509 | * @throws InvalidArgumentException |
| 510 | 510 | * @throws InvalidDataTypeException |
@@ -659,7 +659,7 @@ discard block |
||
| 659 | 659 | * @param EE_Messages_Addressee $recipient |
| 660 | 660 | * @param array $templates formatted array of templates used for parsing data. |
| 661 | 661 | * @param EE_Message_Template_Group $message_template_group |
| 662 | - * @return bool|EE_Message |
|
| 662 | + * @return EE_Message |
|
| 663 | 663 | * @throws EE_Error |
| 664 | 664 | * @throws InvalidArgumentException |
| 665 | 665 | * @throws InvalidDataTypeException |
@@ -17,997 +17,997 @@ |
||
| 17 | 17 | { |
| 18 | 18 | |
| 19 | 19 | |
| 20 | - /** |
|
| 21 | - * @type EE_Messages_Data_Handler_Collection |
|
| 22 | - */ |
|
| 23 | - protected $_data_handler_collection; |
|
| 24 | - |
|
| 25 | - /** |
|
| 26 | - * @type EE_Message_Template_Group_Collection |
|
| 27 | - */ |
|
| 28 | - protected $_template_collection; |
|
| 29 | - |
|
| 30 | - /** |
|
| 31 | - * This will hold the data handler for the current EE_Message being generated. |
|
| 32 | - * |
|
| 33 | - * @type EE_Messages_incoming_data |
|
| 34 | - */ |
|
| 35 | - protected $_current_data_handler; |
|
| 36 | - |
|
| 37 | - /** |
|
| 38 | - * This holds the EE_Messages_Queue that contains the messages to generate. |
|
| 39 | - * |
|
| 40 | - * @type EE_Messages_Queue |
|
| 41 | - */ |
|
| 42 | - protected $_generation_queue; |
|
| 43 | - |
|
| 44 | - /** |
|
| 45 | - * This holds the EE_Messages_Queue that will store the generated EE_Message objects. |
|
| 46 | - * |
|
| 47 | - * @type EE_Messages_Queue |
|
| 48 | - */ |
|
| 49 | - protected $_ready_queue; |
|
| 50 | - |
|
| 51 | - /** |
|
| 52 | - * This is a container for any error messages that get created through the generation |
|
| 53 | - * process. |
|
| 54 | - * |
|
| 55 | - * @type array |
|
| 56 | - */ |
|
| 57 | - protected $_error_msg = array(); |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * Flag used to set when the current EE_Message in the generation queue has been verified. |
|
| 61 | - * |
|
| 62 | - * @type bool |
|
| 63 | - */ |
|
| 64 | - protected $_verified = false; |
|
| 65 | - |
|
| 66 | - /** |
|
| 67 | - * This will hold the current messenger object corresponding with the current EE_Message in the generation queue. |
|
| 68 | - * |
|
| 69 | - * @type EE_messenger |
|
| 70 | - */ |
|
| 71 | - protected $_current_messenger; |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * This will hold the current message type object corresponding with the current EE_Message in the generation queue. |
|
| 75 | - * |
|
| 76 | - * @type EE_message_type |
|
| 77 | - */ |
|
| 78 | - protected $_current_message_type; |
|
| 79 | - |
|
| 80 | - /** |
|
| 81 | - * @type EEH_Parse_Shortcodes |
|
| 82 | - */ |
|
| 83 | - protected $_shortcode_parser; |
|
| 84 | - |
|
| 85 | - |
|
| 86 | - /** |
|
| 87 | - * @param EE_Messages_Queue $generation_queue |
|
| 88 | - * @param \EE_Messages_Queue $ready_queue |
|
| 89 | - * @param \EE_Messages_Data_Handler_Collection $data_handler_collection |
|
| 90 | - * @param \EE_Message_Template_Group_Collection $template_collection |
|
| 91 | - * @param \EEH_Parse_Shortcodes $shortcode_parser |
|
| 92 | - */ |
|
| 93 | - public function __construct( |
|
| 94 | - EE_Messages_Queue $generation_queue, |
|
| 95 | - EE_Messages_Queue $ready_queue, |
|
| 96 | - EE_Messages_Data_Handler_Collection $data_handler_collection, |
|
| 97 | - EE_Message_Template_Group_Collection $template_collection, |
|
| 98 | - EEH_Parse_Shortcodes $shortcode_parser |
|
| 99 | - ) { |
|
| 100 | - $this->_generation_queue = $generation_queue; |
|
| 101 | - $this->_ready_queue = $ready_queue; |
|
| 102 | - $this->_data_handler_collection = $data_handler_collection; |
|
| 103 | - $this->_template_collection = $template_collection; |
|
| 104 | - $this->_shortcode_parser = $shortcode_parser; |
|
| 105 | - } |
|
| 106 | - |
|
| 107 | - |
|
| 108 | - /** |
|
| 109 | - * @return EE_Messages_Queue |
|
| 110 | - */ |
|
| 111 | - public function generation_queue() |
|
| 112 | - { |
|
| 113 | - return $this->_generation_queue; |
|
| 114 | - } |
|
| 115 | - |
|
| 116 | - |
|
| 117 | - /** |
|
| 118 | - * This iterates through the provided queue and generates the EE_Message objects. |
|
| 119 | - * When iterating through the queue, the queued item that served as the base for generating other EE_Message |
|
| 120 | - * objects gets removed and the new EE_Message objects get added to a NEW queue. The NEW queue is then returned |
|
| 121 | - * for the caller to decide what to do with it. |
|
| 122 | - * |
|
| 123 | - * @param bool $save Whether to save the EE_Message objects in the new queue or just return. |
|
| 124 | - * @return EE_Messages_Queue The new queue for holding generated EE_Message objects. |
|
| 125 | - * @throws EE_Error |
|
| 126 | - * @throws InvalidArgumentException |
|
| 127 | - * @throws InvalidDataTypeException |
|
| 128 | - * @throws InvalidInterfaceException |
|
| 129 | - * @throws ReflectionException |
|
| 130 | - */ |
|
| 131 | - public function generate($save = true) |
|
| 132 | - { |
|
| 133 | - // iterate through the messages in the queue, generate, and add to new queue. |
|
| 134 | - $this->_generation_queue->get_message_repository()->rewind(); |
|
| 135 | - while ($this->_generation_queue->get_message_repository()->valid()) { |
|
| 136 | - // reset "current" properties |
|
| 137 | - $this->_reset_current_properties(); |
|
| 138 | - |
|
| 139 | - /** @type EE_Message $msg */ |
|
| 140 | - $msg = $this->_generation_queue->get_message_repository()->current(); |
|
| 141 | - |
|
| 142 | - /** |
|
| 143 | - * need to get the next object and capture it for setting manually after deletes. The reason is that when |
|
| 144 | - * an object is removed from the repo then valid for the next object will fail. |
|
| 145 | - */ |
|
| 146 | - $this->_generation_queue->get_message_repository()->next(); |
|
| 147 | - $next_msg = $this->_generation_queue->get_message_repository()->current(); |
|
| 148 | - // restore pointer to current item |
|
| 149 | - $this->_generation_queue->get_message_repository()->set_current($msg); |
|
| 150 | - |
|
| 151 | - // skip and delete if the current $msg is NOT incomplete (queued for generation) |
|
| 152 | - if ($msg->STS_ID() !== EEM_Message::status_incomplete) { |
|
| 153 | - // we keep this item in the db just remove from the repo. |
|
| 154 | - $this->_generation_queue->get_message_repository()->remove($msg); |
|
| 155 | - // next item |
|
| 156 | - $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
| 157 | - continue; |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - if ($this->_verify()) { |
|
| 161 | - // let's get generating! |
|
| 162 | - $this->_generate(); |
|
| 163 | - } |
|
| 164 | - |
|
| 165 | - // don't persist debug_only messages if the messages system is not in debug mode. |
|
| 166 | - if ($msg->STS_ID() === EEM_Message::status_debug_only |
|
| 167 | - && ! EEM_Message::debug() |
|
| 168 | - ) { |
|
| 169 | - do_action( |
|
| 170 | - 'AHEE__EE_Messages_Generator__generate__before_debug_delete', |
|
| 171 | - $msg, |
|
| 172 | - $this->_error_msg, |
|
| 173 | - $this->_current_messenger, |
|
| 174 | - $this->_current_message_type, |
|
| 175 | - $this->_current_data_handler |
|
| 176 | - ); |
|
| 177 | - $this->_generation_queue->get_message_repository()->delete(); |
|
| 178 | - $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
| 179 | - continue; |
|
| 180 | - } |
|
| 181 | - |
|
| 182 | - // if there are error messages then let's set the status and the error message. |
|
| 183 | - if ($this->_error_msg) { |
|
| 184 | - // if the status is already debug only, then let's leave it at that. |
|
| 185 | - if ($msg->STS_ID() !== EEM_Message::status_debug_only) { |
|
| 186 | - $msg->set_STS_ID(EEM_Message::status_failed); |
|
| 187 | - } |
|
| 188 | - do_action( |
|
| 189 | - 'AHEE__EE_Messages_Generator__generate__processing_failed_message', |
|
| 190 | - $msg, |
|
| 191 | - $this->_error_msg, |
|
| 192 | - $this->_current_messenger, |
|
| 193 | - $this->_current_message_type, |
|
| 194 | - $this->_current_data_handler |
|
| 195 | - ); |
|
| 196 | - $msg->set_error_message( |
|
| 197 | - esc_html__('Message failed to generate for the following reasons: ', 'event_espresso') |
|
| 198 | - . "\n" |
|
| 199 | - . implode("\n", $this->_error_msg) |
|
| 200 | - ); |
|
| 201 | - $msg->set_modified(time()); |
|
| 202 | - } else { |
|
| 203 | - do_action( |
|
| 204 | - 'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete', |
|
| 205 | - $msg, |
|
| 206 | - $this->_error_msg, |
|
| 207 | - $this->_current_messenger, |
|
| 208 | - $this->_current_message_type, |
|
| 209 | - $this->_current_data_handler |
|
| 210 | - ); |
|
| 211 | - // remove from db |
|
| 212 | - $this->_generation_queue->get_message_repository()->delete(); |
|
| 213 | - } |
|
| 214 | - // next item |
|
| 215 | - $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
| 216 | - } |
|
| 217 | - |
|
| 218 | - // generation queue is ALWAYS saved to record any errors in the generation process. |
|
| 219 | - $this->_generation_queue->save(); |
|
| 220 | - |
|
| 221 | - /** |
|
| 222 | - * save _ready_queue if flag set. |
|
| 223 | - * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method. This |
|
| 224 | - * means if a field was added that is not a valid database column. The EE_Message was already saved to the db |
|
| 225 | - * so a EE_Extra_Meta entry could be created and attached to the EE_Message. In those cases the save flag is |
|
| 226 | - * irrelevant. |
|
| 227 | - */ |
|
| 228 | - if ($save) { |
|
| 229 | - $this->_ready_queue->save(); |
|
| 230 | - } |
|
| 231 | - |
|
| 232 | - // final reset of properties |
|
| 233 | - $this->_reset_current_properties(); |
|
| 234 | - |
|
| 235 | - return $this->_ready_queue; |
|
| 236 | - } |
|
| 237 | - |
|
| 238 | - |
|
| 239 | - /** |
|
| 240 | - * This resets all the properties used for holding "current" values corresponding to the current EE_Message object |
|
| 241 | - * in the generation queue. |
|
| 242 | - */ |
|
| 243 | - protected function _reset_current_properties() |
|
| 244 | - { |
|
| 245 | - $this->_verified = false; |
|
| 246 | - // make sure any _data value in the current message type is reset |
|
| 247 | - if ($this->_current_message_type instanceof EE_message_type) { |
|
| 248 | - $this->_current_message_type->reset_data(); |
|
| 249 | - } |
|
| 250 | - $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null; |
|
| 251 | - } |
|
| 252 | - |
|
| 253 | - |
|
| 254 | - /** |
|
| 255 | - * This proceeds with the actual generation of a message. By the time this is called, there should already be a |
|
| 256 | - * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the |
|
| 257 | - * _generating_queue. |
|
| 258 | - * |
|
| 259 | - * @return bool Whether the message was successfully generated or not. |
|
| 260 | - * @throws EE_Error |
|
| 261 | - * @throws InvalidArgumentException |
|
| 262 | - * @throws InvalidDataTypeException |
|
| 263 | - * @throws InvalidInterfaceException |
|
| 264 | - * @throws ReflectionException |
|
| 265 | - */ |
|
| 266 | - protected function _generate() |
|
| 267 | - { |
|
| 268 | - // double check verification has run and that everything is ready to work with (saves us having to validate |
|
| 269 | - // everything again). |
|
| 270 | - if (! $this->_verified) { |
|
| 271 | - return false; // get out because we don't have a valid setup to work with. |
|
| 272 | - } |
|
| 273 | - |
|
| 274 | - |
|
| 275 | - try { |
|
| 276 | - $addressees = $this->_current_message_type->get_addressees( |
|
| 277 | - $this->_current_data_handler, |
|
| 278 | - $this->_generation_queue->get_message_repository()->current()->context() |
|
| 279 | - ); |
|
| 280 | - } catch (EE_Error $e) { |
|
| 281 | - $this->_error_msg[] = $e->getMessage(); |
|
| 282 | - return false; |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - |
|
| 286 | - // if no addressees then get out because there is nothing to generation (possible bad data). |
|
| 287 | - if (! $this->_valid_addressees($addressees)) { |
|
| 288 | - do_action( |
|
| 289 | - 'AHEE__EE_Messages_Generator___generate__invalid_addressees', |
|
| 290 | - $this->_generation_queue->get_message_repository()->current(), |
|
| 291 | - $addressees, |
|
| 292 | - $this->_current_messenger, |
|
| 293 | - $this->_current_message_type, |
|
| 294 | - $this->_current_data_handler |
|
| 295 | - ); |
|
| 296 | - $this->_generation_queue->get_message_repository()->current()->set_STS_ID( |
|
| 297 | - EEM_Message::status_debug_only |
|
| 298 | - ); |
|
| 299 | - $this->_error_msg[] = esc_html__( |
|
| 300 | - 'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects. There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.', |
|
| 301 | - 'event_espresso' |
|
| 302 | - ); |
|
| 303 | - return false; |
|
| 304 | - } |
|
| 305 | - |
|
| 306 | - $message_template_group = $this->_get_message_template_group(); |
|
| 307 | - |
|
| 308 | - // in the unlikely event there is no EE_Message_Template_Group available, get out! |
|
| 309 | - if (! $message_template_group instanceof EE_Message_Template_Group) { |
|
| 310 | - $this->_error_msg[] = esc_html__( |
|
| 311 | - 'Unable to get the Message Templates for the Message being generated. No message template group accessible.', |
|
| 312 | - 'event_espresso' |
|
| 313 | - ); |
|
| 314 | - return false; |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - // get formatted templates for using to parse and setup EE_Message objects. |
|
| 318 | - $templates = $this->_get_templates($message_template_group); |
|
| 319 | - |
|
| 320 | - |
|
| 321 | - // setup new EE_Message objects (and add to _ready_queue) |
|
| 322 | - return $this->_assemble_messages($addressees, $templates, $message_template_group); |
|
| 323 | - } |
|
| 324 | - |
|
| 325 | - |
|
| 326 | - /** |
|
| 327 | - * Retrieves the message template group being used for generating messages. |
|
| 328 | - * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times. |
|
| 329 | - * |
|
| 330 | - * @return EE_Message_Template_Group|null |
|
| 331 | - * @throws EE_Error |
|
| 332 | - * @throws InvalidArgumentException |
|
| 333 | - * @throws InvalidDataTypeException |
|
| 334 | - * @throws InvalidInterfaceException |
|
| 335 | - * @throws ReflectionException |
|
| 336 | - */ |
|
| 337 | - protected function _get_message_template_group() |
|
| 338 | - { |
|
| 339 | - // first see if there is a specific message template group requested (current message in the queue has a |
|
| 340 | - // specific GRP_ID |
|
| 341 | - $message_template_group = $this->_specific_message_template_group_from_queue(); |
|
| 342 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 343 | - return $message_template_group; |
|
| 344 | - } |
|
| 345 | - |
|
| 346 | - // get event_ids from the datahandler so we can check to see if there's already a message template group for |
|
| 347 | - // them in the collection. |
|
| 348 | - $event_ids = $this->_get_event_ids_from_current_data_handler(); |
|
| 349 | - $message_template_group = $this->_template_collection->get_by_key( |
|
| 350 | - $this->_template_collection->getKey( |
|
| 351 | - $this->_current_messenger->name, |
|
| 352 | - $this->_current_message_type->name, |
|
| 353 | - $event_ids |
|
| 354 | - ) |
|
| 355 | - ); |
|
| 356 | - |
|
| 357 | - // if we have a message template group then no need to hit the database, just return it. |
|
| 358 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 359 | - return $message_template_group; |
|
| 360 | - } |
|
| 361 | - |
|
| 362 | - // okay made it here, so let's get the global group first for this messenger and message type to ensure |
|
| 363 | - // there is no override set. |
|
| 364 | - $global_message_template_group = |
|
| 365 | - $this->_get_global_message_template_group_for_current_messenger_and_message_type(); |
|
| 366 | - |
|
| 367 | - if ($global_message_template_group instanceof EE_Message_Template_Group |
|
| 368 | - && $global_message_template_group->get('MTP_is_override') |
|
| 369 | - ) { |
|
| 370 | - return $global_message_template_group; |
|
| 371 | - } |
|
| 372 | - |
|
| 373 | - // if we're still here, that means there was no message template group for the events in the collection and |
|
| 374 | - // the global message template group for the messenger and message type is not set for override. So next step |
|
| 375 | - // is to see if there is a common shared custom message template group for this set of events. |
|
| 376 | - $message_template_group = $this->_get_shared_message_template_for_events($event_ids); |
|
| 377 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 378 | - return $message_template_group; |
|
| 379 | - } |
|
| 380 | - |
|
| 381 | - // STILL here? Okay that means the fallback is to just use the global message template group for this event |
|
| 382 | - // set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this |
|
| 383 | - // request) and return it. |
|
| 384 | - if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 385 | - $this->_template_collection->add( |
|
| 386 | - $global_message_template_group, |
|
| 387 | - $event_ids |
|
| 388 | - ); |
|
| 389 | - return $global_message_template_group; |
|
| 390 | - } |
|
| 391 | - |
|
| 392 | - // if we land here that means there's NO active message template group for this set. |
|
| 393 | - // TODO this will be a good target for some optimization down the road. Whenever there is no active message |
|
| 394 | - // template group for a given event set then cache that result so we don't repeat the logic. However, for now, |
|
| 395 | - // this should likely bit hit rarely enough that it's not a significant issue. |
|
| 396 | - return null; |
|
| 397 | - } |
|
| 398 | - |
|
| 399 | - |
|
| 400 | - /** |
|
| 401 | - * This checks the current message in the queue and determines if there is a specific Message Template Group |
|
| 402 | - * requested for that message. |
|
| 403 | - * |
|
| 404 | - * @return EE_Message_Template_Group|null |
|
| 405 | - * @throws EE_Error |
|
| 406 | - * @throws InvalidArgumentException |
|
| 407 | - * @throws InvalidDataTypeException |
|
| 408 | - * @throws InvalidInterfaceException |
|
| 409 | - */ |
|
| 410 | - protected function _specific_message_template_group_from_queue() |
|
| 411 | - { |
|
| 412 | - // is there a GRP_ID already on the EE_Message object? If there is, then a specific template has been requested |
|
| 413 | - // so let's use that. |
|
| 414 | - $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID(); |
|
| 415 | - |
|
| 416 | - if ($GRP_ID) { |
|
| 417 | - // attempt to retrieve from repo first |
|
| 418 | - $message_template_group = $this->_template_collection->get_by_ID($GRP_ID); |
|
| 419 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 420 | - return $message_template_group; // got it! |
|
| 421 | - } |
|
| 422 | - |
|
| 423 | - // nope don't have it yet. Get from DB then add to repo if its not here, then that means the current GRP_ID |
|
| 424 | - // is not valid, so we'll continue on in the code assuming there's NO GRP_ID. |
|
| 425 | - $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID); |
|
| 426 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 427 | - $this->_template_collection->add($message_template_group); |
|
| 428 | - return $message_template_group; |
|
| 429 | - } |
|
| 430 | - } |
|
| 431 | - return null; |
|
| 432 | - } |
|
| 433 | - |
|
| 434 | - |
|
| 435 | - /** |
|
| 436 | - * Returns whether the event ids passed in all share the same message template group for the current message type |
|
| 437 | - * and messenger. |
|
| 438 | - * |
|
| 439 | - * @param array $event_ids |
|
| 440 | - * @return bool true means they DO share the same message template group, false means they don't. |
|
| 441 | - * @throws EE_Error |
|
| 442 | - * @throws InvalidArgumentException |
|
| 443 | - * @throws InvalidDataTypeException |
|
| 444 | - * @throws InvalidInterfaceException |
|
| 445 | - */ |
|
| 446 | - protected function _queue_shares_same_message_template_group_for_events(array $event_ids) |
|
| 447 | - { |
|
| 448 | - foreach ($this->_current_data_handler->events as $event) { |
|
| 449 | - $event_ids[ $event['ID'] ] = $event['ID']; |
|
| 450 | - } |
|
| 451 | - $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count( |
|
| 452 | - array( |
|
| 453 | - array( |
|
| 454 | - 'Event.EVT_ID' => array('IN', $event_ids), |
|
| 455 | - 'MTP_messenger' => $this->_current_messenger->name, |
|
| 456 | - 'MTP_message_type' => $this->_current_message_type->name, |
|
| 457 | - ), |
|
| 458 | - ), |
|
| 459 | - 'GRP_ID', |
|
| 460 | - true |
|
| 461 | - ); |
|
| 462 | - return $count_of_message_template_groups === 1; |
|
| 463 | - } |
|
| 464 | - |
|
| 465 | - |
|
| 466 | - /** |
|
| 467 | - * This will get the shared message template group for events that are in the current data handler but ONLY if |
|
| 468 | - * there's a single shared message template group among all the events. Otherwise it returns null. |
|
| 469 | - * |
|
| 470 | - * @param array $event_ids |
|
| 471 | - * @return EE_Message_Template_Group|null |
|
| 472 | - * @throws EE_Error |
|
| 473 | - * @throws InvalidArgumentException |
|
| 474 | - * @throws InvalidDataTypeException |
|
| 475 | - * @throws InvalidInterfaceException |
|
| 476 | - */ |
|
| 477 | - protected function _get_shared_message_template_for_events(array $event_ids) |
|
| 478 | - { |
|
| 479 | - $message_template_group = null; |
|
| 480 | - if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) { |
|
| 481 | - $message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
| 482 | - array( |
|
| 483 | - array( |
|
| 484 | - 'Event.EVT_ID' => array('IN', $event_ids), |
|
| 485 | - 'MTP_messenger' => $this->_current_messenger->name, |
|
| 486 | - 'MTP_message_type' => $this->_current_message_type->name, |
|
| 487 | - 'MTP_is_active' => true, |
|
| 488 | - ), |
|
| 489 | - 'group_by' => 'GRP_ID', |
|
| 490 | - ) |
|
| 491 | - ); |
|
| 492 | - // store this in the collection if its valid |
|
| 493 | - if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 494 | - $this->_template_collection->add( |
|
| 495 | - $message_template_group, |
|
| 496 | - $event_ids |
|
| 497 | - ); |
|
| 498 | - } |
|
| 499 | - } |
|
| 500 | - return $message_template_group; |
|
| 501 | - } |
|
| 502 | - |
|
| 503 | - |
|
| 504 | - /** |
|
| 505 | - * Retrieves the global message template group for the current messenger and message type. |
|
| 506 | - * |
|
| 507 | - * @return EE_Message_Template_Group|null |
|
| 508 | - * @throws EE_Error |
|
| 509 | - * @throws InvalidArgumentException |
|
| 510 | - * @throws InvalidDataTypeException |
|
| 511 | - * @throws InvalidInterfaceException |
|
| 512 | - */ |
|
| 513 | - protected function _get_global_message_template_group_for_current_messenger_and_message_type() |
|
| 514 | - { |
|
| 515 | - // first check the collection (we use an array with 0 in it to represent global groups). |
|
| 516 | - $global_message_template_group = $this->_template_collection->get_by_key( |
|
| 517 | - $this->_template_collection->getKey( |
|
| 518 | - $this->_current_messenger->name, |
|
| 519 | - $this->_current_message_type->name, |
|
| 520 | - array(0) |
|
| 521 | - ) |
|
| 522 | - ); |
|
| 523 | - |
|
| 524 | - // if we don't have a group lets hit the db. |
|
| 525 | - if (! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 526 | - $global_message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
| 527 | - array( |
|
| 528 | - array( |
|
| 529 | - 'MTP_messenger' => $this->_current_messenger->name, |
|
| 530 | - 'MTP_message_type' => $this->_current_message_type->name, |
|
| 531 | - 'MTP_is_active' => true, |
|
| 532 | - 'MTP_is_global' => true, |
|
| 533 | - ), |
|
| 534 | - ) |
|
| 535 | - ); |
|
| 536 | - // if we have a group, add it to the collection. |
|
| 537 | - if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 538 | - $this->_template_collection->add( |
|
| 539 | - $global_message_template_group, |
|
| 540 | - array(0) |
|
| 541 | - ); |
|
| 542 | - } |
|
| 543 | - } |
|
| 544 | - return $global_message_template_group; |
|
| 545 | - } |
|
| 546 | - |
|
| 547 | - |
|
| 548 | - /** |
|
| 549 | - * Returns an array of event ids for all the events within the current data handler. |
|
| 550 | - * |
|
| 551 | - * @return array |
|
| 552 | - */ |
|
| 553 | - protected function _get_event_ids_from_current_data_handler() |
|
| 554 | - { |
|
| 555 | - $event_ids = array(); |
|
| 556 | - foreach ($this->_current_data_handler->events as $event) { |
|
| 557 | - $event_ids[ $event['ID'] ] = $event['ID']; |
|
| 558 | - } |
|
| 559 | - return $event_ids; |
|
| 560 | - } |
|
| 561 | - |
|
| 562 | - |
|
| 563 | - /** |
|
| 564 | - * Retrieves formatted array of template information for each context specific to the given |
|
| 565 | - * EE_Message_Template_Group |
|
| 566 | - * |
|
| 567 | - * @param EE_Message_Template_Group $message_template_group |
|
| 568 | - * @return array The returned array is in this structure: |
|
| 569 | - * array( |
|
| 570 | - * 'field_name' => array( |
|
| 571 | - * 'context' => 'content' |
|
| 572 | - * ) |
|
| 573 | - * ) |
|
| 574 | - * @throws EE_Error |
|
| 575 | - * @throws InvalidArgumentException |
|
| 576 | - * @throws InvalidDataTypeException |
|
| 577 | - * @throws InvalidInterfaceException |
|
| 578 | - * @throws ReflectionException |
|
| 579 | - */ |
|
| 580 | - protected function _get_templates(EE_Message_Template_Group $message_template_group) |
|
| 581 | - { |
|
| 582 | - $templates = array(); |
|
| 583 | - $context_templates = $message_template_group->context_templates(); |
|
| 584 | - foreach ($context_templates as $context => $template_fields) { |
|
| 585 | - foreach ($template_fields as $template_field => $template_obj) { |
|
| 586 | - if (! $template_obj instanceof EE_Message_Template) { |
|
| 587 | - continue; |
|
| 588 | - } |
|
| 589 | - $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content'); |
|
| 590 | - } |
|
| 591 | - } |
|
| 592 | - return $templates; |
|
| 593 | - } |
|
| 594 | - |
|
| 595 | - |
|
| 596 | - /** |
|
| 597 | - * Assembles new fully generated EE_Message objects and adds to _ready_queue |
|
| 598 | - * |
|
| 599 | - * @param array $addressees Array of EE_Messages_Addressee objects indexed by message type |
|
| 600 | - * context. |
|
| 601 | - * @param array $templates formatted array of templates used for parsing data. |
|
| 602 | - * @param EE_Message_Template_Group $message_template_group |
|
| 603 | - * @return bool true if message generation went a-ok. false if some sort of exception occurred. Note: The |
|
| 604 | - * method will attempt to generate ALL EE_Message objects and add to |
|
| 605 | - * the _ready_queue. Successfully generated messages get added to the |
|
| 606 | - * queue with EEM_Message::status_idle, unsuccessfully generated |
|
| 607 | - * messages will get added to the queue as EEM_Message::status_failed. |
|
| 608 | - * Very rarely should "false" be returned from this method. |
|
| 609 | - * @throws EE_Error |
|
| 610 | - * @throws InvalidArgumentException |
|
| 611 | - * @throws InvalidDataTypeException |
|
| 612 | - * @throws InvalidIdentifierException |
|
| 613 | - * @throws InvalidInterfaceException |
|
| 614 | - * @throws ReflectionException |
|
| 615 | - */ |
|
| 616 | - protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group) |
|
| 617 | - { |
|
| 618 | - |
|
| 619 | - // if templates are empty then get out because we can't generate anything. |
|
| 620 | - if (! $templates) { |
|
| 621 | - $this->_error_msg[] = esc_html__( |
|
| 622 | - 'Unable to assemble messages because there are no templates retrieved for generating the messages with', |
|
| 623 | - 'event_espresso' |
|
| 624 | - ); |
|
| 625 | - return false; |
|
| 626 | - } |
|
| 627 | - |
|
| 628 | - // We use this as the counter for generated messages because don't forget we may be executing this inside of a |
|
| 629 | - // generation_queue. So _ready_queue may have generated EE_Message objects already. |
|
| 630 | - $generated_count = 0; |
|
| 631 | - foreach ($addressees as $context => $recipients) { |
|
| 632 | - foreach ($recipients as $recipient) { |
|
| 633 | - $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group); |
|
| 634 | - if ($message instanceof EE_Message) { |
|
| 635 | - $this->_ready_queue->add( |
|
| 636 | - $message, |
|
| 637 | - array(), |
|
| 638 | - $this->_generation_queue->get_message_repository()->is_preview(), |
|
| 639 | - $this->_generation_queue->get_message_repository()->is_test_send() |
|
| 640 | - ); |
|
| 641 | - $generated_count++; |
|
| 642 | - } |
|
| 643 | - |
|
| 644 | - // if the current MSG being generated is for a test send then we'll only use ONE message in the |
|
| 645 | - // generation. |
|
| 646 | - if ($this->_generation_queue->get_message_repository()->is_test_send()) { |
|
| 647 | - break 2; |
|
| 648 | - } |
|
| 649 | - } |
|
| 650 | - } |
|
| 651 | - |
|
| 652 | - // if there are no generated messages then something else fatal went wrong. |
|
| 653 | - return $generated_count > 0; |
|
| 654 | - } |
|
| 655 | - |
|
| 656 | - |
|
| 657 | - /** |
|
| 658 | - * @param string $context The context for the generated message. |
|
| 659 | - * @param EE_Messages_Addressee $recipient |
|
| 660 | - * @param array $templates formatted array of templates used for parsing data. |
|
| 661 | - * @param EE_Message_Template_Group $message_template_group |
|
| 662 | - * @return bool|EE_Message |
|
| 663 | - * @throws EE_Error |
|
| 664 | - * @throws InvalidArgumentException |
|
| 665 | - * @throws InvalidDataTypeException |
|
| 666 | - * @throws InvalidInterfaceException |
|
| 667 | - * @throws ReflectionException |
|
| 668 | - * @throws InvalidIdentifierException |
|
| 669 | - */ |
|
| 670 | - protected function _setup_message_object( |
|
| 671 | - $context, |
|
| 672 | - EE_Messages_Addressee $recipient, |
|
| 673 | - $templates, |
|
| 674 | - EE_Message_Template_Group $message_template_group |
|
| 675 | - ) { |
|
| 676 | - // stuff we already know |
|
| 677 | - $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0; |
|
| 678 | - $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction |
|
| 679 | - ? $this->_current_data_handler->txn->ID() |
|
| 680 | - : $transaction_id; |
|
| 681 | - $message_fields = array( |
|
| 682 | - 'GRP_ID' => $message_template_group->ID(), |
|
| 683 | - 'TXN_ID' => $transaction_id, |
|
| 684 | - 'MSG_messenger' => $this->_current_messenger->name, |
|
| 685 | - 'MSG_message_type' => $this->_current_message_type->name, |
|
| 686 | - 'MSG_context' => $context, |
|
| 687 | - ); |
|
| 688 | - |
|
| 689 | - // recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab |
|
| 690 | - // the info from the att_obj found in the EE_Messages_Addressee object. |
|
| 691 | - if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) { |
|
| 692 | - $message_fields['MSG_recipient_ID'] = $recipient->att_obj instanceof EE_Attendee |
|
| 693 | - ? $recipient->att_obj->ID() |
|
| 694 | - : 0; |
|
| 695 | - $message_fields['MSG_recipient_type'] = 'Attendee'; |
|
| 696 | - } else { |
|
| 697 | - $message_fields['MSG_recipient_ID'] = $recipient->recipient_id; |
|
| 698 | - $message_fields['MSG_recipient_type'] = $recipient->recipient_type; |
|
| 699 | - } |
|
| 700 | - $message = EE_Message_Factory::create($message_fields); |
|
| 701 | - |
|
| 702 | - // grab valid shortcodes for shortcode parser |
|
| 703 | - $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes(); |
|
| 704 | - $m_shortcodes = $this->_current_messenger->get_valid_shortcodes(); |
|
| 705 | - |
|
| 706 | - // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing |
|
| 707 | - if (! $this->_generation_queue->get_message_repository()->is_preview() |
|
| 708 | - && ( |
|
| 709 | - ( |
|
| 710 | - empty($templates['to'][ $context ]) |
|
| 711 | - && ! $this->_current_messenger->allow_empty_to_field() |
|
| 712 | - ) |
|
| 713 | - || ! $message_template_group->is_context_active($context) |
|
| 714 | - ) |
|
| 715 | - ) { |
|
| 716 | - // we silently exit here and do NOT record a fail because the message is "turned off" by having no "to" |
|
| 717 | - // field. |
|
| 718 | - return false; |
|
| 719 | - } |
|
| 720 | - $error_msg = array(); |
|
| 721 | - foreach ($templates as $field => $field_context) { |
|
| 722 | - $error_msg = array(); |
|
| 723 | - // let's setup the valid shortcodes for the incoming context. |
|
| 724 | - $valid_shortcodes = $mt_shortcodes[ $context ]; |
|
| 725 | - // merge in valid shortcodes for the field. |
|
| 726 | - $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes; |
|
| 727 | - if (isset($templates[ $field ][ $context ])) { |
|
| 728 | - // prefix field. |
|
| 729 | - $column_name = 'MSG_' . $field; |
|
| 730 | - try { |
|
| 731 | - $content = $this->_shortcode_parser->parse_message_template( |
|
| 732 | - $templates[ $field ][ $context ], |
|
| 733 | - $recipient, |
|
| 734 | - $shortcodes, |
|
| 735 | - $this->_current_message_type, |
|
| 736 | - $this->_current_messenger, |
|
| 737 | - $message |
|
| 738 | - ); |
|
| 739 | - // the model field removes slashes when setting (usually necessary when the input is from the |
|
| 740 | - // request) but this value is from another model and has no slashes. So add them so it matchces |
|
| 741 | - // what the field expected (otherwise slashes will have been stripped from this an extra time) |
|
| 742 | - $message->set_field_or_extra_meta($column_name, addslashes($content)); |
|
| 743 | - } catch (EE_Error $e) { |
|
| 744 | - $error_msg[] = sprintf( |
|
| 745 | - /* Translators: First place holder is message model field name. |
|
| 20 | + /** |
|
| 21 | + * @type EE_Messages_Data_Handler_Collection |
|
| 22 | + */ |
|
| 23 | + protected $_data_handler_collection; |
|
| 24 | + |
|
| 25 | + /** |
|
| 26 | + * @type EE_Message_Template_Group_Collection |
|
| 27 | + */ |
|
| 28 | + protected $_template_collection; |
|
| 29 | + |
|
| 30 | + /** |
|
| 31 | + * This will hold the data handler for the current EE_Message being generated. |
|
| 32 | + * |
|
| 33 | + * @type EE_Messages_incoming_data |
|
| 34 | + */ |
|
| 35 | + protected $_current_data_handler; |
|
| 36 | + |
|
| 37 | + /** |
|
| 38 | + * This holds the EE_Messages_Queue that contains the messages to generate. |
|
| 39 | + * |
|
| 40 | + * @type EE_Messages_Queue |
|
| 41 | + */ |
|
| 42 | + protected $_generation_queue; |
|
| 43 | + |
|
| 44 | + /** |
|
| 45 | + * This holds the EE_Messages_Queue that will store the generated EE_Message objects. |
|
| 46 | + * |
|
| 47 | + * @type EE_Messages_Queue |
|
| 48 | + */ |
|
| 49 | + protected $_ready_queue; |
|
| 50 | + |
|
| 51 | + /** |
|
| 52 | + * This is a container for any error messages that get created through the generation |
|
| 53 | + * process. |
|
| 54 | + * |
|
| 55 | + * @type array |
|
| 56 | + */ |
|
| 57 | + protected $_error_msg = array(); |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * Flag used to set when the current EE_Message in the generation queue has been verified. |
|
| 61 | + * |
|
| 62 | + * @type bool |
|
| 63 | + */ |
|
| 64 | + protected $_verified = false; |
|
| 65 | + |
|
| 66 | + /** |
|
| 67 | + * This will hold the current messenger object corresponding with the current EE_Message in the generation queue. |
|
| 68 | + * |
|
| 69 | + * @type EE_messenger |
|
| 70 | + */ |
|
| 71 | + protected $_current_messenger; |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * This will hold the current message type object corresponding with the current EE_Message in the generation queue. |
|
| 75 | + * |
|
| 76 | + * @type EE_message_type |
|
| 77 | + */ |
|
| 78 | + protected $_current_message_type; |
|
| 79 | + |
|
| 80 | + /** |
|
| 81 | + * @type EEH_Parse_Shortcodes |
|
| 82 | + */ |
|
| 83 | + protected $_shortcode_parser; |
|
| 84 | + |
|
| 85 | + |
|
| 86 | + /** |
|
| 87 | + * @param EE_Messages_Queue $generation_queue |
|
| 88 | + * @param \EE_Messages_Queue $ready_queue |
|
| 89 | + * @param \EE_Messages_Data_Handler_Collection $data_handler_collection |
|
| 90 | + * @param \EE_Message_Template_Group_Collection $template_collection |
|
| 91 | + * @param \EEH_Parse_Shortcodes $shortcode_parser |
|
| 92 | + */ |
|
| 93 | + public function __construct( |
|
| 94 | + EE_Messages_Queue $generation_queue, |
|
| 95 | + EE_Messages_Queue $ready_queue, |
|
| 96 | + EE_Messages_Data_Handler_Collection $data_handler_collection, |
|
| 97 | + EE_Message_Template_Group_Collection $template_collection, |
|
| 98 | + EEH_Parse_Shortcodes $shortcode_parser |
|
| 99 | + ) { |
|
| 100 | + $this->_generation_queue = $generation_queue; |
|
| 101 | + $this->_ready_queue = $ready_queue; |
|
| 102 | + $this->_data_handler_collection = $data_handler_collection; |
|
| 103 | + $this->_template_collection = $template_collection; |
|
| 104 | + $this->_shortcode_parser = $shortcode_parser; |
|
| 105 | + } |
|
| 106 | + |
|
| 107 | + |
|
| 108 | + /** |
|
| 109 | + * @return EE_Messages_Queue |
|
| 110 | + */ |
|
| 111 | + public function generation_queue() |
|
| 112 | + { |
|
| 113 | + return $this->_generation_queue; |
|
| 114 | + } |
|
| 115 | + |
|
| 116 | + |
|
| 117 | + /** |
|
| 118 | + * This iterates through the provided queue and generates the EE_Message objects. |
|
| 119 | + * When iterating through the queue, the queued item that served as the base for generating other EE_Message |
|
| 120 | + * objects gets removed and the new EE_Message objects get added to a NEW queue. The NEW queue is then returned |
|
| 121 | + * for the caller to decide what to do with it. |
|
| 122 | + * |
|
| 123 | + * @param bool $save Whether to save the EE_Message objects in the new queue or just return. |
|
| 124 | + * @return EE_Messages_Queue The new queue for holding generated EE_Message objects. |
|
| 125 | + * @throws EE_Error |
|
| 126 | + * @throws InvalidArgumentException |
|
| 127 | + * @throws InvalidDataTypeException |
|
| 128 | + * @throws InvalidInterfaceException |
|
| 129 | + * @throws ReflectionException |
|
| 130 | + */ |
|
| 131 | + public function generate($save = true) |
|
| 132 | + { |
|
| 133 | + // iterate through the messages in the queue, generate, and add to new queue. |
|
| 134 | + $this->_generation_queue->get_message_repository()->rewind(); |
|
| 135 | + while ($this->_generation_queue->get_message_repository()->valid()) { |
|
| 136 | + // reset "current" properties |
|
| 137 | + $this->_reset_current_properties(); |
|
| 138 | + |
|
| 139 | + /** @type EE_Message $msg */ |
|
| 140 | + $msg = $this->_generation_queue->get_message_repository()->current(); |
|
| 141 | + |
|
| 142 | + /** |
|
| 143 | + * need to get the next object and capture it for setting manually after deletes. The reason is that when |
|
| 144 | + * an object is removed from the repo then valid for the next object will fail. |
|
| 145 | + */ |
|
| 146 | + $this->_generation_queue->get_message_repository()->next(); |
|
| 147 | + $next_msg = $this->_generation_queue->get_message_repository()->current(); |
|
| 148 | + // restore pointer to current item |
|
| 149 | + $this->_generation_queue->get_message_repository()->set_current($msg); |
|
| 150 | + |
|
| 151 | + // skip and delete if the current $msg is NOT incomplete (queued for generation) |
|
| 152 | + if ($msg->STS_ID() !== EEM_Message::status_incomplete) { |
|
| 153 | + // we keep this item in the db just remove from the repo. |
|
| 154 | + $this->_generation_queue->get_message_repository()->remove($msg); |
|
| 155 | + // next item |
|
| 156 | + $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
| 157 | + continue; |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + if ($this->_verify()) { |
|
| 161 | + // let's get generating! |
|
| 162 | + $this->_generate(); |
|
| 163 | + } |
|
| 164 | + |
|
| 165 | + // don't persist debug_only messages if the messages system is not in debug mode. |
|
| 166 | + if ($msg->STS_ID() === EEM_Message::status_debug_only |
|
| 167 | + && ! EEM_Message::debug() |
|
| 168 | + ) { |
|
| 169 | + do_action( |
|
| 170 | + 'AHEE__EE_Messages_Generator__generate__before_debug_delete', |
|
| 171 | + $msg, |
|
| 172 | + $this->_error_msg, |
|
| 173 | + $this->_current_messenger, |
|
| 174 | + $this->_current_message_type, |
|
| 175 | + $this->_current_data_handler |
|
| 176 | + ); |
|
| 177 | + $this->_generation_queue->get_message_repository()->delete(); |
|
| 178 | + $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
| 179 | + continue; |
|
| 180 | + } |
|
| 181 | + |
|
| 182 | + // if there are error messages then let's set the status and the error message. |
|
| 183 | + if ($this->_error_msg) { |
|
| 184 | + // if the status is already debug only, then let's leave it at that. |
|
| 185 | + if ($msg->STS_ID() !== EEM_Message::status_debug_only) { |
|
| 186 | + $msg->set_STS_ID(EEM_Message::status_failed); |
|
| 187 | + } |
|
| 188 | + do_action( |
|
| 189 | + 'AHEE__EE_Messages_Generator__generate__processing_failed_message', |
|
| 190 | + $msg, |
|
| 191 | + $this->_error_msg, |
|
| 192 | + $this->_current_messenger, |
|
| 193 | + $this->_current_message_type, |
|
| 194 | + $this->_current_data_handler |
|
| 195 | + ); |
|
| 196 | + $msg->set_error_message( |
|
| 197 | + esc_html__('Message failed to generate for the following reasons: ', 'event_espresso') |
|
| 198 | + . "\n" |
|
| 199 | + . implode("\n", $this->_error_msg) |
|
| 200 | + ); |
|
| 201 | + $msg->set_modified(time()); |
|
| 202 | + } else { |
|
| 203 | + do_action( |
|
| 204 | + 'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete', |
|
| 205 | + $msg, |
|
| 206 | + $this->_error_msg, |
|
| 207 | + $this->_current_messenger, |
|
| 208 | + $this->_current_message_type, |
|
| 209 | + $this->_current_data_handler |
|
| 210 | + ); |
|
| 211 | + // remove from db |
|
| 212 | + $this->_generation_queue->get_message_repository()->delete(); |
|
| 213 | + } |
|
| 214 | + // next item |
|
| 215 | + $this->_generation_queue->get_message_repository()->set_current($next_msg); |
|
| 216 | + } |
|
| 217 | + |
|
| 218 | + // generation queue is ALWAYS saved to record any errors in the generation process. |
|
| 219 | + $this->_generation_queue->save(); |
|
| 220 | + |
|
| 221 | + /** |
|
| 222 | + * save _ready_queue if flag set. |
|
| 223 | + * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method. This |
|
| 224 | + * means if a field was added that is not a valid database column. The EE_Message was already saved to the db |
|
| 225 | + * so a EE_Extra_Meta entry could be created and attached to the EE_Message. In those cases the save flag is |
|
| 226 | + * irrelevant. |
|
| 227 | + */ |
|
| 228 | + if ($save) { |
|
| 229 | + $this->_ready_queue->save(); |
|
| 230 | + } |
|
| 231 | + |
|
| 232 | + // final reset of properties |
|
| 233 | + $this->_reset_current_properties(); |
|
| 234 | + |
|
| 235 | + return $this->_ready_queue; |
|
| 236 | + } |
|
| 237 | + |
|
| 238 | + |
|
| 239 | + /** |
|
| 240 | + * This resets all the properties used for holding "current" values corresponding to the current EE_Message object |
|
| 241 | + * in the generation queue. |
|
| 242 | + */ |
|
| 243 | + protected function _reset_current_properties() |
|
| 244 | + { |
|
| 245 | + $this->_verified = false; |
|
| 246 | + // make sure any _data value in the current message type is reset |
|
| 247 | + if ($this->_current_message_type instanceof EE_message_type) { |
|
| 248 | + $this->_current_message_type->reset_data(); |
|
| 249 | + } |
|
| 250 | + $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null; |
|
| 251 | + } |
|
| 252 | + |
|
| 253 | + |
|
| 254 | + /** |
|
| 255 | + * This proceeds with the actual generation of a message. By the time this is called, there should already be a |
|
| 256 | + * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the |
|
| 257 | + * _generating_queue. |
|
| 258 | + * |
|
| 259 | + * @return bool Whether the message was successfully generated or not. |
|
| 260 | + * @throws EE_Error |
|
| 261 | + * @throws InvalidArgumentException |
|
| 262 | + * @throws InvalidDataTypeException |
|
| 263 | + * @throws InvalidInterfaceException |
|
| 264 | + * @throws ReflectionException |
|
| 265 | + */ |
|
| 266 | + protected function _generate() |
|
| 267 | + { |
|
| 268 | + // double check verification has run and that everything is ready to work with (saves us having to validate |
|
| 269 | + // everything again). |
|
| 270 | + if (! $this->_verified) { |
|
| 271 | + return false; // get out because we don't have a valid setup to work with. |
|
| 272 | + } |
|
| 273 | + |
|
| 274 | + |
|
| 275 | + try { |
|
| 276 | + $addressees = $this->_current_message_type->get_addressees( |
|
| 277 | + $this->_current_data_handler, |
|
| 278 | + $this->_generation_queue->get_message_repository()->current()->context() |
|
| 279 | + ); |
|
| 280 | + } catch (EE_Error $e) { |
|
| 281 | + $this->_error_msg[] = $e->getMessage(); |
|
| 282 | + return false; |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + |
|
| 286 | + // if no addressees then get out because there is nothing to generation (possible bad data). |
|
| 287 | + if (! $this->_valid_addressees($addressees)) { |
|
| 288 | + do_action( |
|
| 289 | + 'AHEE__EE_Messages_Generator___generate__invalid_addressees', |
|
| 290 | + $this->_generation_queue->get_message_repository()->current(), |
|
| 291 | + $addressees, |
|
| 292 | + $this->_current_messenger, |
|
| 293 | + $this->_current_message_type, |
|
| 294 | + $this->_current_data_handler |
|
| 295 | + ); |
|
| 296 | + $this->_generation_queue->get_message_repository()->current()->set_STS_ID( |
|
| 297 | + EEM_Message::status_debug_only |
|
| 298 | + ); |
|
| 299 | + $this->_error_msg[] = esc_html__( |
|
| 300 | + 'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects. There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.', |
|
| 301 | + 'event_espresso' |
|
| 302 | + ); |
|
| 303 | + return false; |
|
| 304 | + } |
|
| 305 | + |
|
| 306 | + $message_template_group = $this->_get_message_template_group(); |
|
| 307 | + |
|
| 308 | + // in the unlikely event there is no EE_Message_Template_Group available, get out! |
|
| 309 | + if (! $message_template_group instanceof EE_Message_Template_Group) { |
|
| 310 | + $this->_error_msg[] = esc_html__( |
|
| 311 | + 'Unable to get the Message Templates for the Message being generated. No message template group accessible.', |
|
| 312 | + 'event_espresso' |
|
| 313 | + ); |
|
| 314 | + return false; |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + // get formatted templates for using to parse and setup EE_Message objects. |
|
| 318 | + $templates = $this->_get_templates($message_template_group); |
|
| 319 | + |
|
| 320 | + |
|
| 321 | + // setup new EE_Message objects (and add to _ready_queue) |
|
| 322 | + return $this->_assemble_messages($addressees, $templates, $message_template_group); |
|
| 323 | + } |
|
| 324 | + |
|
| 325 | + |
|
| 326 | + /** |
|
| 327 | + * Retrieves the message template group being used for generating messages. |
|
| 328 | + * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times. |
|
| 329 | + * |
|
| 330 | + * @return EE_Message_Template_Group|null |
|
| 331 | + * @throws EE_Error |
|
| 332 | + * @throws InvalidArgumentException |
|
| 333 | + * @throws InvalidDataTypeException |
|
| 334 | + * @throws InvalidInterfaceException |
|
| 335 | + * @throws ReflectionException |
|
| 336 | + */ |
|
| 337 | + protected function _get_message_template_group() |
|
| 338 | + { |
|
| 339 | + // first see if there is a specific message template group requested (current message in the queue has a |
|
| 340 | + // specific GRP_ID |
|
| 341 | + $message_template_group = $this->_specific_message_template_group_from_queue(); |
|
| 342 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 343 | + return $message_template_group; |
|
| 344 | + } |
|
| 345 | + |
|
| 346 | + // get event_ids from the datahandler so we can check to see if there's already a message template group for |
|
| 347 | + // them in the collection. |
|
| 348 | + $event_ids = $this->_get_event_ids_from_current_data_handler(); |
|
| 349 | + $message_template_group = $this->_template_collection->get_by_key( |
|
| 350 | + $this->_template_collection->getKey( |
|
| 351 | + $this->_current_messenger->name, |
|
| 352 | + $this->_current_message_type->name, |
|
| 353 | + $event_ids |
|
| 354 | + ) |
|
| 355 | + ); |
|
| 356 | + |
|
| 357 | + // if we have a message template group then no need to hit the database, just return it. |
|
| 358 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 359 | + return $message_template_group; |
|
| 360 | + } |
|
| 361 | + |
|
| 362 | + // okay made it here, so let's get the global group first for this messenger and message type to ensure |
|
| 363 | + // there is no override set. |
|
| 364 | + $global_message_template_group = |
|
| 365 | + $this->_get_global_message_template_group_for_current_messenger_and_message_type(); |
|
| 366 | + |
|
| 367 | + if ($global_message_template_group instanceof EE_Message_Template_Group |
|
| 368 | + && $global_message_template_group->get('MTP_is_override') |
|
| 369 | + ) { |
|
| 370 | + return $global_message_template_group; |
|
| 371 | + } |
|
| 372 | + |
|
| 373 | + // if we're still here, that means there was no message template group for the events in the collection and |
|
| 374 | + // the global message template group for the messenger and message type is not set for override. So next step |
|
| 375 | + // is to see if there is a common shared custom message template group for this set of events. |
|
| 376 | + $message_template_group = $this->_get_shared_message_template_for_events($event_ids); |
|
| 377 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 378 | + return $message_template_group; |
|
| 379 | + } |
|
| 380 | + |
|
| 381 | + // STILL here? Okay that means the fallback is to just use the global message template group for this event |
|
| 382 | + // set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this |
|
| 383 | + // request) and return it. |
|
| 384 | + if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 385 | + $this->_template_collection->add( |
|
| 386 | + $global_message_template_group, |
|
| 387 | + $event_ids |
|
| 388 | + ); |
|
| 389 | + return $global_message_template_group; |
|
| 390 | + } |
|
| 391 | + |
|
| 392 | + // if we land here that means there's NO active message template group for this set. |
|
| 393 | + // TODO this will be a good target for some optimization down the road. Whenever there is no active message |
|
| 394 | + // template group for a given event set then cache that result so we don't repeat the logic. However, for now, |
|
| 395 | + // this should likely bit hit rarely enough that it's not a significant issue. |
|
| 396 | + return null; |
|
| 397 | + } |
|
| 398 | + |
|
| 399 | + |
|
| 400 | + /** |
|
| 401 | + * This checks the current message in the queue and determines if there is a specific Message Template Group |
|
| 402 | + * requested for that message. |
|
| 403 | + * |
|
| 404 | + * @return EE_Message_Template_Group|null |
|
| 405 | + * @throws EE_Error |
|
| 406 | + * @throws InvalidArgumentException |
|
| 407 | + * @throws InvalidDataTypeException |
|
| 408 | + * @throws InvalidInterfaceException |
|
| 409 | + */ |
|
| 410 | + protected function _specific_message_template_group_from_queue() |
|
| 411 | + { |
|
| 412 | + // is there a GRP_ID already on the EE_Message object? If there is, then a specific template has been requested |
|
| 413 | + // so let's use that. |
|
| 414 | + $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID(); |
|
| 415 | + |
|
| 416 | + if ($GRP_ID) { |
|
| 417 | + // attempt to retrieve from repo first |
|
| 418 | + $message_template_group = $this->_template_collection->get_by_ID($GRP_ID); |
|
| 419 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 420 | + return $message_template_group; // got it! |
|
| 421 | + } |
|
| 422 | + |
|
| 423 | + // nope don't have it yet. Get from DB then add to repo if its not here, then that means the current GRP_ID |
|
| 424 | + // is not valid, so we'll continue on in the code assuming there's NO GRP_ID. |
|
| 425 | + $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID); |
|
| 426 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 427 | + $this->_template_collection->add($message_template_group); |
|
| 428 | + return $message_template_group; |
|
| 429 | + } |
|
| 430 | + } |
|
| 431 | + return null; |
|
| 432 | + } |
|
| 433 | + |
|
| 434 | + |
|
| 435 | + /** |
|
| 436 | + * Returns whether the event ids passed in all share the same message template group for the current message type |
|
| 437 | + * and messenger. |
|
| 438 | + * |
|
| 439 | + * @param array $event_ids |
|
| 440 | + * @return bool true means they DO share the same message template group, false means they don't. |
|
| 441 | + * @throws EE_Error |
|
| 442 | + * @throws InvalidArgumentException |
|
| 443 | + * @throws InvalidDataTypeException |
|
| 444 | + * @throws InvalidInterfaceException |
|
| 445 | + */ |
|
| 446 | + protected function _queue_shares_same_message_template_group_for_events(array $event_ids) |
|
| 447 | + { |
|
| 448 | + foreach ($this->_current_data_handler->events as $event) { |
|
| 449 | + $event_ids[ $event['ID'] ] = $event['ID']; |
|
| 450 | + } |
|
| 451 | + $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count( |
|
| 452 | + array( |
|
| 453 | + array( |
|
| 454 | + 'Event.EVT_ID' => array('IN', $event_ids), |
|
| 455 | + 'MTP_messenger' => $this->_current_messenger->name, |
|
| 456 | + 'MTP_message_type' => $this->_current_message_type->name, |
|
| 457 | + ), |
|
| 458 | + ), |
|
| 459 | + 'GRP_ID', |
|
| 460 | + true |
|
| 461 | + ); |
|
| 462 | + return $count_of_message_template_groups === 1; |
|
| 463 | + } |
|
| 464 | + |
|
| 465 | + |
|
| 466 | + /** |
|
| 467 | + * This will get the shared message template group for events that are in the current data handler but ONLY if |
|
| 468 | + * there's a single shared message template group among all the events. Otherwise it returns null. |
|
| 469 | + * |
|
| 470 | + * @param array $event_ids |
|
| 471 | + * @return EE_Message_Template_Group|null |
|
| 472 | + * @throws EE_Error |
|
| 473 | + * @throws InvalidArgumentException |
|
| 474 | + * @throws InvalidDataTypeException |
|
| 475 | + * @throws InvalidInterfaceException |
|
| 476 | + */ |
|
| 477 | + protected function _get_shared_message_template_for_events(array $event_ids) |
|
| 478 | + { |
|
| 479 | + $message_template_group = null; |
|
| 480 | + if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) { |
|
| 481 | + $message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
| 482 | + array( |
|
| 483 | + array( |
|
| 484 | + 'Event.EVT_ID' => array('IN', $event_ids), |
|
| 485 | + 'MTP_messenger' => $this->_current_messenger->name, |
|
| 486 | + 'MTP_message_type' => $this->_current_message_type->name, |
|
| 487 | + 'MTP_is_active' => true, |
|
| 488 | + ), |
|
| 489 | + 'group_by' => 'GRP_ID', |
|
| 490 | + ) |
|
| 491 | + ); |
|
| 492 | + // store this in the collection if its valid |
|
| 493 | + if ($message_template_group instanceof EE_Message_Template_Group) { |
|
| 494 | + $this->_template_collection->add( |
|
| 495 | + $message_template_group, |
|
| 496 | + $event_ids |
|
| 497 | + ); |
|
| 498 | + } |
|
| 499 | + } |
|
| 500 | + return $message_template_group; |
|
| 501 | + } |
|
| 502 | + |
|
| 503 | + |
|
| 504 | + /** |
|
| 505 | + * Retrieves the global message template group for the current messenger and message type. |
|
| 506 | + * |
|
| 507 | + * @return EE_Message_Template_Group|null |
|
| 508 | + * @throws EE_Error |
|
| 509 | + * @throws InvalidArgumentException |
|
| 510 | + * @throws InvalidDataTypeException |
|
| 511 | + * @throws InvalidInterfaceException |
|
| 512 | + */ |
|
| 513 | + protected function _get_global_message_template_group_for_current_messenger_and_message_type() |
|
| 514 | + { |
|
| 515 | + // first check the collection (we use an array with 0 in it to represent global groups). |
|
| 516 | + $global_message_template_group = $this->_template_collection->get_by_key( |
|
| 517 | + $this->_template_collection->getKey( |
|
| 518 | + $this->_current_messenger->name, |
|
| 519 | + $this->_current_message_type->name, |
|
| 520 | + array(0) |
|
| 521 | + ) |
|
| 522 | + ); |
|
| 523 | + |
|
| 524 | + // if we don't have a group lets hit the db. |
|
| 525 | + if (! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 526 | + $global_message_template_group = EEM_Message_Template_Group::instance()->get_one( |
|
| 527 | + array( |
|
| 528 | + array( |
|
| 529 | + 'MTP_messenger' => $this->_current_messenger->name, |
|
| 530 | + 'MTP_message_type' => $this->_current_message_type->name, |
|
| 531 | + 'MTP_is_active' => true, |
|
| 532 | + 'MTP_is_global' => true, |
|
| 533 | + ), |
|
| 534 | + ) |
|
| 535 | + ); |
|
| 536 | + // if we have a group, add it to the collection. |
|
| 537 | + if ($global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 538 | + $this->_template_collection->add( |
|
| 539 | + $global_message_template_group, |
|
| 540 | + array(0) |
|
| 541 | + ); |
|
| 542 | + } |
|
| 543 | + } |
|
| 544 | + return $global_message_template_group; |
|
| 545 | + } |
|
| 546 | + |
|
| 547 | + |
|
| 548 | + /** |
|
| 549 | + * Returns an array of event ids for all the events within the current data handler. |
|
| 550 | + * |
|
| 551 | + * @return array |
|
| 552 | + */ |
|
| 553 | + protected function _get_event_ids_from_current_data_handler() |
|
| 554 | + { |
|
| 555 | + $event_ids = array(); |
|
| 556 | + foreach ($this->_current_data_handler->events as $event) { |
|
| 557 | + $event_ids[ $event['ID'] ] = $event['ID']; |
|
| 558 | + } |
|
| 559 | + return $event_ids; |
|
| 560 | + } |
|
| 561 | + |
|
| 562 | + |
|
| 563 | + /** |
|
| 564 | + * Retrieves formatted array of template information for each context specific to the given |
|
| 565 | + * EE_Message_Template_Group |
|
| 566 | + * |
|
| 567 | + * @param EE_Message_Template_Group $message_template_group |
|
| 568 | + * @return array The returned array is in this structure: |
|
| 569 | + * array( |
|
| 570 | + * 'field_name' => array( |
|
| 571 | + * 'context' => 'content' |
|
| 572 | + * ) |
|
| 573 | + * ) |
|
| 574 | + * @throws EE_Error |
|
| 575 | + * @throws InvalidArgumentException |
|
| 576 | + * @throws InvalidDataTypeException |
|
| 577 | + * @throws InvalidInterfaceException |
|
| 578 | + * @throws ReflectionException |
|
| 579 | + */ |
|
| 580 | + protected function _get_templates(EE_Message_Template_Group $message_template_group) |
|
| 581 | + { |
|
| 582 | + $templates = array(); |
|
| 583 | + $context_templates = $message_template_group->context_templates(); |
|
| 584 | + foreach ($context_templates as $context => $template_fields) { |
|
| 585 | + foreach ($template_fields as $template_field => $template_obj) { |
|
| 586 | + if (! $template_obj instanceof EE_Message_Template) { |
|
| 587 | + continue; |
|
| 588 | + } |
|
| 589 | + $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content'); |
|
| 590 | + } |
|
| 591 | + } |
|
| 592 | + return $templates; |
|
| 593 | + } |
|
| 594 | + |
|
| 595 | + |
|
| 596 | + /** |
|
| 597 | + * Assembles new fully generated EE_Message objects and adds to _ready_queue |
|
| 598 | + * |
|
| 599 | + * @param array $addressees Array of EE_Messages_Addressee objects indexed by message type |
|
| 600 | + * context. |
|
| 601 | + * @param array $templates formatted array of templates used for parsing data. |
|
| 602 | + * @param EE_Message_Template_Group $message_template_group |
|
| 603 | + * @return bool true if message generation went a-ok. false if some sort of exception occurred. Note: The |
|
| 604 | + * method will attempt to generate ALL EE_Message objects and add to |
|
| 605 | + * the _ready_queue. Successfully generated messages get added to the |
|
| 606 | + * queue with EEM_Message::status_idle, unsuccessfully generated |
|
| 607 | + * messages will get added to the queue as EEM_Message::status_failed. |
|
| 608 | + * Very rarely should "false" be returned from this method. |
|
| 609 | + * @throws EE_Error |
|
| 610 | + * @throws InvalidArgumentException |
|
| 611 | + * @throws InvalidDataTypeException |
|
| 612 | + * @throws InvalidIdentifierException |
|
| 613 | + * @throws InvalidInterfaceException |
|
| 614 | + * @throws ReflectionException |
|
| 615 | + */ |
|
| 616 | + protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group) |
|
| 617 | + { |
|
| 618 | + |
|
| 619 | + // if templates are empty then get out because we can't generate anything. |
|
| 620 | + if (! $templates) { |
|
| 621 | + $this->_error_msg[] = esc_html__( |
|
| 622 | + 'Unable to assemble messages because there are no templates retrieved for generating the messages with', |
|
| 623 | + 'event_espresso' |
|
| 624 | + ); |
|
| 625 | + return false; |
|
| 626 | + } |
|
| 627 | + |
|
| 628 | + // We use this as the counter for generated messages because don't forget we may be executing this inside of a |
|
| 629 | + // generation_queue. So _ready_queue may have generated EE_Message objects already. |
|
| 630 | + $generated_count = 0; |
|
| 631 | + foreach ($addressees as $context => $recipients) { |
|
| 632 | + foreach ($recipients as $recipient) { |
|
| 633 | + $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group); |
|
| 634 | + if ($message instanceof EE_Message) { |
|
| 635 | + $this->_ready_queue->add( |
|
| 636 | + $message, |
|
| 637 | + array(), |
|
| 638 | + $this->_generation_queue->get_message_repository()->is_preview(), |
|
| 639 | + $this->_generation_queue->get_message_repository()->is_test_send() |
|
| 640 | + ); |
|
| 641 | + $generated_count++; |
|
| 642 | + } |
|
| 643 | + |
|
| 644 | + // if the current MSG being generated is for a test send then we'll only use ONE message in the |
|
| 645 | + // generation. |
|
| 646 | + if ($this->_generation_queue->get_message_repository()->is_test_send()) { |
|
| 647 | + break 2; |
|
| 648 | + } |
|
| 649 | + } |
|
| 650 | + } |
|
| 651 | + |
|
| 652 | + // if there are no generated messages then something else fatal went wrong. |
|
| 653 | + return $generated_count > 0; |
|
| 654 | + } |
|
| 655 | + |
|
| 656 | + |
|
| 657 | + /** |
|
| 658 | + * @param string $context The context for the generated message. |
|
| 659 | + * @param EE_Messages_Addressee $recipient |
|
| 660 | + * @param array $templates formatted array of templates used for parsing data. |
|
| 661 | + * @param EE_Message_Template_Group $message_template_group |
|
| 662 | + * @return bool|EE_Message |
|
| 663 | + * @throws EE_Error |
|
| 664 | + * @throws InvalidArgumentException |
|
| 665 | + * @throws InvalidDataTypeException |
|
| 666 | + * @throws InvalidInterfaceException |
|
| 667 | + * @throws ReflectionException |
|
| 668 | + * @throws InvalidIdentifierException |
|
| 669 | + */ |
|
| 670 | + protected function _setup_message_object( |
|
| 671 | + $context, |
|
| 672 | + EE_Messages_Addressee $recipient, |
|
| 673 | + $templates, |
|
| 674 | + EE_Message_Template_Group $message_template_group |
|
| 675 | + ) { |
|
| 676 | + // stuff we already know |
|
| 677 | + $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0; |
|
| 678 | + $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction |
|
| 679 | + ? $this->_current_data_handler->txn->ID() |
|
| 680 | + : $transaction_id; |
|
| 681 | + $message_fields = array( |
|
| 682 | + 'GRP_ID' => $message_template_group->ID(), |
|
| 683 | + 'TXN_ID' => $transaction_id, |
|
| 684 | + 'MSG_messenger' => $this->_current_messenger->name, |
|
| 685 | + 'MSG_message_type' => $this->_current_message_type->name, |
|
| 686 | + 'MSG_context' => $context, |
|
| 687 | + ); |
|
| 688 | + |
|
| 689 | + // recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab |
|
| 690 | + // the info from the att_obj found in the EE_Messages_Addressee object. |
|
| 691 | + if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) { |
|
| 692 | + $message_fields['MSG_recipient_ID'] = $recipient->att_obj instanceof EE_Attendee |
|
| 693 | + ? $recipient->att_obj->ID() |
|
| 694 | + : 0; |
|
| 695 | + $message_fields['MSG_recipient_type'] = 'Attendee'; |
|
| 696 | + } else { |
|
| 697 | + $message_fields['MSG_recipient_ID'] = $recipient->recipient_id; |
|
| 698 | + $message_fields['MSG_recipient_type'] = $recipient->recipient_type; |
|
| 699 | + } |
|
| 700 | + $message = EE_Message_Factory::create($message_fields); |
|
| 701 | + |
|
| 702 | + // grab valid shortcodes for shortcode parser |
|
| 703 | + $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes(); |
|
| 704 | + $m_shortcodes = $this->_current_messenger->get_valid_shortcodes(); |
|
| 705 | + |
|
| 706 | + // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing |
|
| 707 | + if (! $this->_generation_queue->get_message_repository()->is_preview() |
|
| 708 | + && ( |
|
| 709 | + ( |
|
| 710 | + empty($templates['to'][ $context ]) |
|
| 711 | + && ! $this->_current_messenger->allow_empty_to_field() |
|
| 712 | + ) |
|
| 713 | + || ! $message_template_group->is_context_active($context) |
|
| 714 | + ) |
|
| 715 | + ) { |
|
| 716 | + // we silently exit here and do NOT record a fail because the message is "turned off" by having no "to" |
|
| 717 | + // field. |
|
| 718 | + return false; |
|
| 719 | + } |
|
| 720 | + $error_msg = array(); |
|
| 721 | + foreach ($templates as $field => $field_context) { |
|
| 722 | + $error_msg = array(); |
|
| 723 | + // let's setup the valid shortcodes for the incoming context. |
|
| 724 | + $valid_shortcodes = $mt_shortcodes[ $context ]; |
|
| 725 | + // merge in valid shortcodes for the field. |
|
| 726 | + $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes; |
|
| 727 | + if (isset($templates[ $field ][ $context ])) { |
|
| 728 | + // prefix field. |
|
| 729 | + $column_name = 'MSG_' . $field; |
|
| 730 | + try { |
|
| 731 | + $content = $this->_shortcode_parser->parse_message_template( |
|
| 732 | + $templates[ $field ][ $context ], |
|
| 733 | + $recipient, |
|
| 734 | + $shortcodes, |
|
| 735 | + $this->_current_message_type, |
|
| 736 | + $this->_current_messenger, |
|
| 737 | + $message |
|
| 738 | + ); |
|
| 739 | + // the model field removes slashes when setting (usually necessary when the input is from the |
|
| 740 | + // request) but this value is from another model and has no slashes. So add them so it matchces |
|
| 741 | + // what the field expected (otherwise slashes will have been stripped from this an extra time) |
|
| 742 | + $message->set_field_or_extra_meta($column_name, addslashes($content)); |
|
| 743 | + } catch (EE_Error $e) { |
|
| 744 | + $error_msg[] = sprintf( |
|
| 745 | + /* Translators: First place holder is message model field name. |
|
| 746 | 746 | * Second placeholder is exception error message */ |
| 747 | - esc_html__( |
|
| 748 | - 'There was a problem generating the content for the field %s: %s', |
|
| 749 | - 'event_espresso' |
|
| 750 | - ), |
|
| 751 | - $field, |
|
| 752 | - $e->getMessage() |
|
| 753 | - ); |
|
| 754 | - $message->set_STS_ID(EEM_Message::status_failed); |
|
| 755 | - } |
|
| 756 | - } |
|
| 757 | - } |
|
| 758 | - |
|
| 759 | - if ($message->STS_ID() === EEM_Message::status_failed) { |
|
| 760 | - $error_msg = esc_html__('There were problems generating this message:', 'event_espresso') |
|
| 761 | - . "\n" |
|
| 762 | - . implode("\n", $error_msg); |
|
| 763 | - $message->set_error_message($error_msg); |
|
| 764 | - } else { |
|
| 765 | - $message->set_STS_ID(EEM_Message::status_idle); |
|
| 766 | - } |
|
| 767 | - return $message; |
|
| 768 | - } |
|
| 769 | - |
|
| 770 | - |
|
| 771 | - /** |
|
| 772 | - * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate |
|
| 773 | - * error message if either is missing. |
|
| 774 | - * |
|
| 775 | - * @return bool true means there were no errors, false means there were errors. |
|
| 776 | - */ |
|
| 777 | - protected function _verify() |
|
| 778 | - { |
|
| 779 | - // reset error message to an empty array. |
|
| 780 | - $this->_error_msg = array(); |
|
| 781 | - $valid = true; |
|
| 782 | - $valid = $valid ? $this->_validate_messenger_and_message_type() : $valid; |
|
| 783 | - $valid = $valid ? $this->_validate_and_setup_data() : $valid; |
|
| 784 | - |
|
| 785 | - // set the verified flag so we know everything has been validated. |
|
| 786 | - $this->_verified = $valid; |
|
| 787 | - |
|
| 788 | - return $valid; |
|
| 789 | - } |
|
| 790 | - |
|
| 791 | - |
|
| 792 | - /** |
|
| 793 | - * This accepts an array and validates that it is an array indexed by context with each value being an array of |
|
| 794 | - * EE_Messages_Addressee objects. |
|
| 795 | - * |
|
| 796 | - * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[] |
|
| 797 | - * @return bool |
|
| 798 | - */ |
|
| 799 | - protected function _valid_addressees($addressees) |
|
| 800 | - { |
|
| 801 | - if (! $addressees || ! is_array($addressees)) { |
|
| 802 | - return false; |
|
| 803 | - } |
|
| 804 | - |
|
| 805 | - foreach ($addressees as $addressee_array) { |
|
| 806 | - foreach ($addressee_array as $addressee) { |
|
| 807 | - if (! $addressee instanceof EE_Messages_Addressee) { |
|
| 808 | - return false; |
|
| 809 | - } |
|
| 810 | - } |
|
| 811 | - } |
|
| 812 | - return true; |
|
| 813 | - } |
|
| 814 | - |
|
| 815 | - |
|
| 816 | - /** |
|
| 817 | - * This validates the messenger, message type, and presences of generation data for the current EE_Message in the |
|
| 818 | - * queue. This process sets error messages if something is wrong. |
|
| 819 | - * |
|
| 820 | - * @return bool true is if there are no errors. false is if there is. |
|
| 821 | - */ |
|
| 822 | - protected function _validate_messenger_and_message_type() |
|
| 823 | - { |
|
| 824 | - |
|
| 825 | - // first are there any existing error messages? If so then return. |
|
| 826 | - if ($this->_error_msg) { |
|
| 827 | - return false; |
|
| 828 | - } |
|
| 829 | - /** @type EE_Message $message */ |
|
| 830 | - $message = $this->_generation_queue->get_message_repository()->current(); |
|
| 831 | - try { |
|
| 832 | - $this->_current_messenger = $message->valid_messenger(true) |
|
| 833 | - ? $message->messenger_object() |
|
| 834 | - : null; |
|
| 835 | - } catch (Exception $e) { |
|
| 836 | - $this->_error_msg[] = $e->getMessage(); |
|
| 837 | - } |
|
| 838 | - try { |
|
| 839 | - $this->_current_message_type = $message->valid_message_type(true) |
|
| 840 | - ? $message->message_type_object() |
|
| 841 | - : null; |
|
| 842 | - } catch (Exception $e) { |
|
| 843 | - $this->_error_msg[] = $e->getMessage(); |
|
| 844 | - } |
|
| 845 | - |
|
| 846 | - /** |
|
| 847 | - * Check if there is any generation data, but only if this is not for a preview. |
|
| 848 | - */ |
|
| 849 | - if (! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
| 850 | - && ( |
|
| 851 | - ! $this->_generation_queue->get_message_repository()->is_preview() |
|
| 852 | - && $this->_generation_queue->get_message_repository()->get_data_handler() |
|
| 853 | - !== 'EE_Messages_Preview_incoming_data' |
|
| 854 | - ) |
|
| 855 | - ) { |
|
| 856 | - $this->_error_msg[] = esc_html__( |
|
| 857 | - 'There is no generation data for this message. Unable to generate.', |
|
| 858 | - 'event_espresso' |
|
| 859 | - ); |
|
| 860 | - } |
|
| 861 | - |
|
| 862 | - return empty($this->_error_msg); |
|
| 863 | - } |
|
| 864 | - |
|
| 865 | - |
|
| 866 | - /** |
|
| 867 | - * This method retrieves the expected data handler for the message type and validates the generation data for that |
|
| 868 | - * data handler. |
|
| 869 | - * |
|
| 870 | - * @return bool true means there are no errors. false means there were errors (and handler did not get setup). |
|
| 871 | - */ |
|
| 872 | - protected function _validate_and_setup_data() |
|
| 873 | - { |
|
| 874 | - |
|
| 875 | - // First, are there any existing error messages? If so, return because if there were errors elsewhere this |
|
| 876 | - // can't be used anyways. |
|
| 877 | - if ($this->_error_msg) { |
|
| 878 | - return false; |
|
| 879 | - } |
|
| 880 | - |
|
| 881 | - $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data(); |
|
| 882 | - |
|
| 883 | - /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/ |
|
| 884 | - $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler() |
|
| 885 | - ? $this->_generation_queue->get_message_repository()->get_data_handler() |
|
| 886 | - : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data'; |
|
| 887 | - |
|
| 888 | - // If this EE_Message is for a preview, then let's switch out to the preview data handler. |
|
| 889 | - if ($this->_generation_queue->get_message_repository()->is_preview()) { |
|
| 890 | - $data_handler_class_name = 'EE_Messages_Preview_incoming_data'; |
|
| 891 | - } |
|
| 892 | - |
|
| 893 | - // First get the class name for the data handler (and also verifies it exists. |
|
| 894 | - if (! class_exists($data_handler_class_name)) { |
|
| 895 | - $this->_error_msg[] = sprintf( |
|
| 896 | - /* Translators: Both placeholders are the names of php classes. */ |
|
| 897 | - esc_html__( |
|
| 898 | - 'The included data handler class name does not match any valid, accessible, "%1$s" classes. Looking for %2$s.', |
|
| 899 | - 'event_espresso' |
|
| 900 | - ), |
|
| 901 | - 'EE_Messages_incoming_data', |
|
| 902 | - $data_handler_class_name |
|
| 903 | - ); |
|
| 904 | - return false; |
|
| 905 | - } |
|
| 906 | - |
|
| 907 | - // convert generation_data for data_handler_instantiation. |
|
| 908 | - $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data); |
|
| 909 | - |
|
| 910 | - // note, this may set error messages as well. |
|
| 911 | - $this->_set_data_handler($generation_data, $data_handler_class_name); |
|
| 912 | - |
|
| 913 | - return empty($this->_error_msg); |
|
| 914 | - } |
|
| 915 | - |
|
| 916 | - |
|
| 917 | - /** |
|
| 918 | - * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and |
|
| 919 | - * adds it to the _data repository. |
|
| 920 | - * |
|
| 921 | - * @param mixed $generating_data This is data expected by the instantiated data handler. |
|
| 922 | - * @param string $data_handler_class_name This is the reference string indicating what data handler is being |
|
| 923 | - * instantiated. |
|
| 924 | - */ |
|
| 925 | - protected function _set_data_handler($generating_data, $data_handler_class_name) |
|
| 926 | - { |
|
| 927 | - // valid classname for the data handler. Now let's setup the key for the data handler repository to see if |
|
| 928 | - // there is already a ready data handler in the repository. |
|
| 929 | - $this->_current_data_handler = $this->_data_handler_collection->get_by_key( |
|
| 930 | - $this->_data_handler_collection->get_key( |
|
| 931 | - $data_handler_class_name, |
|
| 932 | - $generating_data |
|
| 933 | - ) |
|
| 934 | - ); |
|
| 935 | - if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
| 936 | - // no saved data_handler in the repo so let's set one up and add it to the repo. |
|
| 937 | - try { |
|
| 938 | - $this->_current_data_handler = new $data_handler_class_name($generating_data); |
|
| 939 | - $this->_data_handler_collection->add($this->_current_data_handler, $generating_data); |
|
| 940 | - } catch (Exception $e) { |
|
| 941 | - $this->_error_msg[] = $e->getMessage(); |
|
| 942 | - } |
|
| 943 | - } |
|
| 944 | - } |
|
| 945 | - |
|
| 946 | - |
|
| 947 | - /** |
|
| 948 | - * The queued EE_Message for generation does not save the data used for generation as objects |
|
| 949 | - * because serialization of those objects could be problematic if the data is saved to the db. |
|
| 950 | - * So this method calls the static method on the associated data_handler for the given message_type |
|
| 951 | - * and that preps the data for later instantiation when generating. |
|
| 952 | - * |
|
| 953 | - * @param EE_Message_To_Generate $message_to_generate |
|
| 954 | - * @param bool $preview Indicate whether this is being used for a preview or not. |
|
| 955 | - * @return mixed Prepped data for persisting to the queue. false is returned if unable to prep data. |
|
| 956 | - */ |
|
| 957 | - protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview) |
|
| 958 | - { |
|
| 959 | - /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */ |
|
| 960 | - $data_handler = $message_to_generate->get_data_handler_class_name($preview); |
|
| 961 | - if (! $message_to_generate->valid()) { |
|
| 962 | - return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid. |
|
| 963 | - } |
|
| 964 | - return $data_handler::convert_data_for_persistent_storage($message_to_generate->data()); |
|
| 965 | - } |
|
| 966 | - |
|
| 967 | - |
|
| 968 | - /** |
|
| 969 | - * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue. |
|
| 970 | - * |
|
| 971 | - * @param EE_Message_To_Generate $message_to_generate |
|
| 972 | - * @param bool $test_send Whether this is just a test send or not. Typically used for previews. |
|
| 973 | - * @throws InvalidArgumentException |
|
| 974 | - * @throws InvalidDataTypeException |
|
| 975 | - * @throws InvalidInterfaceException |
|
| 976 | - */ |
|
| 977 | - public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false) |
|
| 978 | - { |
|
| 979 | - // prep data |
|
| 980 | - $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview()); |
|
| 981 | - $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
| 982 | - |
|
| 983 | - $message = $message_to_generate->get_EE_Message(); |
|
| 984 | - $GRP_ID = $request->getRequestParam('GRP_ID', 0); |
|
| 985 | - |
|
| 986 | - $GRP_ID = apply_filters( |
|
| 987 | - 'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID', |
|
| 988 | - $GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(), |
|
| 989 | - $message, |
|
| 990 | - $message_to_generate, |
|
| 991 | - $test_send |
|
| 992 | - ); |
|
| 993 | - |
|
| 994 | - if ($GRP_ID > 0) { |
|
| 995 | - $message->set_GRP_ID($GRP_ID); |
|
| 996 | - } |
|
| 997 | - |
|
| 998 | - if ($data === false) { |
|
| 999 | - $message->set_STS_ID(EEM_Message::status_failed); |
|
| 1000 | - $message->set_error_message( |
|
| 1001 | - esc_html__( |
|
| 1002 | - 'Unable to prepare data for persistence to the database.', |
|
| 1003 | - 'event_espresso' |
|
| 1004 | - ) |
|
| 1005 | - ); |
|
| 1006 | - } else { |
|
| 1007 | - // make sure that the data handler is cached on the message as well |
|
| 1008 | - $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name(); |
|
| 1009 | - } |
|
| 1010 | - |
|
| 1011 | - $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send); |
|
| 1012 | - } |
|
| 747 | + esc_html__( |
|
| 748 | + 'There was a problem generating the content for the field %s: %s', |
|
| 749 | + 'event_espresso' |
|
| 750 | + ), |
|
| 751 | + $field, |
|
| 752 | + $e->getMessage() |
|
| 753 | + ); |
|
| 754 | + $message->set_STS_ID(EEM_Message::status_failed); |
|
| 755 | + } |
|
| 756 | + } |
|
| 757 | + } |
|
| 758 | + |
|
| 759 | + if ($message->STS_ID() === EEM_Message::status_failed) { |
|
| 760 | + $error_msg = esc_html__('There were problems generating this message:', 'event_espresso') |
|
| 761 | + . "\n" |
|
| 762 | + . implode("\n", $error_msg); |
|
| 763 | + $message->set_error_message($error_msg); |
|
| 764 | + } else { |
|
| 765 | + $message->set_STS_ID(EEM_Message::status_idle); |
|
| 766 | + } |
|
| 767 | + return $message; |
|
| 768 | + } |
|
| 769 | + |
|
| 770 | + |
|
| 771 | + /** |
|
| 772 | + * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate |
|
| 773 | + * error message if either is missing. |
|
| 774 | + * |
|
| 775 | + * @return bool true means there were no errors, false means there were errors. |
|
| 776 | + */ |
|
| 777 | + protected function _verify() |
|
| 778 | + { |
|
| 779 | + // reset error message to an empty array. |
|
| 780 | + $this->_error_msg = array(); |
|
| 781 | + $valid = true; |
|
| 782 | + $valid = $valid ? $this->_validate_messenger_and_message_type() : $valid; |
|
| 783 | + $valid = $valid ? $this->_validate_and_setup_data() : $valid; |
|
| 784 | + |
|
| 785 | + // set the verified flag so we know everything has been validated. |
|
| 786 | + $this->_verified = $valid; |
|
| 787 | + |
|
| 788 | + return $valid; |
|
| 789 | + } |
|
| 790 | + |
|
| 791 | + |
|
| 792 | + /** |
|
| 793 | + * This accepts an array and validates that it is an array indexed by context with each value being an array of |
|
| 794 | + * EE_Messages_Addressee objects. |
|
| 795 | + * |
|
| 796 | + * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[] |
|
| 797 | + * @return bool |
|
| 798 | + */ |
|
| 799 | + protected function _valid_addressees($addressees) |
|
| 800 | + { |
|
| 801 | + if (! $addressees || ! is_array($addressees)) { |
|
| 802 | + return false; |
|
| 803 | + } |
|
| 804 | + |
|
| 805 | + foreach ($addressees as $addressee_array) { |
|
| 806 | + foreach ($addressee_array as $addressee) { |
|
| 807 | + if (! $addressee instanceof EE_Messages_Addressee) { |
|
| 808 | + return false; |
|
| 809 | + } |
|
| 810 | + } |
|
| 811 | + } |
|
| 812 | + return true; |
|
| 813 | + } |
|
| 814 | + |
|
| 815 | + |
|
| 816 | + /** |
|
| 817 | + * This validates the messenger, message type, and presences of generation data for the current EE_Message in the |
|
| 818 | + * queue. This process sets error messages if something is wrong. |
|
| 819 | + * |
|
| 820 | + * @return bool true is if there are no errors. false is if there is. |
|
| 821 | + */ |
|
| 822 | + protected function _validate_messenger_and_message_type() |
|
| 823 | + { |
|
| 824 | + |
|
| 825 | + // first are there any existing error messages? If so then return. |
|
| 826 | + if ($this->_error_msg) { |
|
| 827 | + return false; |
|
| 828 | + } |
|
| 829 | + /** @type EE_Message $message */ |
|
| 830 | + $message = $this->_generation_queue->get_message_repository()->current(); |
|
| 831 | + try { |
|
| 832 | + $this->_current_messenger = $message->valid_messenger(true) |
|
| 833 | + ? $message->messenger_object() |
|
| 834 | + : null; |
|
| 835 | + } catch (Exception $e) { |
|
| 836 | + $this->_error_msg[] = $e->getMessage(); |
|
| 837 | + } |
|
| 838 | + try { |
|
| 839 | + $this->_current_message_type = $message->valid_message_type(true) |
|
| 840 | + ? $message->message_type_object() |
|
| 841 | + : null; |
|
| 842 | + } catch (Exception $e) { |
|
| 843 | + $this->_error_msg[] = $e->getMessage(); |
|
| 844 | + } |
|
| 845 | + |
|
| 846 | + /** |
|
| 847 | + * Check if there is any generation data, but only if this is not for a preview. |
|
| 848 | + */ |
|
| 849 | + if (! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
| 850 | + && ( |
|
| 851 | + ! $this->_generation_queue->get_message_repository()->is_preview() |
|
| 852 | + && $this->_generation_queue->get_message_repository()->get_data_handler() |
|
| 853 | + !== 'EE_Messages_Preview_incoming_data' |
|
| 854 | + ) |
|
| 855 | + ) { |
|
| 856 | + $this->_error_msg[] = esc_html__( |
|
| 857 | + 'There is no generation data for this message. Unable to generate.', |
|
| 858 | + 'event_espresso' |
|
| 859 | + ); |
|
| 860 | + } |
|
| 861 | + |
|
| 862 | + return empty($this->_error_msg); |
|
| 863 | + } |
|
| 864 | + |
|
| 865 | + |
|
| 866 | + /** |
|
| 867 | + * This method retrieves the expected data handler for the message type and validates the generation data for that |
|
| 868 | + * data handler. |
|
| 869 | + * |
|
| 870 | + * @return bool true means there are no errors. false means there were errors (and handler did not get setup). |
|
| 871 | + */ |
|
| 872 | + protected function _validate_and_setup_data() |
|
| 873 | + { |
|
| 874 | + |
|
| 875 | + // First, are there any existing error messages? If so, return because if there were errors elsewhere this |
|
| 876 | + // can't be used anyways. |
|
| 877 | + if ($this->_error_msg) { |
|
| 878 | + return false; |
|
| 879 | + } |
|
| 880 | + |
|
| 881 | + $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data(); |
|
| 882 | + |
|
| 883 | + /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/ |
|
| 884 | + $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler() |
|
| 885 | + ? $this->_generation_queue->get_message_repository()->get_data_handler() |
|
| 886 | + : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data'; |
|
| 887 | + |
|
| 888 | + // If this EE_Message is for a preview, then let's switch out to the preview data handler. |
|
| 889 | + if ($this->_generation_queue->get_message_repository()->is_preview()) { |
|
| 890 | + $data_handler_class_name = 'EE_Messages_Preview_incoming_data'; |
|
| 891 | + } |
|
| 892 | + |
|
| 893 | + // First get the class name for the data handler (and also verifies it exists. |
|
| 894 | + if (! class_exists($data_handler_class_name)) { |
|
| 895 | + $this->_error_msg[] = sprintf( |
|
| 896 | + /* Translators: Both placeholders are the names of php classes. */ |
|
| 897 | + esc_html__( |
|
| 898 | + 'The included data handler class name does not match any valid, accessible, "%1$s" classes. Looking for %2$s.', |
|
| 899 | + 'event_espresso' |
|
| 900 | + ), |
|
| 901 | + 'EE_Messages_incoming_data', |
|
| 902 | + $data_handler_class_name |
|
| 903 | + ); |
|
| 904 | + return false; |
|
| 905 | + } |
|
| 906 | + |
|
| 907 | + // convert generation_data for data_handler_instantiation. |
|
| 908 | + $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data); |
|
| 909 | + |
|
| 910 | + // note, this may set error messages as well. |
|
| 911 | + $this->_set_data_handler($generation_data, $data_handler_class_name); |
|
| 912 | + |
|
| 913 | + return empty($this->_error_msg); |
|
| 914 | + } |
|
| 915 | + |
|
| 916 | + |
|
| 917 | + /** |
|
| 918 | + * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and |
|
| 919 | + * adds it to the _data repository. |
|
| 920 | + * |
|
| 921 | + * @param mixed $generating_data This is data expected by the instantiated data handler. |
|
| 922 | + * @param string $data_handler_class_name This is the reference string indicating what data handler is being |
|
| 923 | + * instantiated. |
|
| 924 | + */ |
|
| 925 | + protected function _set_data_handler($generating_data, $data_handler_class_name) |
|
| 926 | + { |
|
| 927 | + // valid classname for the data handler. Now let's setup the key for the data handler repository to see if |
|
| 928 | + // there is already a ready data handler in the repository. |
|
| 929 | + $this->_current_data_handler = $this->_data_handler_collection->get_by_key( |
|
| 930 | + $this->_data_handler_collection->get_key( |
|
| 931 | + $data_handler_class_name, |
|
| 932 | + $generating_data |
|
| 933 | + ) |
|
| 934 | + ); |
|
| 935 | + if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
| 936 | + // no saved data_handler in the repo so let's set one up and add it to the repo. |
|
| 937 | + try { |
|
| 938 | + $this->_current_data_handler = new $data_handler_class_name($generating_data); |
|
| 939 | + $this->_data_handler_collection->add($this->_current_data_handler, $generating_data); |
|
| 940 | + } catch (Exception $e) { |
|
| 941 | + $this->_error_msg[] = $e->getMessage(); |
|
| 942 | + } |
|
| 943 | + } |
|
| 944 | + } |
|
| 945 | + |
|
| 946 | + |
|
| 947 | + /** |
|
| 948 | + * The queued EE_Message for generation does not save the data used for generation as objects |
|
| 949 | + * because serialization of those objects could be problematic if the data is saved to the db. |
|
| 950 | + * So this method calls the static method on the associated data_handler for the given message_type |
|
| 951 | + * and that preps the data for later instantiation when generating. |
|
| 952 | + * |
|
| 953 | + * @param EE_Message_To_Generate $message_to_generate |
|
| 954 | + * @param bool $preview Indicate whether this is being used for a preview or not. |
|
| 955 | + * @return mixed Prepped data for persisting to the queue. false is returned if unable to prep data. |
|
| 956 | + */ |
|
| 957 | + protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview) |
|
| 958 | + { |
|
| 959 | + /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */ |
|
| 960 | + $data_handler = $message_to_generate->get_data_handler_class_name($preview); |
|
| 961 | + if (! $message_to_generate->valid()) { |
|
| 962 | + return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid. |
|
| 963 | + } |
|
| 964 | + return $data_handler::convert_data_for_persistent_storage($message_to_generate->data()); |
|
| 965 | + } |
|
| 966 | + |
|
| 967 | + |
|
| 968 | + /** |
|
| 969 | + * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue. |
|
| 970 | + * |
|
| 971 | + * @param EE_Message_To_Generate $message_to_generate |
|
| 972 | + * @param bool $test_send Whether this is just a test send or not. Typically used for previews. |
|
| 973 | + * @throws InvalidArgumentException |
|
| 974 | + * @throws InvalidDataTypeException |
|
| 975 | + * @throws InvalidInterfaceException |
|
| 976 | + */ |
|
| 977 | + public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false) |
|
| 978 | + { |
|
| 979 | + // prep data |
|
| 980 | + $data = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview()); |
|
| 981 | + $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface'); |
|
| 982 | + |
|
| 983 | + $message = $message_to_generate->get_EE_Message(); |
|
| 984 | + $GRP_ID = $request->getRequestParam('GRP_ID', 0); |
|
| 985 | + |
|
| 986 | + $GRP_ID = apply_filters( |
|
| 987 | + 'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID', |
|
| 988 | + $GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(), |
|
| 989 | + $message, |
|
| 990 | + $message_to_generate, |
|
| 991 | + $test_send |
|
| 992 | + ); |
|
| 993 | + |
|
| 994 | + if ($GRP_ID > 0) { |
|
| 995 | + $message->set_GRP_ID($GRP_ID); |
|
| 996 | + } |
|
| 997 | + |
|
| 998 | + if ($data === false) { |
|
| 999 | + $message->set_STS_ID(EEM_Message::status_failed); |
|
| 1000 | + $message->set_error_message( |
|
| 1001 | + esc_html__( |
|
| 1002 | + 'Unable to prepare data for persistence to the database.', |
|
| 1003 | + 'event_espresso' |
|
| 1004 | + ) |
|
| 1005 | + ); |
|
| 1006 | + } else { |
|
| 1007 | + // make sure that the data handler is cached on the message as well |
|
| 1008 | + $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name(); |
|
| 1009 | + } |
|
| 1010 | + |
|
| 1011 | + $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send); |
|
| 1012 | + } |
|
| 1013 | 1013 | } |
@@ -267,7 +267,7 @@ discard block |
||
| 267 | 267 | { |
| 268 | 268 | // double check verification has run and that everything is ready to work with (saves us having to validate |
| 269 | 269 | // everything again). |
| 270 | - if (! $this->_verified) { |
|
| 270 | + if ( ! $this->_verified) { |
|
| 271 | 271 | return false; // get out because we don't have a valid setup to work with. |
| 272 | 272 | } |
| 273 | 273 | |
@@ -284,7 +284,7 @@ discard block |
||
| 284 | 284 | |
| 285 | 285 | |
| 286 | 286 | // if no addressees then get out because there is nothing to generation (possible bad data). |
| 287 | - if (! $this->_valid_addressees($addressees)) { |
|
| 287 | + if ( ! $this->_valid_addressees($addressees)) { |
|
| 288 | 288 | do_action( |
| 289 | 289 | 'AHEE__EE_Messages_Generator___generate__invalid_addressees', |
| 290 | 290 | $this->_generation_queue->get_message_repository()->current(), |
@@ -306,7 +306,7 @@ discard block |
||
| 306 | 306 | $message_template_group = $this->_get_message_template_group(); |
| 307 | 307 | |
| 308 | 308 | // in the unlikely event there is no EE_Message_Template_Group available, get out! |
| 309 | - if (! $message_template_group instanceof EE_Message_Template_Group) { |
|
| 309 | + if ( ! $message_template_group instanceof EE_Message_Template_Group) { |
|
| 310 | 310 | $this->_error_msg[] = esc_html__( |
| 311 | 311 | 'Unable to get the Message Templates for the Message being generated. No message template group accessible.', |
| 312 | 312 | 'event_espresso' |
@@ -417,7 +417,7 @@ discard block |
||
| 417 | 417 | // attempt to retrieve from repo first |
| 418 | 418 | $message_template_group = $this->_template_collection->get_by_ID($GRP_ID); |
| 419 | 419 | if ($message_template_group instanceof EE_Message_Template_Group) { |
| 420 | - return $message_template_group; // got it! |
|
| 420 | + return $message_template_group; // got it! |
|
| 421 | 421 | } |
| 422 | 422 | |
| 423 | 423 | // nope don't have it yet. Get from DB then add to repo if its not here, then that means the current GRP_ID |
@@ -446,7 +446,7 @@ discard block |
||
| 446 | 446 | protected function _queue_shares_same_message_template_group_for_events(array $event_ids) |
| 447 | 447 | { |
| 448 | 448 | foreach ($this->_current_data_handler->events as $event) { |
| 449 | - $event_ids[ $event['ID'] ] = $event['ID']; |
|
| 449 | + $event_ids[$event['ID']] = $event['ID']; |
|
| 450 | 450 | } |
| 451 | 451 | $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count( |
| 452 | 452 | array( |
@@ -522,7 +522,7 @@ discard block |
||
| 522 | 522 | ); |
| 523 | 523 | |
| 524 | 524 | // if we don't have a group lets hit the db. |
| 525 | - if (! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 525 | + if ( ! $global_message_template_group instanceof EE_Message_Template_Group) { |
|
| 526 | 526 | $global_message_template_group = EEM_Message_Template_Group::instance()->get_one( |
| 527 | 527 | array( |
| 528 | 528 | array( |
@@ -554,7 +554,7 @@ discard block |
||
| 554 | 554 | { |
| 555 | 555 | $event_ids = array(); |
| 556 | 556 | foreach ($this->_current_data_handler->events as $event) { |
| 557 | - $event_ids[ $event['ID'] ] = $event['ID']; |
|
| 557 | + $event_ids[$event['ID']] = $event['ID']; |
|
| 558 | 558 | } |
| 559 | 559 | return $event_ids; |
| 560 | 560 | } |
@@ -583,10 +583,10 @@ discard block |
||
| 583 | 583 | $context_templates = $message_template_group->context_templates(); |
| 584 | 584 | foreach ($context_templates as $context => $template_fields) { |
| 585 | 585 | foreach ($template_fields as $template_field => $template_obj) { |
| 586 | - if (! $template_obj instanceof EE_Message_Template) { |
|
| 586 | + if ( ! $template_obj instanceof EE_Message_Template) { |
|
| 587 | 587 | continue; |
| 588 | 588 | } |
| 589 | - $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content'); |
|
| 589 | + $templates[$template_field][$context] = $template_obj->get('MTP_content'); |
|
| 590 | 590 | } |
| 591 | 591 | } |
| 592 | 592 | return $templates; |
@@ -617,7 +617,7 @@ discard block |
||
| 617 | 617 | { |
| 618 | 618 | |
| 619 | 619 | // if templates are empty then get out because we can't generate anything. |
| 620 | - if (! $templates) { |
|
| 620 | + if ( ! $templates) { |
|
| 621 | 621 | $this->_error_msg[] = esc_html__( |
| 622 | 622 | 'Unable to assemble messages because there are no templates retrieved for generating the messages with', |
| 623 | 623 | 'event_espresso' |
@@ -704,10 +704,10 @@ discard block |
||
| 704 | 704 | $m_shortcodes = $this->_current_messenger->get_valid_shortcodes(); |
| 705 | 705 | |
| 706 | 706 | // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing |
| 707 | - if (! $this->_generation_queue->get_message_repository()->is_preview() |
|
| 707 | + if ( ! $this->_generation_queue->get_message_repository()->is_preview() |
|
| 708 | 708 | && ( |
| 709 | 709 | ( |
| 710 | - empty($templates['to'][ $context ]) |
|
| 710 | + empty($templates['to'][$context]) |
|
| 711 | 711 | && ! $this->_current_messenger->allow_empty_to_field() |
| 712 | 712 | ) |
| 713 | 713 | || ! $message_template_group->is_context_active($context) |
@@ -721,15 +721,15 @@ discard block |
||
| 721 | 721 | foreach ($templates as $field => $field_context) { |
| 722 | 722 | $error_msg = array(); |
| 723 | 723 | // let's setup the valid shortcodes for the incoming context. |
| 724 | - $valid_shortcodes = $mt_shortcodes[ $context ]; |
|
| 724 | + $valid_shortcodes = $mt_shortcodes[$context]; |
|
| 725 | 725 | // merge in valid shortcodes for the field. |
| 726 | - $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes; |
|
| 727 | - if (isset($templates[ $field ][ $context ])) { |
|
| 726 | + $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes; |
|
| 727 | + if (isset($templates[$field][$context])) { |
|
| 728 | 728 | // prefix field. |
| 729 | - $column_name = 'MSG_' . $field; |
|
| 729 | + $column_name = 'MSG_'.$field; |
|
| 730 | 730 | try { |
| 731 | 731 | $content = $this->_shortcode_parser->parse_message_template( |
| 732 | - $templates[ $field ][ $context ], |
|
| 732 | + $templates[$field][$context], |
|
| 733 | 733 | $recipient, |
| 734 | 734 | $shortcodes, |
| 735 | 735 | $this->_current_message_type, |
@@ -798,13 +798,13 @@ discard block |
||
| 798 | 798 | */ |
| 799 | 799 | protected function _valid_addressees($addressees) |
| 800 | 800 | { |
| 801 | - if (! $addressees || ! is_array($addressees)) { |
|
| 801 | + if ( ! $addressees || ! is_array($addressees)) { |
|
| 802 | 802 | return false; |
| 803 | 803 | } |
| 804 | 804 | |
| 805 | 805 | foreach ($addressees as $addressee_array) { |
| 806 | 806 | foreach ($addressee_array as $addressee) { |
| 807 | - if (! $addressee instanceof EE_Messages_Addressee) { |
|
| 807 | + if ( ! $addressee instanceof EE_Messages_Addressee) { |
|
| 808 | 808 | return false; |
| 809 | 809 | } |
| 810 | 810 | } |
@@ -846,7 +846,7 @@ discard block |
||
| 846 | 846 | /** |
| 847 | 847 | * Check if there is any generation data, but only if this is not for a preview. |
| 848 | 848 | */ |
| 849 | - if (! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
| 849 | + if ( ! $this->_generation_queue->get_message_repository()->get_generation_data() |
|
| 850 | 850 | && ( |
| 851 | 851 | ! $this->_generation_queue->get_message_repository()->is_preview() |
| 852 | 852 | && $this->_generation_queue->get_message_repository()->get_data_handler() |
@@ -883,7 +883,7 @@ discard block |
||
| 883 | 883 | /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually*/ |
| 884 | 884 | $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler() |
| 885 | 885 | ? $this->_generation_queue->get_message_repository()->get_data_handler() |
| 886 | - : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data'; |
|
| 886 | + : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data'; |
|
| 887 | 887 | |
| 888 | 888 | // If this EE_Message is for a preview, then let's switch out to the preview data handler. |
| 889 | 889 | if ($this->_generation_queue->get_message_repository()->is_preview()) { |
@@ -891,7 +891,7 @@ discard block |
||
| 891 | 891 | } |
| 892 | 892 | |
| 893 | 893 | // First get the class name for the data handler (and also verifies it exists. |
| 894 | - if (! class_exists($data_handler_class_name)) { |
|
| 894 | + if ( ! class_exists($data_handler_class_name)) { |
|
| 895 | 895 | $this->_error_msg[] = sprintf( |
| 896 | 896 | /* Translators: Both placeholders are the names of php classes. */ |
| 897 | 897 | esc_html__( |
@@ -932,7 +932,7 @@ discard block |
||
| 932 | 932 | $generating_data |
| 933 | 933 | ) |
| 934 | 934 | ); |
| 935 | - if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
| 935 | + if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) { |
|
| 936 | 936 | // no saved data_handler in the repo so let's set one up and add it to the repo. |
| 937 | 937 | try { |
| 938 | 938 | $this->_current_data_handler = new $data_handler_class_name($generating_data); |
@@ -958,7 +958,7 @@ discard block |
||
| 958 | 958 | { |
| 959 | 959 | /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */ |
| 960 | 960 | $data_handler = $message_to_generate->get_data_handler_class_name($preview); |
| 961 | - if (! $message_to_generate->valid()) { |
|
| 961 | + if ( ! $message_to_generate->valid()) { |
|
| 962 | 962 | return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid. |
| 963 | 963 | } |
| 964 | 964 | return $data_handler::convert_data_for_persistent_storage($message_to_generate->data()); |
@@ -14,1323 +14,1323 @@ |
||
| 14 | 14 | class Extend_Registration_Form_Admin_Page extends Registration_Form_Admin_Page |
| 15 | 15 | { |
| 16 | 16 | |
| 17 | - /** |
|
| 18 | - * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object. |
|
| 19 | - */ |
|
| 20 | - public function __construct($routing = true) |
|
| 21 | - { |
|
| 22 | - define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form' . DS); |
|
| 23 | - define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets' . DS); |
|
| 24 | - define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/'); |
|
| 25 | - define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates' . DS); |
|
| 26 | - define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/'); |
|
| 27 | - parent::__construct($routing); |
|
| 28 | - } |
|
| 29 | - |
|
| 30 | - |
|
| 31 | - /** |
|
| 32 | - * @return void |
|
| 33 | - */ |
|
| 34 | - protected function _extend_page_config() |
|
| 35 | - { |
|
| 36 | - $this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN; |
|
| 37 | - $qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID']) |
|
| 38 | - ? $this->_req_data['QST_ID'] : 0; |
|
| 39 | - $qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID']) |
|
| 40 | - ? $this->_req_data['QSG_ID'] : 0; |
|
| 41 | - |
|
| 42 | - $new_page_routes = array( |
|
| 43 | - 'question_groups' => array( |
|
| 44 | - 'func' => '_question_groups_overview_list_table', |
|
| 45 | - 'capability' => 'ee_read_question_groups', |
|
| 46 | - ), |
|
| 47 | - 'add_question' => array( |
|
| 48 | - 'func' => '_edit_question', |
|
| 49 | - 'capability' => 'ee_edit_questions', |
|
| 50 | - ), |
|
| 51 | - 'insert_question' => array( |
|
| 52 | - 'func' => '_insert_or_update_question', |
|
| 53 | - 'args' => array('new_question' => true), |
|
| 54 | - 'capability' => 'ee_edit_questions', |
|
| 55 | - 'noheader' => true, |
|
| 56 | - ), |
|
| 57 | - 'duplicate_question' => array( |
|
| 58 | - 'func' => '_duplicate_question', |
|
| 59 | - 'capability' => 'ee_edit_questions', |
|
| 60 | - 'noheader' => true, |
|
| 61 | - ), |
|
| 62 | - 'trash_question' => array( |
|
| 63 | - 'func' => '_trash_question', |
|
| 64 | - 'capability' => 'ee_delete_question', |
|
| 65 | - 'obj_id' => $qst_id, |
|
| 66 | - 'noheader' => true, |
|
| 67 | - ), |
|
| 68 | - |
|
| 69 | - 'restore_question' => array( |
|
| 70 | - 'func' => '_trash_or_restore_questions', |
|
| 71 | - 'capability' => 'ee_delete_question', |
|
| 72 | - 'obj_id' => $qst_id, |
|
| 73 | - 'args' => array('trash' => false), |
|
| 74 | - 'noheader' => true, |
|
| 75 | - ), |
|
| 76 | - |
|
| 77 | - 'delete_question' => array( |
|
| 78 | - 'func' => '_delete_question', |
|
| 79 | - 'capability' => 'ee_delete_question', |
|
| 80 | - 'obj_id' => $qst_id, |
|
| 81 | - 'noheader' => true, |
|
| 82 | - ), |
|
| 83 | - |
|
| 84 | - 'trash_questions' => array( |
|
| 85 | - 'func' => '_trash_or_restore_questions', |
|
| 86 | - 'capability' => 'ee_delete_questions', |
|
| 87 | - 'args' => array('trash' => true), |
|
| 88 | - 'noheader' => true, |
|
| 89 | - ), |
|
| 90 | - |
|
| 91 | - 'restore_questions' => array( |
|
| 92 | - 'func' => '_trash_or_restore_questions', |
|
| 93 | - 'capability' => 'ee_delete_questions', |
|
| 94 | - 'args' => array('trash' => false), |
|
| 95 | - 'noheader' => true, |
|
| 96 | - ), |
|
| 97 | - |
|
| 98 | - 'delete_questions' => array( |
|
| 99 | - 'func' => '_delete_questions', |
|
| 100 | - 'args' => array(), |
|
| 101 | - 'capability' => 'ee_delete_questions', |
|
| 102 | - 'noheader' => true, |
|
| 103 | - ), |
|
| 104 | - |
|
| 105 | - 'add_question_group' => array( |
|
| 106 | - 'func' => '_edit_question_group', |
|
| 107 | - 'capability' => 'ee_edit_question_groups', |
|
| 108 | - ), |
|
| 109 | - |
|
| 110 | - 'edit_question_group' => array( |
|
| 111 | - 'func' => '_edit_question_group', |
|
| 112 | - 'capability' => 'ee_edit_question_group', |
|
| 113 | - 'obj_id' => $qsg_id, |
|
| 114 | - 'args' => array('edit'), |
|
| 115 | - ), |
|
| 116 | - |
|
| 117 | - 'delete_question_groups' => array( |
|
| 118 | - 'func' => '_delete_question_groups', |
|
| 119 | - 'capability' => 'ee_delete_question_groups', |
|
| 120 | - 'noheader' => true, |
|
| 121 | - ), |
|
| 122 | - |
|
| 123 | - 'delete_question_group' => array( |
|
| 124 | - 'func' => '_delete_question_groups', |
|
| 125 | - 'capability' => 'ee_delete_question_group', |
|
| 126 | - 'obj_id' => $qsg_id, |
|
| 127 | - 'noheader' => true, |
|
| 128 | - ), |
|
| 129 | - |
|
| 130 | - 'trash_question_group' => array( |
|
| 131 | - 'func' => '_trash_or_restore_question_groups', |
|
| 132 | - 'args' => array('trash' => true), |
|
| 133 | - 'capability' => 'ee_delete_question_group', |
|
| 134 | - 'obj_id' => $qsg_id, |
|
| 135 | - 'noheader' => true, |
|
| 136 | - ), |
|
| 137 | - |
|
| 138 | - 'restore_question_group' => array( |
|
| 139 | - 'func' => '_trash_or_restore_question_groups', |
|
| 140 | - 'args' => array('trash' => false), |
|
| 141 | - 'capability' => 'ee_delete_question_group', |
|
| 142 | - 'obj_id' => $qsg_id, |
|
| 143 | - 'noheader' => true, |
|
| 144 | - ), |
|
| 145 | - |
|
| 146 | - 'insert_question_group' => array( |
|
| 147 | - 'func' => '_insert_or_update_question_group', |
|
| 148 | - 'args' => array('new_question_group' => true), |
|
| 149 | - 'capability' => 'ee_edit_question_groups', |
|
| 150 | - 'noheader' => true, |
|
| 151 | - ), |
|
| 152 | - |
|
| 153 | - 'update_question_group' => array( |
|
| 154 | - 'func' => '_insert_or_update_question_group', |
|
| 155 | - 'args' => array('new_question_group' => false), |
|
| 156 | - 'capability' => 'ee_edit_question_group', |
|
| 157 | - 'obj_id' => $qsg_id, |
|
| 158 | - 'noheader' => true, |
|
| 159 | - ), |
|
| 160 | - |
|
| 161 | - 'trash_question_groups' => array( |
|
| 162 | - 'func' => '_trash_or_restore_question_groups', |
|
| 163 | - 'args' => array('trash' => true), |
|
| 164 | - 'capability' => 'ee_delete_question_groups', |
|
| 165 | - 'noheader' => array('trash' => false), |
|
| 166 | - ), |
|
| 167 | - |
|
| 168 | - 'restore_question_groups' => array( |
|
| 169 | - 'func' => '_trash_or_restore_question_groups', |
|
| 170 | - 'args' => array('trash' => false), |
|
| 171 | - 'capability' => 'ee_delete_question_groups', |
|
| 172 | - 'noheader' => true, |
|
| 173 | - ), |
|
| 174 | - |
|
| 175 | - |
|
| 176 | - 'espresso_update_question_group_order' => array( |
|
| 177 | - 'func' => 'update_question_group_order', |
|
| 178 | - 'capability' => 'ee_edit_question_groups', |
|
| 179 | - 'noheader' => true, |
|
| 180 | - ), |
|
| 181 | - |
|
| 182 | - 'view_reg_form_settings' => array( |
|
| 183 | - 'func' => '_reg_form_settings', |
|
| 184 | - 'capability' => 'manage_options', |
|
| 185 | - ), |
|
| 186 | - |
|
| 187 | - 'update_reg_form_settings' => array( |
|
| 188 | - 'func' => '_update_reg_form_settings', |
|
| 189 | - 'capability' => 'manage_options', |
|
| 190 | - 'noheader' => true, |
|
| 191 | - ), |
|
| 192 | - ); |
|
| 193 | - $this->_page_routes = array_merge($this->_page_routes, $new_page_routes); |
|
| 194 | - |
|
| 195 | - $new_page_config = array( |
|
| 196 | - |
|
| 197 | - 'question_groups' => array( |
|
| 198 | - 'nav' => array( |
|
| 199 | - 'label' => esc_html__('Question Groups', 'event_espresso'), |
|
| 200 | - 'order' => 20, |
|
| 201 | - ), |
|
| 202 | - 'list_table' => 'Registration_Form_Question_Groups_Admin_List_Table', |
|
| 203 | - 'help_tabs' => array( |
|
| 204 | - 'registration_form_question_groups_help_tab' => array( |
|
| 205 | - 'title' => esc_html__('Question Groups', 'event_espresso'), |
|
| 206 | - 'filename' => 'registration_form_question_groups', |
|
| 207 | - ), |
|
| 208 | - 'registration_form_question_groups_table_column_headings_help_tab' => array( |
|
| 209 | - 'title' => esc_html__('Question Groups Table Column Headings', 'event_espresso'), |
|
| 210 | - 'filename' => 'registration_form_question_groups_table_column_headings', |
|
| 211 | - ), |
|
| 212 | - 'registration_form_question_groups_views_bulk_actions_search_help_tab' => array( |
|
| 213 | - 'title' => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'), |
|
| 214 | - 'filename' => 'registration_form_question_groups_views_bulk_actions_search', |
|
| 215 | - ), |
|
| 216 | - ), |
|
| 217 | - 'help_tour' => array('Registration_Form_Question_Groups_Help_Tour'), |
|
| 218 | - 'metaboxes' => $this->_default_espresso_metaboxes, |
|
| 219 | - 'require_nonce' => false, |
|
| 220 | - 'qtips' => array( |
|
| 221 | - 'EE_Registration_Form_Tips', |
|
| 222 | - ), |
|
| 223 | - ), |
|
| 224 | - |
|
| 225 | - 'add_question' => array( |
|
| 226 | - 'nav' => array( |
|
| 227 | - 'label' => esc_html__('Add Question', 'event_espresso'), |
|
| 228 | - 'order' => 5, |
|
| 229 | - 'persistent' => false, |
|
| 230 | - ), |
|
| 231 | - 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 232 | - 'help_tabs' => array( |
|
| 233 | - 'registration_form_add_question_help_tab' => array( |
|
| 234 | - 'title' => esc_html__('Add Question', 'event_espresso'), |
|
| 235 | - 'filename' => 'registration_form_add_question', |
|
| 236 | - ), |
|
| 237 | - ), |
|
| 238 | - 'help_tour' => array('Registration_Form_Add_Question_Help_Tour'), |
|
| 239 | - 'require_nonce' => false, |
|
| 240 | - ), |
|
| 241 | - |
|
| 242 | - 'add_question_group' => array( |
|
| 243 | - 'nav' => array( |
|
| 244 | - 'label' => esc_html__('Add Question Group', 'event_espresso'), |
|
| 245 | - 'order' => 5, |
|
| 246 | - 'persistent' => false, |
|
| 247 | - ), |
|
| 248 | - 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 249 | - 'help_tabs' => array( |
|
| 250 | - 'registration_form_add_question_group_help_tab' => array( |
|
| 251 | - 'title' => esc_html__('Add Question Group', 'event_espresso'), |
|
| 252 | - 'filename' => 'registration_form_add_question_group', |
|
| 253 | - ), |
|
| 254 | - ), |
|
| 255 | - 'help_tour' => array('Registration_Form_Add_Question_Group_Help_Tour'), |
|
| 256 | - 'require_nonce' => false, |
|
| 257 | - ), |
|
| 258 | - |
|
| 259 | - 'edit_question_group' => array( |
|
| 260 | - 'nav' => array( |
|
| 261 | - 'label' => esc_html__('Edit Question Group', 'event_espresso'), |
|
| 262 | - 'order' => 5, |
|
| 263 | - 'persistent' => false, |
|
| 264 | - 'url' => isset($this->_req_data['question_group_id']) ? add_query_arg( |
|
| 265 | - array('question_group_id' => $this->_req_data['question_group_id']), |
|
| 266 | - $this->_current_page_view_url |
|
| 267 | - ) : $this->_admin_base_url, |
|
| 268 | - ), |
|
| 269 | - 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 270 | - 'help_tabs' => array( |
|
| 271 | - 'registration_form_edit_question_group_help_tab' => array( |
|
| 272 | - 'title' => esc_html__('Edit Question Group', 'event_espresso'), |
|
| 273 | - 'filename' => 'registration_form_edit_question_group', |
|
| 274 | - ), |
|
| 275 | - ), |
|
| 276 | - 'help_tour' => array('Registration_Form_Edit_Question_Group_Help_Tour'), |
|
| 277 | - 'require_nonce' => false, |
|
| 278 | - ), |
|
| 279 | - |
|
| 280 | - 'view_reg_form_settings' => array( |
|
| 281 | - 'nav' => array( |
|
| 282 | - 'label' => esc_html__('Reg Form Settings', 'event_espresso'), |
|
| 283 | - 'order' => 40, |
|
| 284 | - ), |
|
| 285 | - 'labels' => array( |
|
| 286 | - 'publishbox' => esc_html__('Update Settings', 'event_espresso'), |
|
| 287 | - ), |
|
| 288 | - 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 289 | - 'help_tabs' => array( |
|
| 290 | - 'registration_form_reg_form_settings_help_tab' => array( |
|
| 291 | - 'title' => esc_html__('Registration Form Settings', 'event_espresso'), |
|
| 292 | - 'filename' => 'registration_form_reg_form_settings', |
|
| 293 | - ), |
|
| 294 | - ), |
|
| 295 | - 'help_tour' => array('Registration_Form_Settings_Help_Tour'), |
|
| 296 | - 'require_nonce' => false, |
|
| 297 | - ), |
|
| 298 | - |
|
| 299 | - ); |
|
| 300 | - $this->_page_config = array_merge($this->_page_config, $new_page_config); |
|
| 301 | - |
|
| 302 | - // change the list table we're going to use so it's the NEW list table! |
|
| 303 | - $this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table'; |
|
| 304 | - |
|
| 305 | - |
|
| 306 | - // additional labels |
|
| 307 | - $new_labels = array( |
|
| 308 | - 'add_question' => esc_html__('Add New Question', 'event_espresso'), |
|
| 309 | - 'delete_question' => esc_html__('Delete Question', 'event_espresso'), |
|
| 310 | - 'add_question_group' => esc_html__('Add New Question Group', 'event_espresso'), |
|
| 311 | - 'edit_question_group' => esc_html__('Edit Question Group', 'event_espresso'), |
|
| 312 | - 'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'), |
|
| 313 | - ); |
|
| 314 | - $this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels); |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - |
|
| 318 | - /** |
|
| 319 | - * @return void |
|
| 320 | - */ |
|
| 321 | - protected function _ajax_hooks() |
|
| 322 | - { |
|
| 323 | - add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order')); |
|
| 324 | - } |
|
| 325 | - |
|
| 326 | - |
|
| 327 | - /** |
|
| 328 | - * @return void |
|
| 329 | - */ |
|
| 330 | - public function load_scripts_styles_question_groups() |
|
| 331 | - { |
|
| 332 | - wp_enqueue_script('espresso_ajax_table_sorting'); |
|
| 333 | - } |
|
| 334 | - |
|
| 335 | - |
|
| 336 | - /** |
|
| 337 | - * @return void |
|
| 338 | - */ |
|
| 339 | - public function load_scripts_styles_add_question_group() |
|
| 340 | - { |
|
| 341 | - $this->load_scripts_styles_forms(); |
|
| 342 | - $this->load_sortable_question_script(); |
|
| 343 | - } |
|
| 344 | - |
|
| 345 | - |
|
| 346 | - /** |
|
| 347 | - * @return void |
|
| 348 | - */ |
|
| 349 | - public function load_scripts_styles_edit_question_group() |
|
| 350 | - { |
|
| 351 | - $this->load_scripts_styles_forms(); |
|
| 352 | - $this->load_sortable_question_script(); |
|
| 353 | - } |
|
| 354 | - |
|
| 355 | - |
|
| 356 | - /** |
|
| 357 | - * registers and enqueues script for questions |
|
| 358 | - * |
|
| 359 | - * @return void |
|
| 360 | - */ |
|
| 361 | - public function load_sortable_question_script() |
|
| 362 | - { |
|
| 363 | - wp_register_script( |
|
| 364 | - 'ee-question-sortable', |
|
| 365 | - REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js', |
|
| 366 | - array('jquery-ui-sortable'), |
|
| 367 | - EVENT_ESPRESSO_VERSION, |
|
| 368 | - true |
|
| 369 | - ); |
|
| 370 | - wp_enqueue_script('ee-question-sortable'); |
|
| 371 | - } |
|
| 372 | - |
|
| 373 | - |
|
| 374 | - /** |
|
| 375 | - * @return void |
|
| 376 | - */ |
|
| 377 | - protected function _set_list_table_views_default() |
|
| 378 | - { |
|
| 379 | - $this->_views = array( |
|
| 380 | - 'all' => array( |
|
| 381 | - 'slug' => 'all', |
|
| 382 | - 'label' => esc_html__('View All Questions', 'event_espresso'), |
|
| 383 | - 'count' => 0, |
|
| 384 | - 'bulk_action' => array( |
|
| 385 | - 'trash_questions' => esc_html__('Trash', 'event_espresso'), |
|
| 386 | - ), |
|
| 387 | - ), |
|
| 388 | - ); |
|
| 389 | - |
|
| 390 | - if (EE_Registry::instance()->CAP->current_user_can( |
|
| 391 | - 'ee_delete_questions', |
|
| 392 | - 'espresso_registration_form_trash_questions' |
|
| 393 | - ) |
|
| 394 | - ) { |
|
| 395 | - $this->_views['trash'] = array( |
|
| 396 | - 'slug' => 'trash', |
|
| 397 | - 'label' => esc_html__('Trash', 'event_espresso'), |
|
| 398 | - 'count' => 0, |
|
| 399 | - 'bulk_action' => array( |
|
| 400 | - 'delete_questions' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 401 | - 'restore_questions' => esc_html__('Restore', 'event_espresso'), |
|
| 402 | - ), |
|
| 403 | - ); |
|
| 404 | - } |
|
| 405 | - } |
|
| 406 | - |
|
| 407 | - |
|
| 408 | - /** |
|
| 409 | - * @return void |
|
| 410 | - */ |
|
| 411 | - protected function _set_list_table_views_question_groups() |
|
| 412 | - { |
|
| 413 | - $this->_views = array( |
|
| 414 | - 'all' => array( |
|
| 415 | - 'slug' => 'all', |
|
| 416 | - 'label' => esc_html__('All', 'event_espresso'), |
|
| 417 | - 'count' => 0, |
|
| 418 | - 'bulk_action' => array( |
|
| 419 | - 'trash_question_groups' => esc_html__('Trash', 'event_espresso'), |
|
| 420 | - ), |
|
| 421 | - ), |
|
| 422 | - ); |
|
| 423 | - |
|
| 424 | - if (EE_Registry::instance()->CAP->current_user_can( |
|
| 425 | - 'ee_delete_question_groups', |
|
| 426 | - 'espresso_registration_form_trash_question_groups' |
|
| 427 | - ) |
|
| 428 | - ) { |
|
| 429 | - $this->_views['trash'] = array( |
|
| 430 | - 'slug' => 'trash', |
|
| 431 | - 'label' => esc_html__('Trash', 'event_espresso'), |
|
| 432 | - 'count' => 0, |
|
| 433 | - 'bulk_action' => array( |
|
| 434 | - 'delete_question_groups' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 435 | - 'restore_question_groups' => esc_html__('Restore', 'event_espresso'), |
|
| 436 | - ), |
|
| 437 | - ); |
|
| 438 | - } |
|
| 439 | - } |
|
| 440 | - |
|
| 441 | - |
|
| 442 | - /** |
|
| 443 | - * @return void |
|
| 444 | - * @throws EE_Error |
|
| 445 | - * @throws InvalidArgumentException |
|
| 446 | - * @throws InvalidDataTypeException |
|
| 447 | - * @throws InvalidInterfaceException |
|
| 448 | - */ |
|
| 449 | - protected function _questions_overview_list_table() |
|
| 450 | - { |
|
| 451 | - $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 452 | - 'add_question', |
|
| 453 | - 'add_question', |
|
| 454 | - array(), |
|
| 455 | - 'add-new-h2' |
|
| 456 | - ); |
|
| 457 | - parent::_questions_overview_list_table(); |
|
| 458 | - } |
|
| 459 | - |
|
| 460 | - |
|
| 461 | - /** |
|
| 462 | - * @return void |
|
| 463 | - * @throws DomainException |
|
| 464 | - * @throws EE_Error |
|
| 465 | - * @throws InvalidArgumentException |
|
| 466 | - * @throws InvalidDataTypeException |
|
| 467 | - * @throws InvalidInterfaceException |
|
| 468 | - */ |
|
| 469 | - protected function _question_groups_overview_list_table() |
|
| 470 | - { |
|
| 471 | - $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso'); |
|
| 472 | - $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 473 | - 'add_question_group', |
|
| 474 | - 'add_question_group', |
|
| 475 | - array(), |
|
| 476 | - 'add-new-h2' |
|
| 477 | - ); |
|
| 478 | - $this->display_admin_list_table_page_with_sidebar(); |
|
| 479 | - } |
|
| 480 | - |
|
| 481 | - |
|
| 482 | - /** |
|
| 483 | - * @return void |
|
| 484 | - * @throws EE_Error |
|
| 485 | - * @throws InvalidArgumentException |
|
| 486 | - * @throws InvalidDataTypeException |
|
| 487 | - * @throws InvalidInterfaceException |
|
| 488 | - */ |
|
| 489 | - protected function _delete_question() |
|
| 490 | - { |
|
| 491 | - $success = $this->_delete_items($this->_question_model); |
|
| 492 | - $this->_redirect_after_action( |
|
| 493 | - $success, |
|
| 494 | - $this->_question_model->item_name($success), |
|
| 495 | - 'deleted', |
|
| 496 | - array('action' => 'default', 'status' => 'all') |
|
| 497 | - ); |
|
| 498 | - } |
|
| 499 | - |
|
| 500 | - |
|
| 501 | - /** |
|
| 502 | - * @return void |
|
| 503 | - * @throws EE_Error |
|
| 504 | - * @throws InvalidArgumentException |
|
| 505 | - * @throws InvalidDataTypeException |
|
| 506 | - * @throws InvalidInterfaceException |
|
| 507 | - */ |
|
| 508 | - protected function _delete_questions() |
|
| 509 | - { |
|
| 510 | - $success = $this->_delete_items($this->_question_model); |
|
| 511 | - $this->_redirect_after_action( |
|
| 512 | - $success, |
|
| 513 | - $this->_question_model->item_name($success), |
|
| 514 | - 'deleted permanently', |
|
| 515 | - array('action' => 'default', 'status' => 'trash') |
|
| 516 | - ); |
|
| 517 | - } |
|
| 518 | - |
|
| 519 | - |
|
| 520 | - /** |
|
| 521 | - * Performs the deletion of a single or multiple questions or question groups. |
|
| 522 | - * |
|
| 523 | - * @param EEM_Soft_Delete_Base $model |
|
| 524 | - * @return int number of items deleted permanently |
|
| 525 | - * @throws EE_Error |
|
| 526 | - * @throws InvalidArgumentException |
|
| 527 | - * @throws InvalidDataTypeException |
|
| 528 | - * @throws InvalidInterfaceException |
|
| 529 | - */ |
|
| 530 | - private function _delete_items(EEM_Soft_Delete_Base $model) |
|
| 531 | - { |
|
| 532 | - $success = 0; |
|
| 533 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 534 | - if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 535 | - // if array has more than one element than success message should be plural |
|
| 536 | - $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1; |
|
| 537 | - // cycle thru bulk action checkboxes |
|
| 538 | - while (list($ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 539 | - if (! $this->_delete_item($ID, $model)) { |
|
| 540 | - $success = 0; |
|
| 541 | - } |
|
| 542 | - } |
|
| 543 | - } elseif (! empty($this->_req_data['QSG_ID'])) { |
|
| 544 | - $success = $this->_delete_item($this->_req_data['QSG_ID'], $model); |
|
| 545 | - } elseif (! empty($this->_req_data['QST_ID'])) { |
|
| 546 | - $success = $this->_delete_item($this->_req_data['QST_ID'], $model); |
|
| 547 | - } else { |
|
| 548 | - EE_Error::add_error( |
|
| 549 | - sprintf( |
|
| 550 | - esc_html__( |
|
| 551 | - "No Questions or Question Groups were selected for deleting. This error usually shows when you've attempted to delete via bulk action but there were no selections.", |
|
| 552 | - "event_espresso" |
|
| 553 | - ) |
|
| 554 | - ), |
|
| 555 | - __FILE__, |
|
| 556 | - __FUNCTION__, |
|
| 557 | - __LINE__ |
|
| 558 | - ); |
|
| 559 | - } |
|
| 560 | - return $success; |
|
| 561 | - } |
|
| 562 | - |
|
| 563 | - |
|
| 564 | - /** |
|
| 565 | - * Deletes the specified question (and its associated question options) or question group |
|
| 566 | - * |
|
| 567 | - * @param int $id |
|
| 568 | - * @param EEM_Soft_Delete_Base $model |
|
| 569 | - * @return boolean |
|
| 570 | - * @throws EE_Error |
|
| 571 | - * @throws InvalidArgumentException |
|
| 572 | - * @throws InvalidDataTypeException |
|
| 573 | - * @throws InvalidInterfaceException |
|
| 574 | - */ |
|
| 575 | - protected function _delete_item($id, $model) |
|
| 576 | - { |
|
| 577 | - if ($model instanceof EEM_Question) { |
|
| 578 | - EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id)))); |
|
| 579 | - } |
|
| 580 | - return $model->delete_permanently_by_ID(absint($id)); |
|
| 581 | - } |
|
| 582 | - |
|
| 583 | - |
|
| 584 | - /****************************** QUESTION GROUPS ******************************/ |
|
| 585 | - |
|
| 586 | - |
|
| 587 | - /** |
|
| 588 | - * @param string $type |
|
| 589 | - * @return void |
|
| 590 | - * @throws DomainException |
|
| 591 | - * @throws EE_Error |
|
| 592 | - * @throws InvalidArgumentException |
|
| 593 | - * @throws InvalidDataTypeException |
|
| 594 | - * @throws InvalidInterfaceException |
|
| 595 | - */ |
|
| 596 | - protected function _edit_question_group($type = 'add') |
|
| 597 | - { |
|
| 598 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 599 | - $ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID']) |
|
| 600 | - ? absint($this->_req_data['QSG_ID']) |
|
| 601 | - : false; |
|
| 602 | - |
|
| 603 | - switch ($this->_req_action) { |
|
| 604 | - case 'add_question_group': |
|
| 605 | - $this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso'); |
|
| 606 | - break; |
|
| 607 | - case 'edit_question_group': |
|
| 608 | - $this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso'); |
|
| 609 | - break; |
|
| 610 | - default: |
|
| 611 | - $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action)); |
|
| 612 | - } |
|
| 613 | - // add ID to title if editing |
|
| 614 | - $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title; |
|
| 615 | - if ($ID) { |
|
| 616 | - /** @var EE_Question_Group $questionGroup */ |
|
| 617 | - $questionGroup = $this->_question_group_model->get_one_by_ID($ID); |
|
| 618 | - $additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID)); |
|
| 619 | - $this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields); |
|
| 620 | - } else { |
|
| 621 | - /** @var EE_Question_Group $questionGroup */ |
|
| 622 | - $questionGroup = EEM_Question_Group::instance()->create_default_object(); |
|
| 623 | - $questionGroup->set_order_to_latest(); |
|
| 624 | - $this->_set_add_edit_form_tags('insert_question_group'); |
|
| 625 | - } |
|
| 626 | - $this->_template_args['values'] = $this->_yes_no_values; |
|
| 627 | - $this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group(); |
|
| 628 | - $this->_template_args['QSG_ID'] = $ID ? $ID : true; |
|
| 629 | - $this->_template_args['question_group'] = $questionGroup; |
|
| 630 | - |
|
| 631 | - $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url); |
|
| 632 | - $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL); |
|
| 633 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
| 634 | - REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php', |
|
| 635 | - $this->_template_args, |
|
| 636 | - true |
|
| 637 | - ); |
|
| 638 | - |
|
| 639 | - // the details template wrapper |
|
| 640 | - $this->display_admin_page_with_sidebar(); |
|
| 641 | - } |
|
| 642 | - |
|
| 643 | - |
|
| 644 | - /** |
|
| 645 | - * @return void |
|
| 646 | - * @throws EE_Error |
|
| 647 | - * @throws InvalidArgumentException |
|
| 648 | - * @throws InvalidDataTypeException |
|
| 649 | - * @throws InvalidInterfaceException |
|
| 650 | - */ |
|
| 651 | - protected function _delete_question_groups() |
|
| 652 | - { |
|
| 653 | - $success = $this->_delete_items($this->_question_group_model); |
|
| 654 | - $this->_redirect_after_action( |
|
| 655 | - $success, |
|
| 656 | - $this->_question_group_model->item_name($success), |
|
| 657 | - 'deleted permanently', |
|
| 658 | - array('action' => 'question_groups', 'status' => 'trash') |
|
| 659 | - ); |
|
| 660 | - } |
|
| 661 | - |
|
| 662 | - |
|
| 663 | - /** |
|
| 664 | - * @param bool $new_question_group |
|
| 665 | - * @throws EE_Error |
|
| 666 | - * @throws InvalidArgumentException |
|
| 667 | - * @throws InvalidDataTypeException |
|
| 668 | - * @throws InvalidInterfaceException |
|
| 669 | - */ |
|
| 670 | - protected function _insert_or_update_question_group($new_question_group = true) |
|
| 671 | - { |
|
| 672 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 673 | - $set_column_values = $this->_set_column_values_for($this->_question_group_model); |
|
| 674 | - if ($new_question_group) { |
|
| 675 | - // make sure identifier is unique |
|
| 676 | - $identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : ''; |
|
| 677 | - $identifier_exists = ! empty($identifier_value) |
|
| 678 | - ? $this->_question_group_model->count([['QSG_identifier' => $set_column_values['QSG_identifier']]]) > 0 |
|
| 679 | - : false; |
|
| 680 | - if ($identifier_exists) { |
|
| 681 | - $set_column_values['QSG_identifier'] .= uniqid('id', true); |
|
| 682 | - } |
|
| 683 | - $QSG_ID = $this->_question_group_model->insert($set_column_values); |
|
| 684 | - $success = $QSG_ID ? 1 : 0; |
|
| 685 | - if ($success === 0) { |
|
| 686 | - EE_Error::add_error( |
|
| 687 | - esc_html__('Something went wrong saving the question group.', 'event_espresso'), |
|
| 688 | - __FILE__, |
|
| 689 | - __FUNCTION__, |
|
| 690 | - __LINE__ |
|
| 691 | - ); |
|
| 692 | - $this->_redirect_after_action( |
|
| 693 | - false, |
|
| 694 | - '', |
|
| 695 | - '', |
|
| 696 | - array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID), |
|
| 697 | - true |
|
| 698 | - ); |
|
| 699 | - } |
|
| 700 | - } else { |
|
| 701 | - $QSG_ID = absint($this->_req_data['QSG_ID']); |
|
| 702 | - unset($set_column_values['QSG_ID']); |
|
| 703 | - $success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID))); |
|
| 704 | - } |
|
| 705 | - |
|
| 706 | - $phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string( |
|
| 707 | - EEM_Attendee::system_question_phone |
|
| 708 | - ); |
|
| 709 | - // update the existing related questions |
|
| 710 | - // BUT FIRST... delete the phone question from the Question_Group_Question |
|
| 711 | - // if it is being added to this question group (therefore removed from the existing group) |
|
| 712 | - if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) { |
|
| 713 | - // delete where QST ID = system phone question ID and Question Group ID is NOT this group |
|
| 714 | - EEM_Question_Group_Question::instance()->delete( |
|
| 715 | - array( |
|
| 716 | - array( |
|
| 717 | - 'QST_ID' => $phone_question_id, |
|
| 718 | - 'QSG_ID' => array('!=', $QSG_ID), |
|
| 719 | - ), |
|
| 720 | - ) |
|
| 721 | - ); |
|
| 722 | - } |
|
| 723 | - /** @type EE_Question_Group $question_group */ |
|
| 724 | - $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID); |
|
| 725 | - $questions = $question_group->questions(); |
|
| 726 | - // make sure system phone question is added to list of questions for this group |
|
| 727 | - if (! isset($questions[ $phone_question_id ])) { |
|
| 728 | - $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id); |
|
| 729 | - } |
|
| 730 | - |
|
| 731 | - foreach ($questions as $question_ID => $question) { |
|
| 732 | - // first we always check for order. |
|
| 733 | - if (! empty($this->_req_data['question_orders'][ $question_ID ])) { |
|
| 734 | - // update question order |
|
| 735 | - $question_group->update_question_order( |
|
| 736 | - $question_ID, |
|
| 737 | - $this->_req_data['question_orders'][ $question_ID ] |
|
| 738 | - ); |
|
| 739 | - } |
|
| 740 | - |
|
| 741 | - // then we always check if adding or removing. |
|
| 742 | - if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) { |
|
| 743 | - $question_group->add_question($question_ID); |
|
| 744 | - } else { |
|
| 745 | - // not found, remove it (but only if not a system question for the personal group |
|
| 746 | - // with the exception of lname system question - we allow removal of it) |
|
| 747 | - if (in_array( |
|
| 748 | - $question->system_ID(), |
|
| 749 | - EEM_Question::instance()->required_system_questions_in_system_question_group( |
|
| 750 | - $question_group->system_group() |
|
| 751 | - ) |
|
| 752 | - )) { |
|
| 753 | - continue; |
|
| 754 | - } else { |
|
| 755 | - $question_group->remove_question($question_ID); |
|
| 756 | - } |
|
| 757 | - } |
|
| 758 | - } |
|
| 759 | - // save new related questions |
|
| 760 | - if (isset($this->_req_data['questions'])) { |
|
| 761 | - foreach ($this->_req_data['questions'] as $QST_ID) { |
|
| 762 | - $question_group->add_question($QST_ID); |
|
| 763 | - if (isset($this->_req_data['question_orders'][ $QST_ID ])) { |
|
| 764 | - $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]); |
|
| 765 | - } |
|
| 766 | - } |
|
| 767 | - } |
|
| 768 | - |
|
| 769 | - if ($success !== false) { |
|
| 770 | - $msg = $new_question_group |
|
| 771 | - ? sprintf( |
|
| 772 | - esc_html__('The %s has been created', 'event_espresso'), |
|
| 773 | - $this->_question_group_model->item_name() |
|
| 774 | - ) |
|
| 775 | - : sprintf( |
|
| 776 | - esc_html__( |
|
| 777 | - 'The %s has been updated', |
|
| 778 | - 'event_espresso' |
|
| 779 | - ), |
|
| 780 | - $this->_question_group_model->item_name() |
|
| 781 | - ); |
|
| 782 | - EE_Error::add_success($msg); |
|
| 783 | - } |
|
| 784 | - $this->_redirect_after_action( |
|
| 785 | - false, |
|
| 786 | - '', |
|
| 787 | - '', |
|
| 788 | - array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID), |
|
| 789 | - true |
|
| 790 | - ); |
|
| 791 | - } |
|
| 792 | - |
|
| 793 | - |
|
| 794 | - /** |
|
| 795 | - * duplicates a question and all its question options and redirects to the new question. |
|
| 796 | - * |
|
| 797 | - * @return void |
|
| 798 | - * @throws EE_Error |
|
| 799 | - * @throws InvalidArgumentException |
|
| 800 | - * @throws ReflectionException |
|
| 801 | - * @throws InvalidDataTypeException |
|
| 802 | - * @throws InvalidInterfaceException |
|
| 803 | - */ |
|
| 804 | - public function _duplicate_question() |
|
| 805 | - { |
|
| 806 | - $question_ID = (int) $this->_req_data['QST_ID']; |
|
| 807 | - $question = EEM_Question::instance()->get_one_by_ID($question_ID); |
|
| 808 | - if ($question instanceof EE_Question) { |
|
| 809 | - $new_question = $question->duplicate(); |
|
| 810 | - if ($new_question instanceof EE_Question) { |
|
| 811 | - $this->_redirect_after_action( |
|
| 812 | - true, |
|
| 813 | - esc_html__('Question', 'event_espresso'), |
|
| 814 | - esc_html__('Duplicated', 'event_espresso'), |
|
| 815 | - array('action' => 'edit_question', 'QST_ID' => $new_question->ID()), |
|
| 816 | - true |
|
| 817 | - ); |
|
| 818 | - } else { |
|
| 819 | - global $wpdb; |
|
| 820 | - EE_Error::add_error( |
|
| 821 | - sprintf( |
|
| 822 | - esc_html__( |
|
| 823 | - 'Could not duplicate question with ID %1$d because: %2$s', |
|
| 824 | - 'event_espresso' |
|
| 825 | - ), |
|
| 826 | - $question_ID, |
|
| 827 | - $wpdb->last_error |
|
| 828 | - ), |
|
| 829 | - __FILE__, |
|
| 830 | - __FUNCTION__, |
|
| 831 | - __LINE__ |
|
| 832 | - ); |
|
| 833 | - $this->_redirect_after_action(false, '', '', array('action' => 'default'), false); |
|
| 834 | - } |
|
| 835 | - } else { |
|
| 836 | - EE_Error::add_error( |
|
| 837 | - sprintf( |
|
| 838 | - esc_html__( |
|
| 839 | - 'Could not duplicate question with ID %d because it didn\'t exist!', |
|
| 840 | - 'event_espresso' |
|
| 841 | - ), |
|
| 842 | - $question_ID |
|
| 843 | - ), |
|
| 844 | - __FILE__, |
|
| 845 | - __FUNCTION__, |
|
| 846 | - __LINE__ |
|
| 847 | - ); |
|
| 848 | - $this->_redirect_after_action(false, '', '', array('action' => 'default'), false); |
|
| 849 | - } |
|
| 850 | - } |
|
| 851 | - |
|
| 852 | - |
|
| 853 | - /** |
|
| 854 | - * @param bool $trash |
|
| 855 | - * @throws EE_Error |
|
| 856 | - */ |
|
| 857 | - protected function _trash_or_restore_question_groups($trash = true) |
|
| 858 | - { |
|
| 859 | - $this->_trash_or_restore_items($this->_question_group_model, $trash); |
|
| 860 | - } |
|
| 861 | - |
|
| 862 | - |
|
| 863 | - /** |
|
| 864 | - *_trash_question |
|
| 865 | - * |
|
| 866 | - * @return void |
|
| 867 | - * @throws EE_Error |
|
| 868 | - */ |
|
| 869 | - protected function _trash_question() |
|
| 870 | - { |
|
| 871 | - $success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']); |
|
| 872 | - $query_args = array('action' => 'default', 'status' => 'all'); |
|
| 873 | - $this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args); |
|
| 874 | - } |
|
| 875 | - |
|
| 876 | - |
|
| 877 | - /** |
|
| 878 | - * @param bool $trash |
|
| 879 | - * @throws EE_Error |
|
| 880 | - */ |
|
| 881 | - protected function _trash_or_restore_questions($trash = true) |
|
| 882 | - { |
|
| 883 | - $this->_trash_or_restore_items($this->_question_model, $trash); |
|
| 884 | - } |
|
| 885 | - |
|
| 886 | - |
|
| 887 | - /** |
|
| 888 | - * Internally used to delete or restore items, using the request data. Meant to be |
|
| 889 | - * flexible between question or question groups |
|
| 890 | - * |
|
| 891 | - * @param EEM_Soft_Delete_Base $model |
|
| 892 | - * @param boolean $trash whether to trash or restore |
|
| 893 | - * @throws EE_Error |
|
| 894 | - */ |
|
| 895 | - private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true) |
|
| 896 | - { |
|
| 897 | - |
|
| 898 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 899 | - |
|
| 900 | - $success = 1; |
|
| 901 | - // Checkboxes |
|
| 902 | - // echo "trash $trash"; |
|
| 903 | - // var_dump($this->_req_data['checkbox']);die; |
|
| 904 | - if (isset($this->_req_data['checkbox'])) { |
|
| 905 | - if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 906 | - // if array has more than one element than success message should be plural |
|
| 907 | - $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1; |
|
| 908 | - // cycle thru bulk action checkboxes |
|
| 909 | - while (list($ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 910 | - if (! $model->delete_or_restore_by_ID($trash, absint($ID))) { |
|
| 911 | - $success = 0; |
|
| 912 | - } |
|
| 913 | - } |
|
| 914 | - } else { |
|
| 915 | - // grab single id and delete |
|
| 916 | - $ID = absint($this->_req_data['checkbox']); |
|
| 917 | - if (! $model->delete_or_restore_by_ID($trash, $ID)) { |
|
| 918 | - $success = 0; |
|
| 919 | - } |
|
| 920 | - } |
|
| 921 | - } else { |
|
| 922 | - // delete via trash link |
|
| 923 | - // grab single id and delete |
|
| 924 | - $ID = absint($this->_req_data[ $model->primary_key_name() ]); |
|
| 925 | - if (! $model->delete_or_restore_by_ID($trash, $ID)) { |
|
| 926 | - $success = 0; |
|
| 927 | - } |
|
| 928 | - } |
|
| 929 | - |
|
| 930 | - |
|
| 931 | - $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) ); |
|
| 932 | - // echo "action :$action"; |
|
| 933 | - // $action = 'questions' ? 'default' : $action; |
|
| 934 | - if ($trash) { |
|
| 935 | - $action_desc = 'trashed'; |
|
| 936 | - $status = 'trash'; |
|
| 937 | - } else { |
|
| 938 | - $action_desc = 'restored'; |
|
| 939 | - $status = 'all'; |
|
| 940 | - } |
|
| 941 | - $this->_redirect_after_action( |
|
| 942 | - $success, |
|
| 943 | - $model->item_name($success), |
|
| 944 | - $action_desc, |
|
| 945 | - array('action' => $action, 'status' => $status) |
|
| 946 | - ); |
|
| 947 | - } |
|
| 948 | - |
|
| 949 | - |
|
| 950 | - /** |
|
| 951 | - * @param $per_page |
|
| 952 | - * @param int $current_page |
|
| 953 | - * @param bool|false $count |
|
| 954 | - * @return EE_Soft_Delete_Base_Class[]|int |
|
| 955 | - * @throws EE_Error |
|
| 956 | - * @throws InvalidArgumentException |
|
| 957 | - * @throws InvalidDataTypeException |
|
| 958 | - * @throws InvalidInterfaceException |
|
| 959 | - */ |
|
| 960 | - public function get_trashed_questions($per_page, $current_page = 1, $count = false) |
|
| 961 | - { |
|
| 962 | - $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page); |
|
| 963 | - |
|
| 964 | - if ($count) { |
|
| 965 | - // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items |
|
| 966 | - $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
| 967 | - $results = $this->_question_model->count_deleted($where); |
|
| 968 | - } else { |
|
| 969 | - // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items |
|
| 970 | - $results = $this->_question_model->get_all_deleted($query_params); |
|
| 971 | - } |
|
| 972 | - return $results; |
|
| 973 | - } |
|
| 974 | - |
|
| 975 | - |
|
| 976 | - /** |
|
| 977 | - * @param $per_page |
|
| 978 | - * @param int $current_page |
|
| 979 | - * @param bool|false $count |
|
| 980 | - * @return EE_Soft_Delete_Base_Class[]|int |
|
| 981 | - * @throws EE_Error |
|
| 982 | - * @throws InvalidArgumentException |
|
| 983 | - * @throws InvalidDataTypeException |
|
| 984 | - * @throws InvalidInterfaceException |
|
| 985 | - */ |
|
| 986 | - public function get_question_groups($per_page, $current_page = 1, $count = false) |
|
| 987 | - { |
|
| 988 | - $questionGroupModel = EEM_Question_Group::instance(); |
|
| 989 | - $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page); |
|
| 990 | - if ($count) { |
|
| 991 | - $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
| 992 | - $results = $questionGroupModel->count($where); |
|
| 993 | - } else { |
|
| 994 | - $results = $questionGroupModel->get_all($query_params); |
|
| 995 | - } |
|
| 996 | - return $results; |
|
| 997 | - } |
|
| 998 | - |
|
| 999 | - |
|
| 1000 | - /** |
|
| 1001 | - * @param $per_page |
|
| 1002 | - * @param int $current_page |
|
| 1003 | - * @param bool $count |
|
| 1004 | - * @return EE_Soft_Delete_Base_Class[]|int |
|
| 1005 | - * @throws EE_Error |
|
| 1006 | - * @throws InvalidArgumentException |
|
| 1007 | - * @throws InvalidDataTypeException |
|
| 1008 | - * @throws InvalidInterfaceException |
|
| 1009 | - */ |
|
| 1010 | - public function get_trashed_question_groups($per_page, $current_page = 1, $count = false) |
|
| 1011 | - { |
|
| 1012 | - $questionGroupModel = EEM_Question_Group::instance(); |
|
| 1013 | - $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page); |
|
| 1014 | - if ($count) { |
|
| 1015 | - $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
| 1016 | - $query_params['limit'] = null; |
|
| 1017 | - $results = $questionGroupModel->count_deleted($where); |
|
| 1018 | - } else { |
|
| 1019 | - $results = $questionGroupModel->get_all_deleted($query_params); |
|
| 1020 | - } |
|
| 1021 | - return $results; |
|
| 1022 | - } |
|
| 1023 | - |
|
| 1024 | - |
|
| 1025 | - /** |
|
| 1026 | - * method for performing updates to question order |
|
| 1027 | - * |
|
| 1028 | - * @return void results array |
|
| 1029 | - * @throws EE_Error |
|
| 1030 | - * @throws InvalidArgumentException |
|
| 1031 | - * @throws InvalidDataTypeException |
|
| 1032 | - * @throws InvalidInterfaceException |
|
| 1033 | - */ |
|
| 1034 | - public function update_question_group_order() |
|
| 1035 | - { |
|
| 1036 | - |
|
| 1037 | - $success = esc_html__('Question group order was updated successfully.', 'event_espresso'); |
|
| 1038 | - |
|
| 1039 | - // grab our row IDs |
|
| 1040 | - $row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids']) |
|
| 1041 | - ? explode(',', rtrim($this->_req_data['row_ids'], ',')) |
|
| 1042 | - : array(); |
|
| 1043 | - |
|
| 1044 | - $perpage = ! empty($this->_req_data['perpage']) |
|
| 1045 | - ? (int) $this->_req_data['perpage'] |
|
| 1046 | - : null; |
|
| 1047 | - $curpage = ! empty($this->_req_data['curpage']) |
|
| 1048 | - ? (int) $this->_req_data['curpage'] |
|
| 1049 | - : null; |
|
| 1050 | - |
|
| 1051 | - if (! empty($row_ids)) { |
|
| 1052 | - // figure out where we start the row_id count at for the current page. |
|
| 1053 | - $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage; |
|
| 1054 | - |
|
| 1055 | - $row_count = count($row_ids); |
|
| 1056 | - for ($i = 0; $i < $row_count; $i++) { |
|
| 1057 | - // Update the questions when re-ordering |
|
| 1058 | - $updated = EEM_Question_Group::instance()->update( |
|
| 1059 | - array('QSG_order' => $qsgcount), |
|
| 1060 | - array(array('QSG_ID' => $row_ids[ $i ])) |
|
| 1061 | - ); |
|
| 1062 | - if ($updated === false) { |
|
| 1063 | - $success = false; |
|
| 1064 | - } |
|
| 1065 | - $qsgcount++; |
|
| 1066 | - } |
|
| 1067 | - } else { |
|
| 1068 | - $success = false; |
|
| 1069 | - } |
|
| 1070 | - |
|
| 1071 | - $errors = ! $success |
|
| 1072 | - ? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso') |
|
| 1073 | - : false; |
|
| 1074 | - |
|
| 1075 | - echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors)); |
|
| 1076 | - die(); |
|
| 1077 | - } |
|
| 1078 | - |
|
| 1079 | - |
|
| 1080 | - |
|
| 1081 | - /*************************************** REGISTRATION SETTINGS ***************************************/ |
|
| 1082 | - |
|
| 1083 | - |
|
| 1084 | - /** |
|
| 1085 | - * @throws DomainException |
|
| 1086 | - * @throws EE_Error |
|
| 1087 | - * @throws InvalidArgumentException |
|
| 1088 | - * @throws InvalidDataTypeException |
|
| 1089 | - * @throws InvalidInterfaceException |
|
| 1090 | - */ |
|
| 1091 | - protected function _reg_form_settings() |
|
| 1092 | - { |
|
| 1093 | - $this->_template_args['values'] = $this->_yes_no_values; |
|
| 1094 | - add_action( |
|
| 1095 | - 'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template', |
|
| 1096 | - array($this, 'email_validation_settings_form'), |
|
| 1097 | - 2 |
|
| 1098 | - ); |
|
| 1099 | - $this->_template_args = (array) apply_filters( |
|
| 1100 | - 'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args', |
|
| 1101 | - $this->_template_args |
|
| 1102 | - ); |
|
| 1103 | - $this->_set_add_edit_form_tags('update_reg_form_settings'); |
|
| 1104 | - $this->_set_publish_post_box_vars(null, false, false, null, false); |
|
| 1105 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
| 1106 | - REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php', |
|
| 1107 | - $this->_template_args, |
|
| 1108 | - true |
|
| 1109 | - ); |
|
| 1110 | - $this->display_admin_page_with_sidebar(); |
|
| 1111 | - } |
|
| 1112 | - |
|
| 1113 | - |
|
| 1114 | - /** |
|
| 1115 | - * @return void |
|
| 1116 | - * @throws EE_Error |
|
| 1117 | - * @throws InvalidArgumentException |
|
| 1118 | - * @throws ReflectionException |
|
| 1119 | - * @throws InvalidDataTypeException |
|
| 1120 | - * @throws InvalidInterfaceException |
|
| 1121 | - */ |
|
| 1122 | - protected function _update_reg_form_settings() |
|
| 1123 | - { |
|
| 1124 | - EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form( |
|
| 1125 | - EE_Registry::instance()->CFG->registration |
|
| 1126 | - ); |
|
| 1127 | - EE_Registry::instance()->CFG->registration = apply_filters( |
|
| 1128 | - 'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration', |
|
| 1129 | - EE_Registry::instance()->CFG->registration |
|
| 1130 | - ); |
|
| 1131 | - $success = $this->_update_espresso_configuration( |
|
| 1132 | - esc_html__('Registration Form Options', 'event_espresso'), |
|
| 1133 | - EE_Registry::instance()->CFG, |
|
| 1134 | - __FILE__, |
|
| 1135 | - __FUNCTION__, |
|
| 1136 | - __LINE__ |
|
| 1137 | - ); |
|
| 1138 | - $this->_redirect_after_action( |
|
| 1139 | - $success, |
|
| 1140 | - esc_html__('Registration Form Options', 'event_espresso'), |
|
| 1141 | - 'updated', |
|
| 1142 | - array('action' => 'view_reg_form_settings') |
|
| 1143 | - ); |
|
| 1144 | - } |
|
| 1145 | - |
|
| 1146 | - |
|
| 1147 | - /** |
|
| 1148 | - * @return void |
|
| 1149 | - * @throws EE_Error |
|
| 1150 | - * @throws InvalidArgumentException |
|
| 1151 | - * @throws InvalidDataTypeException |
|
| 1152 | - * @throws InvalidInterfaceException |
|
| 1153 | - */ |
|
| 1154 | - public function email_validation_settings_form() |
|
| 1155 | - { |
|
| 1156 | - echo $this->_email_validation_settings_form()->get_html(); |
|
| 1157 | - } |
|
| 1158 | - |
|
| 1159 | - |
|
| 1160 | - /** |
|
| 1161 | - * _email_validation_settings_form |
|
| 1162 | - * |
|
| 1163 | - * @access protected |
|
| 1164 | - * @return EE_Form_Section_Proper |
|
| 1165 | - * @throws \EE_Error |
|
| 1166 | - */ |
|
| 1167 | - protected function _email_validation_settings_form() |
|
| 1168 | - { |
|
| 1169 | - return new EE_Form_Section_Proper( |
|
| 1170 | - array( |
|
| 1171 | - 'name' => 'email_validation_settings', |
|
| 1172 | - 'html_id' => 'email_validation_settings', |
|
| 1173 | - 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
| 1174 | - 'subsections' => apply_filters( |
|
| 1175 | - 'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections', |
|
| 1176 | - array( |
|
| 1177 | - 'email_validation_hdr' => new EE_Form_Section_HTML( |
|
| 1178 | - EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso')) |
|
| 1179 | - ), |
|
| 1180 | - 'email_validation_level' => new EE_Select_Input( |
|
| 1181 | - array( |
|
| 1182 | - 'basic' => esc_html__('Basic', 'event_espresso'), |
|
| 1183 | - 'wp_default' => esc_html__('WordPress Default', 'event_espresso'), |
|
| 1184 | - 'i18n' => esc_html__('International', 'event_espresso'), |
|
| 1185 | - 'i18n_dns' => esc_html__('International + DNS Check', 'event_espresso'), |
|
| 1186 | - ), |
|
| 1187 | - array( |
|
| 1188 | - 'html_label_text' => esc_html__('Email Validation Level', 'event_espresso') |
|
| 1189 | - . EEH_Template::get_help_tab_link('email_validation_info'), |
|
| 1190 | - 'html_help_text' => esc_html__( |
|
| 1191 | - 'These levels range from basic validation ( ie: [email protected] ) to more advanced checks against international email addresses (ie: üñîçøðé@example.com ) with additional MX and A record checks to confirm the domain actually exists. More information on on each level can be found within the help section.', |
|
| 1192 | - 'event_espresso' |
|
| 1193 | - ), |
|
| 1194 | - 'default' => isset( |
|
| 1195 | - EE_Registry::instance()->CFG->registration->email_validation_level |
|
| 1196 | - ) |
|
| 1197 | - ? EE_Registry::instance()->CFG->registration->email_validation_level |
|
| 1198 | - : 'wp_default', |
|
| 1199 | - 'required' => false, |
|
| 1200 | - ) |
|
| 1201 | - ), |
|
| 1202 | - ) |
|
| 1203 | - ), |
|
| 1204 | - ) |
|
| 1205 | - ); |
|
| 1206 | - } |
|
| 1207 | - |
|
| 1208 | - |
|
| 1209 | - /** |
|
| 1210 | - * @param EE_Registration_Config $EE_Registration_Config |
|
| 1211 | - * @return EE_Registration_Config |
|
| 1212 | - * @throws EE_Error |
|
| 1213 | - * @throws InvalidArgumentException |
|
| 1214 | - * @throws ReflectionException |
|
| 1215 | - * @throws InvalidDataTypeException |
|
| 1216 | - * @throws InvalidInterfaceException |
|
| 1217 | - */ |
|
| 1218 | - public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config) |
|
| 1219 | - { |
|
| 1220 | - $prev_email_validation_level = $EE_Registration_Config->email_validation_level; |
|
| 1221 | - try { |
|
| 1222 | - $email_validation_settings_form = $this->_email_validation_settings_form(); |
|
| 1223 | - // if not displaying a form, then check for form submission |
|
| 1224 | - if ($email_validation_settings_form->was_submitted()) { |
|
| 1225 | - // capture form data |
|
| 1226 | - $email_validation_settings_form->receive_form_submission(); |
|
| 1227 | - // validate form data |
|
| 1228 | - if ($email_validation_settings_form->is_valid()) { |
|
| 1229 | - // grab validated data from form |
|
| 1230 | - $valid_data = $email_validation_settings_form->valid_data(); |
|
| 1231 | - if (isset($valid_data['email_validation_level'])) { |
|
| 1232 | - $email_validation_level = $valid_data['email_validation_level']; |
|
| 1233 | - // now if they want to use international email addresses |
|
| 1234 | - if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') { |
|
| 1235 | - // in case we need to reset their email validation level, |
|
| 1236 | - // make sure that the previous value wasn't already set to one of the i18n options. |
|
| 1237 | - if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') { |
|
| 1238 | - // if so, then reset it back to "basic" since that is the only other option that, |
|
| 1239 | - // despite offering poor validation, supports i18n email addresses |
|
| 1240 | - $prev_email_validation_level = 'basic'; |
|
| 1241 | - } |
|
| 1242 | - // confirm our i18n email validation will work on the server |
|
| 1243 | - if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) { |
|
| 1244 | - // or reset email validation level to previous value |
|
| 1245 | - $email_validation_level = $prev_email_validation_level; |
|
| 1246 | - } |
|
| 1247 | - } |
|
| 1248 | - $EE_Registration_Config->email_validation_level = $email_validation_level; |
|
| 1249 | - } else { |
|
| 1250 | - EE_Error::add_error( |
|
| 1251 | - esc_html__( |
|
| 1252 | - 'Invalid or missing Email Validation settings. Please refresh the form and try again.', |
|
| 1253 | - 'event_espresso' |
|
| 1254 | - ), |
|
| 1255 | - __FILE__, |
|
| 1256 | - __FUNCTION__, |
|
| 1257 | - __LINE__ |
|
| 1258 | - ); |
|
| 1259 | - } |
|
| 1260 | - } else { |
|
| 1261 | - if ($email_validation_settings_form->submission_error_message() !== '') { |
|
| 1262 | - EE_Error::add_error( |
|
| 1263 | - $email_validation_settings_form->submission_error_message(), |
|
| 1264 | - __FILE__, |
|
| 1265 | - __FUNCTION__, |
|
| 1266 | - __LINE__ |
|
| 1267 | - ); |
|
| 1268 | - } |
|
| 1269 | - } |
|
| 1270 | - } |
|
| 1271 | - } catch (EE_Error $e) { |
|
| 1272 | - $e->get_error(); |
|
| 1273 | - } |
|
| 1274 | - return $EE_Registration_Config; |
|
| 1275 | - } |
|
| 1276 | - |
|
| 1277 | - |
|
| 1278 | - /** |
|
| 1279 | - * confirms that the server's PHP version has the PCRE module enabled, |
|
| 1280 | - * and that the PCRE version works with our i18n email validation |
|
| 1281 | - * |
|
| 1282 | - * @param EE_Registration_Config $EE_Registration_Config |
|
| 1283 | - * @param string $email_validation_level |
|
| 1284 | - * @return bool |
|
| 1285 | - */ |
|
| 1286 | - private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level) |
|
| 1287 | - { |
|
| 1288 | - // first check that PCRE is enabled |
|
| 1289 | - if (! defined('PREG_BAD_UTF8_ERROR')) { |
|
| 1290 | - EE_Error::add_error( |
|
| 1291 | - sprintf( |
|
| 1292 | - esc_html__( |
|
| 1293 | - 'We\'re sorry, but it appears that your server\'s version of PHP was not compiled with PCRE unicode support.%1$sPlease contact your hosting company and ask them whether the PCRE compiled with your version of PHP on your server can be been built with the "--enable-unicode-properties" and "--enable-utf8" configuration switches to enable more complex regex expressions.%1$sIf they are unable, or unwilling to do so, then your server will not support international email addresses using UTF-8 unicode characters. This means you will either have to lower your email validation level to "Basic" or "WordPress Default", or switch to a hosting company that has/can enable PCRE unicode support on the server.', |
|
| 1294 | - 'event_espresso' |
|
| 1295 | - ), |
|
| 1296 | - '<br />' |
|
| 1297 | - ), |
|
| 1298 | - __FILE__, |
|
| 1299 | - __FUNCTION__, |
|
| 1300 | - __LINE__ |
|
| 1301 | - ); |
|
| 1302 | - return false; |
|
| 1303 | - } else { |
|
| 1304 | - // PCRE support is enabled, but let's still |
|
| 1305 | - // perform a test to see if the server will support it. |
|
| 1306 | - // but first, save the updated validation level to the config, |
|
| 1307 | - // so that the validation strategy picks it up. |
|
| 1308 | - // this will get bumped back down if it doesn't work |
|
| 1309 | - $EE_Registration_Config->email_validation_level = $email_validation_level; |
|
| 1310 | - try { |
|
| 1311 | - $email_validator = new EE_Email_Validation_Strategy(); |
|
| 1312 | - $i18n_email_address = apply_filters( |
|
| 1313 | - 'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address', |
|
| 1314 | - 'jägerjü[email protected]' |
|
| 1315 | - ); |
|
| 1316 | - $email_validator->validate($i18n_email_address); |
|
| 1317 | - } catch (Exception $e) { |
|
| 1318 | - EE_Error::add_error( |
|
| 1319 | - sprintf( |
|
| 1320 | - esc_html__( |
|
| 1321 | - 'We\'re sorry, but it appears that your server\'s configuration will not support the "International" or "International + DNS Check" email validation levels.%1$sTo correct this issue, please consult with your hosting company regarding your server\'s PCRE settings.%1$sIt is recommended that your PHP version be configured to use PCRE 8.10 or newer.%1$sMore information regarding PCRE versions and installation can be found here: %2$s', |
|
| 1322 | - 'event_espresso' |
|
| 1323 | - ), |
|
| 1324 | - '<br />', |
|
| 1325 | - '<a href="http://php.net/manual/en/pcre.installation.php" target="_blank">http://php.net/manual/en/pcre.installation.php</a>' |
|
| 1326 | - ), |
|
| 1327 | - __FILE__, |
|
| 1328 | - __FUNCTION__, |
|
| 1329 | - __LINE__ |
|
| 1330 | - ); |
|
| 1331 | - return false; |
|
| 1332 | - } |
|
| 1333 | - } |
|
| 1334 | - return true; |
|
| 1335 | - } |
|
| 17 | + /** |
|
| 18 | + * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object. |
|
| 19 | + */ |
|
| 20 | + public function __construct($routing = true) |
|
| 21 | + { |
|
| 22 | + define('REGISTRATION_FORM_CAF_ADMIN', EE_CORE_CAF_ADMIN_EXTEND . 'registration_form' . DS); |
|
| 23 | + define('REGISTRATION_FORM_CAF_ASSETS_PATH', REGISTRATION_FORM_CAF_ADMIN . 'assets' . DS); |
|
| 24 | + define('REGISTRATION_FORM_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/assets/'); |
|
| 25 | + define('REGISTRATION_FORM_CAF_TEMPLATE_PATH', REGISTRATION_FORM_CAF_ADMIN . 'templates' . DS); |
|
| 26 | + define('REGISTRATION_FORM_CAF_TEMPLATE_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'registration_form/templates/'); |
|
| 27 | + parent::__construct($routing); |
|
| 28 | + } |
|
| 29 | + |
|
| 30 | + |
|
| 31 | + /** |
|
| 32 | + * @return void |
|
| 33 | + */ |
|
| 34 | + protected function _extend_page_config() |
|
| 35 | + { |
|
| 36 | + $this->_admin_base_path = REGISTRATION_FORM_CAF_ADMIN; |
|
| 37 | + $qst_id = ! empty($this->_req_data['QST_ID']) && ! is_array($this->_req_data['QST_ID']) |
|
| 38 | + ? $this->_req_data['QST_ID'] : 0; |
|
| 39 | + $qsg_id = ! empty($this->_req_data['QSG_ID']) && ! is_array($this->_req_data['QSG_ID']) |
|
| 40 | + ? $this->_req_data['QSG_ID'] : 0; |
|
| 41 | + |
|
| 42 | + $new_page_routes = array( |
|
| 43 | + 'question_groups' => array( |
|
| 44 | + 'func' => '_question_groups_overview_list_table', |
|
| 45 | + 'capability' => 'ee_read_question_groups', |
|
| 46 | + ), |
|
| 47 | + 'add_question' => array( |
|
| 48 | + 'func' => '_edit_question', |
|
| 49 | + 'capability' => 'ee_edit_questions', |
|
| 50 | + ), |
|
| 51 | + 'insert_question' => array( |
|
| 52 | + 'func' => '_insert_or_update_question', |
|
| 53 | + 'args' => array('new_question' => true), |
|
| 54 | + 'capability' => 'ee_edit_questions', |
|
| 55 | + 'noheader' => true, |
|
| 56 | + ), |
|
| 57 | + 'duplicate_question' => array( |
|
| 58 | + 'func' => '_duplicate_question', |
|
| 59 | + 'capability' => 'ee_edit_questions', |
|
| 60 | + 'noheader' => true, |
|
| 61 | + ), |
|
| 62 | + 'trash_question' => array( |
|
| 63 | + 'func' => '_trash_question', |
|
| 64 | + 'capability' => 'ee_delete_question', |
|
| 65 | + 'obj_id' => $qst_id, |
|
| 66 | + 'noheader' => true, |
|
| 67 | + ), |
|
| 68 | + |
|
| 69 | + 'restore_question' => array( |
|
| 70 | + 'func' => '_trash_or_restore_questions', |
|
| 71 | + 'capability' => 'ee_delete_question', |
|
| 72 | + 'obj_id' => $qst_id, |
|
| 73 | + 'args' => array('trash' => false), |
|
| 74 | + 'noheader' => true, |
|
| 75 | + ), |
|
| 76 | + |
|
| 77 | + 'delete_question' => array( |
|
| 78 | + 'func' => '_delete_question', |
|
| 79 | + 'capability' => 'ee_delete_question', |
|
| 80 | + 'obj_id' => $qst_id, |
|
| 81 | + 'noheader' => true, |
|
| 82 | + ), |
|
| 83 | + |
|
| 84 | + 'trash_questions' => array( |
|
| 85 | + 'func' => '_trash_or_restore_questions', |
|
| 86 | + 'capability' => 'ee_delete_questions', |
|
| 87 | + 'args' => array('trash' => true), |
|
| 88 | + 'noheader' => true, |
|
| 89 | + ), |
|
| 90 | + |
|
| 91 | + 'restore_questions' => array( |
|
| 92 | + 'func' => '_trash_or_restore_questions', |
|
| 93 | + 'capability' => 'ee_delete_questions', |
|
| 94 | + 'args' => array('trash' => false), |
|
| 95 | + 'noheader' => true, |
|
| 96 | + ), |
|
| 97 | + |
|
| 98 | + 'delete_questions' => array( |
|
| 99 | + 'func' => '_delete_questions', |
|
| 100 | + 'args' => array(), |
|
| 101 | + 'capability' => 'ee_delete_questions', |
|
| 102 | + 'noheader' => true, |
|
| 103 | + ), |
|
| 104 | + |
|
| 105 | + 'add_question_group' => array( |
|
| 106 | + 'func' => '_edit_question_group', |
|
| 107 | + 'capability' => 'ee_edit_question_groups', |
|
| 108 | + ), |
|
| 109 | + |
|
| 110 | + 'edit_question_group' => array( |
|
| 111 | + 'func' => '_edit_question_group', |
|
| 112 | + 'capability' => 'ee_edit_question_group', |
|
| 113 | + 'obj_id' => $qsg_id, |
|
| 114 | + 'args' => array('edit'), |
|
| 115 | + ), |
|
| 116 | + |
|
| 117 | + 'delete_question_groups' => array( |
|
| 118 | + 'func' => '_delete_question_groups', |
|
| 119 | + 'capability' => 'ee_delete_question_groups', |
|
| 120 | + 'noheader' => true, |
|
| 121 | + ), |
|
| 122 | + |
|
| 123 | + 'delete_question_group' => array( |
|
| 124 | + 'func' => '_delete_question_groups', |
|
| 125 | + 'capability' => 'ee_delete_question_group', |
|
| 126 | + 'obj_id' => $qsg_id, |
|
| 127 | + 'noheader' => true, |
|
| 128 | + ), |
|
| 129 | + |
|
| 130 | + 'trash_question_group' => array( |
|
| 131 | + 'func' => '_trash_or_restore_question_groups', |
|
| 132 | + 'args' => array('trash' => true), |
|
| 133 | + 'capability' => 'ee_delete_question_group', |
|
| 134 | + 'obj_id' => $qsg_id, |
|
| 135 | + 'noheader' => true, |
|
| 136 | + ), |
|
| 137 | + |
|
| 138 | + 'restore_question_group' => array( |
|
| 139 | + 'func' => '_trash_or_restore_question_groups', |
|
| 140 | + 'args' => array('trash' => false), |
|
| 141 | + 'capability' => 'ee_delete_question_group', |
|
| 142 | + 'obj_id' => $qsg_id, |
|
| 143 | + 'noheader' => true, |
|
| 144 | + ), |
|
| 145 | + |
|
| 146 | + 'insert_question_group' => array( |
|
| 147 | + 'func' => '_insert_or_update_question_group', |
|
| 148 | + 'args' => array('new_question_group' => true), |
|
| 149 | + 'capability' => 'ee_edit_question_groups', |
|
| 150 | + 'noheader' => true, |
|
| 151 | + ), |
|
| 152 | + |
|
| 153 | + 'update_question_group' => array( |
|
| 154 | + 'func' => '_insert_or_update_question_group', |
|
| 155 | + 'args' => array('new_question_group' => false), |
|
| 156 | + 'capability' => 'ee_edit_question_group', |
|
| 157 | + 'obj_id' => $qsg_id, |
|
| 158 | + 'noheader' => true, |
|
| 159 | + ), |
|
| 160 | + |
|
| 161 | + 'trash_question_groups' => array( |
|
| 162 | + 'func' => '_trash_or_restore_question_groups', |
|
| 163 | + 'args' => array('trash' => true), |
|
| 164 | + 'capability' => 'ee_delete_question_groups', |
|
| 165 | + 'noheader' => array('trash' => false), |
|
| 166 | + ), |
|
| 167 | + |
|
| 168 | + 'restore_question_groups' => array( |
|
| 169 | + 'func' => '_trash_or_restore_question_groups', |
|
| 170 | + 'args' => array('trash' => false), |
|
| 171 | + 'capability' => 'ee_delete_question_groups', |
|
| 172 | + 'noheader' => true, |
|
| 173 | + ), |
|
| 174 | + |
|
| 175 | + |
|
| 176 | + 'espresso_update_question_group_order' => array( |
|
| 177 | + 'func' => 'update_question_group_order', |
|
| 178 | + 'capability' => 'ee_edit_question_groups', |
|
| 179 | + 'noheader' => true, |
|
| 180 | + ), |
|
| 181 | + |
|
| 182 | + 'view_reg_form_settings' => array( |
|
| 183 | + 'func' => '_reg_form_settings', |
|
| 184 | + 'capability' => 'manage_options', |
|
| 185 | + ), |
|
| 186 | + |
|
| 187 | + 'update_reg_form_settings' => array( |
|
| 188 | + 'func' => '_update_reg_form_settings', |
|
| 189 | + 'capability' => 'manage_options', |
|
| 190 | + 'noheader' => true, |
|
| 191 | + ), |
|
| 192 | + ); |
|
| 193 | + $this->_page_routes = array_merge($this->_page_routes, $new_page_routes); |
|
| 194 | + |
|
| 195 | + $new_page_config = array( |
|
| 196 | + |
|
| 197 | + 'question_groups' => array( |
|
| 198 | + 'nav' => array( |
|
| 199 | + 'label' => esc_html__('Question Groups', 'event_espresso'), |
|
| 200 | + 'order' => 20, |
|
| 201 | + ), |
|
| 202 | + 'list_table' => 'Registration_Form_Question_Groups_Admin_List_Table', |
|
| 203 | + 'help_tabs' => array( |
|
| 204 | + 'registration_form_question_groups_help_tab' => array( |
|
| 205 | + 'title' => esc_html__('Question Groups', 'event_espresso'), |
|
| 206 | + 'filename' => 'registration_form_question_groups', |
|
| 207 | + ), |
|
| 208 | + 'registration_form_question_groups_table_column_headings_help_tab' => array( |
|
| 209 | + 'title' => esc_html__('Question Groups Table Column Headings', 'event_espresso'), |
|
| 210 | + 'filename' => 'registration_form_question_groups_table_column_headings', |
|
| 211 | + ), |
|
| 212 | + 'registration_form_question_groups_views_bulk_actions_search_help_tab' => array( |
|
| 213 | + 'title' => esc_html__('Question Groups Views & Bulk Actions & Search', 'event_espresso'), |
|
| 214 | + 'filename' => 'registration_form_question_groups_views_bulk_actions_search', |
|
| 215 | + ), |
|
| 216 | + ), |
|
| 217 | + 'help_tour' => array('Registration_Form_Question_Groups_Help_Tour'), |
|
| 218 | + 'metaboxes' => $this->_default_espresso_metaboxes, |
|
| 219 | + 'require_nonce' => false, |
|
| 220 | + 'qtips' => array( |
|
| 221 | + 'EE_Registration_Form_Tips', |
|
| 222 | + ), |
|
| 223 | + ), |
|
| 224 | + |
|
| 225 | + 'add_question' => array( |
|
| 226 | + 'nav' => array( |
|
| 227 | + 'label' => esc_html__('Add Question', 'event_espresso'), |
|
| 228 | + 'order' => 5, |
|
| 229 | + 'persistent' => false, |
|
| 230 | + ), |
|
| 231 | + 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 232 | + 'help_tabs' => array( |
|
| 233 | + 'registration_form_add_question_help_tab' => array( |
|
| 234 | + 'title' => esc_html__('Add Question', 'event_espresso'), |
|
| 235 | + 'filename' => 'registration_form_add_question', |
|
| 236 | + ), |
|
| 237 | + ), |
|
| 238 | + 'help_tour' => array('Registration_Form_Add_Question_Help_Tour'), |
|
| 239 | + 'require_nonce' => false, |
|
| 240 | + ), |
|
| 241 | + |
|
| 242 | + 'add_question_group' => array( |
|
| 243 | + 'nav' => array( |
|
| 244 | + 'label' => esc_html__('Add Question Group', 'event_espresso'), |
|
| 245 | + 'order' => 5, |
|
| 246 | + 'persistent' => false, |
|
| 247 | + ), |
|
| 248 | + 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 249 | + 'help_tabs' => array( |
|
| 250 | + 'registration_form_add_question_group_help_tab' => array( |
|
| 251 | + 'title' => esc_html__('Add Question Group', 'event_espresso'), |
|
| 252 | + 'filename' => 'registration_form_add_question_group', |
|
| 253 | + ), |
|
| 254 | + ), |
|
| 255 | + 'help_tour' => array('Registration_Form_Add_Question_Group_Help_Tour'), |
|
| 256 | + 'require_nonce' => false, |
|
| 257 | + ), |
|
| 258 | + |
|
| 259 | + 'edit_question_group' => array( |
|
| 260 | + 'nav' => array( |
|
| 261 | + 'label' => esc_html__('Edit Question Group', 'event_espresso'), |
|
| 262 | + 'order' => 5, |
|
| 263 | + 'persistent' => false, |
|
| 264 | + 'url' => isset($this->_req_data['question_group_id']) ? add_query_arg( |
|
| 265 | + array('question_group_id' => $this->_req_data['question_group_id']), |
|
| 266 | + $this->_current_page_view_url |
|
| 267 | + ) : $this->_admin_base_url, |
|
| 268 | + ), |
|
| 269 | + 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 270 | + 'help_tabs' => array( |
|
| 271 | + 'registration_form_edit_question_group_help_tab' => array( |
|
| 272 | + 'title' => esc_html__('Edit Question Group', 'event_espresso'), |
|
| 273 | + 'filename' => 'registration_form_edit_question_group', |
|
| 274 | + ), |
|
| 275 | + ), |
|
| 276 | + 'help_tour' => array('Registration_Form_Edit_Question_Group_Help_Tour'), |
|
| 277 | + 'require_nonce' => false, |
|
| 278 | + ), |
|
| 279 | + |
|
| 280 | + 'view_reg_form_settings' => array( |
|
| 281 | + 'nav' => array( |
|
| 282 | + 'label' => esc_html__('Reg Form Settings', 'event_espresso'), |
|
| 283 | + 'order' => 40, |
|
| 284 | + ), |
|
| 285 | + 'labels' => array( |
|
| 286 | + 'publishbox' => esc_html__('Update Settings', 'event_espresso'), |
|
| 287 | + ), |
|
| 288 | + 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 289 | + 'help_tabs' => array( |
|
| 290 | + 'registration_form_reg_form_settings_help_tab' => array( |
|
| 291 | + 'title' => esc_html__('Registration Form Settings', 'event_espresso'), |
|
| 292 | + 'filename' => 'registration_form_reg_form_settings', |
|
| 293 | + ), |
|
| 294 | + ), |
|
| 295 | + 'help_tour' => array('Registration_Form_Settings_Help_Tour'), |
|
| 296 | + 'require_nonce' => false, |
|
| 297 | + ), |
|
| 298 | + |
|
| 299 | + ); |
|
| 300 | + $this->_page_config = array_merge($this->_page_config, $new_page_config); |
|
| 301 | + |
|
| 302 | + // change the list table we're going to use so it's the NEW list table! |
|
| 303 | + $this->_page_config['default']['list_table'] = 'Extend_Registration_Form_Questions_Admin_List_Table'; |
|
| 304 | + |
|
| 305 | + |
|
| 306 | + // additional labels |
|
| 307 | + $new_labels = array( |
|
| 308 | + 'add_question' => esc_html__('Add New Question', 'event_espresso'), |
|
| 309 | + 'delete_question' => esc_html__('Delete Question', 'event_espresso'), |
|
| 310 | + 'add_question_group' => esc_html__('Add New Question Group', 'event_espresso'), |
|
| 311 | + 'edit_question_group' => esc_html__('Edit Question Group', 'event_espresso'), |
|
| 312 | + 'delete_question_group' => esc_html__('Delete Question Group', 'event_espresso'), |
|
| 313 | + ); |
|
| 314 | + $this->_labels['buttons'] = array_merge($this->_labels['buttons'], $new_labels); |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + |
|
| 318 | + /** |
|
| 319 | + * @return void |
|
| 320 | + */ |
|
| 321 | + protected function _ajax_hooks() |
|
| 322 | + { |
|
| 323 | + add_action('wp_ajax_espresso_update_question_group_order', array($this, 'update_question_group_order')); |
|
| 324 | + } |
|
| 325 | + |
|
| 326 | + |
|
| 327 | + /** |
|
| 328 | + * @return void |
|
| 329 | + */ |
|
| 330 | + public function load_scripts_styles_question_groups() |
|
| 331 | + { |
|
| 332 | + wp_enqueue_script('espresso_ajax_table_sorting'); |
|
| 333 | + } |
|
| 334 | + |
|
| 335 | + |
|
| 336 | + /** |
|
| 337 | + * @return void |
|
| 338 | + */ |
|
| 339 | + public function load_scripts_styles_add_question_group() |
|
| 340 | + { |
|
| 341 | + $this->load_scripts_styles_forms(); |
|
| 342 | + $this->load_sortable_question_script(); |
|
| 343 | + } |
|
| 344 | + |
|
| 345 | + |
|
| 346 | + /** |
|
| 347 | + * @return void |
|
| 348 | + */ |
|
| 349 | + public function load_scripts_styles_edit_question_group() |
|
| 350 | + { |
|
| 351 | + $this->load_scripts_styles_forms(); |
|
| 352 | + $this->load_sortable_question_script(); |
|
| 353 | + } |
|
| 354 | + |
|
| 355 | + |
|
| 356 | + /** |
|
| 357 | + * registers and enqueues script for questions |
|
| 358 | + * |
|
| 359 | + * @return void |
|
| 360 | + */ |
|
| 361 | + public function load_sortable_question_script() |
|
| 362 | + { |
|
| 363 | + wp_register_script( |
|
| 364 | + 'ee-question-sortable', |
|
| 365 | + REGISTRATION_FORM_CAF_ASSETS_URL . 'ee_question_order.js', |
|
| 366 | + array('jquery-ui-sortable'), |
|
| 367 | + EVENT_ESPRESSO_VERSION, |
|
| 368 | + true |
|
| 369 | + ); |
|
| 370 | + wp_enqueue_script('ee-question-sortable'); |
|
| 371 | + } |
|
| 372 | + |
|
| 373 | + |
|
| 374 | + /** |
|
| 375 | + * @return void |
|
| 376 | + */ |
|
| 377 | + protected function _set_list_table_views_default() |
|
| 378 | + { |
|
| 379 | + $this->_views = array( |
|
| 380 | + 'all' => array( |
|
| 381 | + 'slug' => 'all', |
|
| 382 | + 'label' => esc_html__('View All Questions', 'event_espresso'), |
|
| 383 | + 'count' => 0, |
|
| 384 | + 'bulk_action' => array( |
|
| 385 | + 'trash_questions' => esc_html__('Trash', 'event_espresso'), |
|
| 386 | + ), |
|
| 387 | + ), |
|
| 388 | + ); |
|
| 389 | + |
|
| 390 | + if (EE_Registry::instance()->CAP->current_user_can( |
|
| 391 | + 'ee_delete_questions', |
|
| 392 | + 'espresso_registration_form_trash_questions' |
|
| 393 | + ) |
|
| 394 | + ) { |
|
| 395 | + $this->_views['trash'] = array( |
|
| 396 | + 'slug' => 'trash', |
|
| 397 | + 'label' => esc_html__('Trash', 'event_espresso'), |
|
| 398 | + 'count' => 0, |
|
| 399 | + 'bulk_action' => array( |
|
| 400 | + 'delete_questions' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 401 | + 'restore_questions' => esc_html__('Restore', 'event_espresso'), |
|
| 402 | + ), |
|
| 403 | + ); |
|
| 404 | + } |
|
| 405 | + } |
|
| 406 | + |
|
| 407 | + |
|
| 408 | + /** |
|
| 409 | + * @return void |
|
| 410 | + */ |
|
| 411 | + protected function _set_list_table_views_question_groups() |
|
| 412 | + { |
|
| 413 | + $this->_views = array( |
|
| 414 | + 'all' => array( |
|
| 415 | + 'slug' => 'all', |
|
| 416 | + 'label' => esc_html__('All', 'event_espresso'), |
|
| 417 | + 'count' => 0, |
|
| 418 | + 'bulk_action' => array( |
|
| 419 | + 'trash_question_groups' => esc_html__('Trash', 'event_espresso'), |
|
| 420 | + ), |
|
| 421 | + ), |
|
| 422 | + ); |
|
| 423 | + |
|
| 424 | + if (EE_Registry::instance()->CAP->current_user_can( |
|
| 425 | + 'ee_delete_question_groups', |
|
| 426 | + 'espresso_registration_form_trash_question_groups' |
|
| 427 | + ) |
|
| 428 | + ) { |
|
| 429 | + $this->_views['trash'] = array( |
|
| 430 | + 'slug' => 'trash', |
|
| 431 | + 'label' => esc_html__('Trash', 'event_espresso'), |
|
| 432 | + 'count' => 0, |
|
| 433 | + 'bulk_action' => array( |
|
| 434 | + 'delete_question_groups' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 435 | + 'restore_question_groups' => esc_html__('Restore', 'event_espresso'), |
|
| 436 | + ), |
|
| 437 | + ); |
|
| 438 | + } |
|
| 439 | + } |
|
| 440 | + |
|
| 441 | + |
|
| 442 | + /** |
|
| 443 | + * @return void |
|
| 444 | + * @throws EE_Error |
|
| 445 | + * @throws InvalidArgumentException |
|
| 446 | + * @throws InvalidDataTypeException |
|
| 447 | + * @throws InvalidInterfaceException |
|
| 448 | + */ |
|
| 449 | + protected function _questions_overview_list_table() |
|
| 450 | + { |
|
| 451 | + $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 452 | + 'add_question', |
|
| 453 | + 'add_question', |
|
| 454 | + array(), |
|
| 455 | + 'add-new-h2' |
|
| 456 | + ); |
|
| 457 | + parent::_questions_overview_list_table(); |
|
| 458 | + } |
|
| 459 | + |
|
| 460 | + |
|
| 461 | + /** |
|
| 462 | + * @return void |
|
| 463 | + * @throws DomainException |
|
| 464 | + * @throws EE_Error |
|
| 465 | + * @throws InvalidArgumentException |
|
| 466 | + * @throws InvalidDataTypeException |
|
| 467 | + * @throws InvalidInterfaceException |
|
| 468 | + */ |
|
| 469 | + protected function _question_groups_overview_list_table() |
|
| 470 | + { |
|
| 471 | + $this->_search_btn_label = esc_html__('Question Groups', 'event_espresso'); |
|
| 472 | + $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 473 | + 'add_question_group', |
|
| 474 | + 'add_question_group', |
|
| 475 | + array(), |
|
| 476 | + 'add-new-h2' |
|
| 477 | + ); |
|
| 478 | + $this->display_admin_list_table_page_with_sidebar(); |
|
| 479 | + } |
|
| 480 | + |
|
| 481 | + |
|
| 482 | + /** |
|
| 483 | + * @return void |
|
| 484 | + * @throws EE_Error |
|
| 485 | + * @throws InvalidArgumentException |
|
| 486 | + * @throws InvalidDataTypeException |
|
| 487 | + * @throws InvalidInterfaceException |
|
| 488 | + */ |
|
| 489 | + protected function _delete_question() |
|
| 490 | + { |
|
| 491 | + $success = $this->_delete_items($this->_question_model); |
|
| 492 | + $this->_redirect_after_action( |
|
| 493 | + $success, |
|
| 494 | + $this->_question_model->item_name($success), |
|
| 495 | + 'deleted', |
|
| 496 | + array('action' => 'default', 'status' => 'all') |
|
| 497 | + ); |
|
| 498 | + } |
|
| 499 | + |
|
| 500 | + |
|
| 501 | + /** |
|
| 502 | + * @return void |
|
| 503 | + * @throws EE_Error |
|
| 504 | + * @throws InvalidArgumentException |
|
| 505 | + * @throws InvalidDataTypeException |
|
| 506 | + * @throws InvalidInterfaceException |
|
| 507 | + */ |
|
| 508 | + protected function _delete_questions() |
|
| 509 | + { |
|
| 510 | + $success = $this->_delete_items($this->_question_model); |
|
| 511 | + $this->_redirect_after_action( |
|
| 512 | + $success, |
|
| 513 | + $this->_question_model->item_name($success), |
|
| 514 | + 'deleted permanently', |
|
| 515 | + array('action' => 'default', 'status' => 'trash') |
|
| 516 | + ); |
|
| 517 | + } |
|
| 518 | + |
|
| 519 | + |
|
| 520 | + /** |
|
| 521 | + * Performs the deletion of a single or multiple questions or question groups. |
|
| 522 | + * |
|
| 523 | + * @param EEM_Soft_Delete_Base $model |
|
| 524 | + * @return int number of items deleted permanently |
|
| 525 | + * @throws EE_Error |
|
| 526 | + * @throws InvalidArgumentException |
|
| 527 | + * @throws InvalidDataTypeException |
|
| 528 | + * @throws InvalidInterfaceException |
|
| 529 | + */ |
|
| 530 | + private function _delete_items(EEM_Soft_Delete_Base $model) |
|
| 531 | + { |
|
| 532 | + $success = 0; |
|
| 533 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 534 | + if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 535 | + // if array has more than one element than success message should be plural |
|
| 536 | + $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1; |
|
| 537 | + // cycle thru bulk action checkboxes |
|
| 538 | + while (list($ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 539 | + if (! $this->_delete_item($ID, $model)) { |
|
| 540 | + $success = 0; |
|
| 541 | + } |
|
| 542 | + } |
|
| 543 | + } elseif (! empty($this->_req_data['QSG_ID'])) { |
|
| 544 | + $success = $this->_delete_item($this->_req_data['QSG_ID'], $model); |
|
| 545 | + } elseif (! empty($this->_req_data['QST_ID'])) { |
|
| 546 | + $success = $this->_delete_item($this->_req_data['QST_ID'], $model); |
|
| 547 | + } else { |
|
| 548 | + EE_Error::add_error( |
|
| 549 | + sprintf( |
|
| 550 | + esc_html__( |
|
| 551 | + "No Questions or Question Groups were selected for deleting. This error usually shows when you've attempted to delete via bulk action but there were no selections.", |
|
| 552 | + "event_espresso" |
|
| 553 | + ) |
|
| 554 | + ), |
|
| 555 | + __FILE__, |
|
| 556 | + __FUNCTION__, |
|
| 557 | + __LINE__ |
|
| 558 | + ); |
|
| 559 | + } |
|
| 560 | + return $success; |
|
| 561 | + } |
|
| 562 | + |
|
| 563 | + |
|
| 564 | + /** |
|
| 565 | + * Deletes the specified question (and its associated question options) or question group |
|
| 566 | + * |
|
| 567 | + * @param int $id |
|
| 568 | + * @param EEM_Soft_Delete_Base $model |
|
| 569 | + * @return boolean |
|
| 570 | + * @throws EE_Error |
|
| 571 | + * @throws InvalidArgumentException |
|
| 572 | + * @throws InvalidDataTypeException |
|
| 573 | + * @throws InvalidInterfaceException |
|
| 574 | + */ |
|
| 575 | + protected function _delete_item($id, $model) |
|
| 576 | + { |
|
| 577 | + if ($model instanceof EEM_Question) { |
|
| 578 | + EEM_Question_Option::instance()->delete_permanently(array(array('QST_ID' => absint($id)))); |
|
| 579 | + } |
|
| 580 | + return $model->delete_permanently_by_ID(absint($id)); |
|
| 581 | + } |
|
| 582 | + |
|
| 583 | + |
|
| 584 | + /****************************** QUESTION GROUPS ******************************/ |
|
| 585 | + |
|
| 586 | + |
|
| 587 | + /** |
|
| 588 | + * @param string $type |
|
| 589 | + * @return void |
|
| 590 | + * @throws DomainException |
|
| 591 | + * @throws EE_Error |
|
| 592 | + * @throws InvalidArgumentException |
|
| 593 | + * @throws InvalidDataTypeException |
|
| 594 | + * @throws InvalidInterfaceException |
|
| 595 | + */ |
|
| 596 | + protected function _edit_question_group($type = 'add') |
|
| 597 | + { |
|
| 598 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 599 | + $ID = isset($this->_req_data['QSG_ID']) && ! empty($this->_req_data['QSG_ID']) |
|
| 600 | + ? absint($this->_req_data['QSG_ID']) |
|
| 601 | + : false; |
|
| 602 | + |
|
| 603 | + switch ($this->_req_action) { |
|
| 604 | + case 'add_question_group': |
|
| 605 | + $this->_admin_page_title = esc_html__('Add Question Group', 'event_espresso'); |
|
| 606 | + break; |
|
| 607 | + case 'edit_question_group': |
|
| 608 | + $this->_admin_page_title = esc_html__('Edit Question Group', 'event_espresso'); |
|
| 609 | + break; |
|
| 610 | + default: |
|
| 611 | + $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action)); |
|
| 612 | + } |
|
| 613 | + // add ID to title if editing |
|
| 614 | + $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title; |
|
| 615 | + if ($ID) { |
|
| 616 | + /** @var EE_Question_Group $questionGroup */ |
|
| 617 | + $questionGroup = $this->_question_group_model->get_one_by_ID($ID); |
|
| 618 | + $additional_hidden_fields = array('QSG_ID' => array('type' => 'hidden', 'value' => $ID)); |
|
| 619 | + $this->_set_add_edit_form_tags('update_question_group', $additional_hidden_fields); |
|
| 620 | + } else { |
|
| 621 | + /** @var EE_Question_Group $questionGroup */ |
|
| 622 | + $questionGroup = EEM_Question_Group::instance()->create_default_object(); |
|
| 623 | + $questionGroup->set_order_to_latest(); |
|
| 624 | + $this->_set_add_edit_form_tags('insert_question_group'); |
|
| 625 | + } |
|
| 626 | + $this->_template_args['values'] = $this->_yes_no_values; |
|
| 627 | + $this->_template_args['all_questions'] = $questionGroup->questions_in_and_not_in_group(); |
|
| 628 | + $this->_template_args['QSG_ID'] = $ID ? $ID : true; |
|
| 629 | + $this->_template_args['question_group'] = $questionGroup; |
|
| 630 | + |
|
| 631 | + $redirect_URL = add_query_arg(array('action' => 'question_groups'), $this->_admin_base_url); |
|
| 632 | + $this->_set_publish_post_box_vars('id', $ID, false, $redirect_URL); |
|
| 633 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
| 634 | + REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'question_groups_main_meta_box.template.php', |
|
| 635 | + $this->_template_args, |
|
| 636 | + true |
|
| 637 | + ); |
|
| 638 | + |
|
| 639 | + // the details template wrapper |
|
| 640 | + $this->display_admin_page_with_sidebar(); |
|
| 641 | + } |
|
| 642 | + |
|
| 643 | + |
|
| 644 | + /** |
|
| 645 | + * @return void |
|
| 646 | + * @throws EE_Error |
|
| 647 | + * @throws InvalidArgumentException |
|
| 648 | + * @throws InvalidDataTypeException |
|
| 649 | + * @throws InvalidInterfaceException |
|
| 650 | + */ |
|
| 651 | + protected function _delete_question_groups() |
|
| 652 | + { |
|
| 653 | + $success = $this->_delete_items($this->_question_group_model); |
|
| 654 | + $this->_redirect_after_action( |
|
| 655 | + $success, |
|
| 656 | + $this->_question_group_model->item_name($success), |
|
| 657 | + 'deleted permanently', |
|
| 658 | + array('action' => 'question_groups', 'status' => 'trash') |
|
| 659 | + ); |
|
| 660 | + } |
|
| 661 | + |
|
| 662 | + |
|
| 663 | + /** |
|
| 664 | + * @param bool $new_question_group |
|
| 665 | + * @throws EE_Error |
|
| 666 | + * @throws InvalidArgumentException |
|
| 667 | + * @throws InvalidDataTypeException |
|
| 668 | + * @throws InvalidInterfaceException |
|
| 669 | + */ |
|
| 670 | + protected function _insert_or_update_question_group($new_question_group = true) |
|
| 671 | + { |
|
| 672 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 673 | + $set_column_values = $this->_set_column_values_for($this->_question_group_model); |
|
| 674 | + if ($new_question_group) { |
|
| 675 | + // make sure identifier is unique |
|
| 676 | + $identifier_value = isset($set_column_values['QSG_identifier']) ? $set_column_values['QSG_identifier'] : ''; |
|
| 677 | + $identifier_exists = ! empty($identifier_value) |
|
| 678 | + ? $this->_question_group_model->count([['QSG_identifier' => $set_column_values['QSG_identifier']]]) > 0 |
|
| 679 | + : false; |
|
| 680 | + if ($identifier_exists) { |
|
| 681 | + $set_column_values['QSG_identifier'] .= uniqid('id', true); |
|
| 682 | + } |
|
| 683 | + $QSG_ID = $this->_question_group_model->insert($set_column_values); |
|
| 684 | + $success = $QSG_ID ? 1 : 0; |
|
| 685 | + if ($success === 0) { |
|
| 686 | + EE_Error::add_error( |
|
| 687 | + esc_html__('Something went wrong saving the question group.', 'event_espresso'), |
|
| 688 | + __FILE__, |
|
| 689 | + __FUNCTION__, |
|
| 690 | + __LINE__ |
|
| 691 | + ); |
|
| 692 | + $this->_redirect_after_action( |
|
| 693 | + false, |
|
| 694 | + '', |
|
| 695 | + '', |
|
| 696 | + array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID), |
|
| 697 | + true |
|
| 698 | + ); |
|
| 699 | + } |
|
| 700 | + } else { |
|
| 701 | + $QSG_ID = absint($this->_req_data['QSG_ID']); |
|
| 702 | + unset($set_column_values['QSG_ID']); |
|
| 703 | + $success = $this->_question_group_model->update($set_column_values, array(array('QSG_ID' => $QSG_ID))); |
|
| 704 | + } |
|
| 705 | + |
|
| 706 | + $phone_question_id = EEM_Question::instance()->get_Question_ID_from_system_string( |
|
| 707 | + EEM_Attendee::system_question_phone |
|
| 708 | + ); |
|
| 709 | + // update the existing related questions |
|
| 710 | + // BUT FIRST... delete the phone question from the Question_Group_Question |
|
| 711 | + // if it is being added to this question group (therefore removed from the existing group) |
|
| 712 | + if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $phone_question_id ])) { |
|
| 713 | + // delete where QST ID = system phone question ID and Question Group ID is NOT this group |
|
| 714 | + EEM_Question_Group_Question::instance()->delete( |
|
| 715 | + array( |
|
| 716 | + array( |
|
| 717 | + 'QST_ID' => $phone_question_id, |
|
| 718 | + 'QSG_ID' => array('!=', $QSG_ID), |
|
| 719 | + ), |
|
| 720 | + ) |
|
| 721 | + ); |
|
| 722 | + } |
|
| 723 | + /** @type EE_Question_Group $question_group */ |
|
| 724 | + $question_group = $this->_question_group_model->get_one_by_ID($QSG_ID); |
|
| 725 | + $questions = $question_group->questions(); |
|
| 726 | + // make sure system phone question is added to list of questions for this group |
|
| 727 | + if (! isset($questions[ $phone_question_id ])) { |
|
| 728 | + $questions[ $phone_question_id ] = EEM_Question::instance()->get_one_by_ID($phone_question_id); |
|
| 729 | + } |
|
| 730 | + |
|
| 731 | + foreach ($questions as $question_ID => $question) { |
|
| 732 | + // first we always check for order. |
|
| 733 | + if (! empty($this->_req_data['question_orders'][ $question_ID ])) { |
|
| 734 | + // update question order |
|
| 735 | + $question_group->update_question_order( |
|
| 736 | + $question_ID, |
|
| 737 | + $this->_req_data['question_orders'][ $question_ID ] |
|
| 738 | + ); |
|
| 739 | + } |
|
| 740 | + |
|
| 741 | + // then we always check if adding or removing. |
|
| 742 | + if (isset($this->_req_data['questions'], $this->_req_data['questions'][ $question_ID ])) { |
|
| 743 | + $question_group->add_question($question_ID); |
|
| 744 | + } else { |
|
| 745 | + // not found, remove it (but only if not a system question for the personal group |
|
| 746 | + // with the exception of lname system question - we allow removal of it) |
|
| 747 | + if (in_array( |
|
| 748 | + $question->system_ID(), |
|
| 749 | + EEM_Question::instance()->required_system_questions_in_system_question_group( |
|
| 750 | + $question_group->system_group() |
|
| 751 | + ) |
|
| 752 | + )) { |
|
| 753 | + continue; |
|
| 754 | + } else { |
|
| 755 | + $question_group->remove_question($question_ID); |
|
| 756 | + } |
|
| 757 | + } |
|
| 758 | + } |
|
| 759 | + // save new related questions |
|
| 760 | + if (isset($this->_req_data['questions'])) { |
|
| 761 | + foreach ($this->_req_data['questions'] as $QST_ID) { |
|
| 762 | + $question_group->add_question($QST_ID); |
|
| 763 | + if (isset($this->_req_data['question_orders'][ $QST_ID ])) { |
|
| 764 | + $question_group->update_question_order($QST_ID, $this->_req_data['question_orders'][ $QST_ID ]); |
|
| 765 | + } |
|
| 766 | + } |
|
| 767 | + } |
|
| 768 | + |
|
| 769 | + if ($success !== false) { |
|
| 770 | + $msg = $new_question_group |
|
| 771 | + ? sprintf( |
|
| 772 | + esc_html__('The %s has been created', 'event_espresso'), |
|
| 773 | + $this->_question_group_model->item_name() |
|
| 774 | + ) |
|
| 775 | + : sprintf( |
|
| 776 | + esc_html__( |
|
| 777 | + 'The %s has been updated', |
|
| 778 | + 'event_espresso' |
|
| 779 | + ), |
|
| 780 | + $this->_question_group_model->item_name() |
|
| 781 | + ); |
|
| 782 | + EE_Error::add_success($msg); |
|
| 783 | + } |
|
| 784 | + $this->_redirect_after_action( |
|
| 785 | + false, |
|
| 786 | + '', |
|
| 787 | + '', |
|
| 788 | + array('action' => 'edit_question_group', 'QSG_ID' => $QSG_ID), |
|
| 789 | + true |
|
| 790 | + ); |
|
| 791 | + } |
|
| 792 | + |
|
| 793 | + |
|
| 794 | + /** |
|
| 795 | + * duplicates a question and all its question options and redirects to the new question. |
|
| 796 | + * |
|
| 797 | + * @return void |
|
| 798 | + * @throws EE_Error |
|
| 799 | + * @throws InvalidArgumentException |
|
| 800 | + * @throws ReflectionException |
|
| 801 | + * @throws InvalidDataTypeException |
|
| 802 | + * @throws InvalidInterfaceException |
|
| 803 | + */ |
|
| 804 | + public function _duplicate_question() |
|
| 805 | + { |
|
| 806 | + $question_ID = (int) $this->_req_data['QST_ID']; |
|
| 807 | + $question = EEM_Question::instance()->get_one_by_ID($question_ID); |
|
| 808 | + if ($question instanceof EE_Question) { |
|
| 809 | + $new_question = $question->duplicate(); |
|
| 810 | + if ($new_question instanceof EE_Question) { |
|
| 811 | + $this->_redirect_after_action( |
|
| 812 | + true, |
|
| 813 | + esc_html__('Question', 'event_espresso'), |
|
| 814 | + esc_html__('Duplicated', 'event_espresso'), |
|
| 815 | + array('action' => 'edit_question', 'QST_ID' => $new_question->ID()), |
|
| 816 | + true |
|
| 817 | + ); |
|
| 818 | + } else { |
|
| 819 | + global $wpdb; |
|
| 820 | + EE_Error::add_error( |
|
| 821 | + sprintf( |
|
| 822 | + esc_html__( |
|
| 823 | + 'Could not duplicate question with ID %1$d because: %2$s', |
|
| 824 | + 'event_espresso' |
|
| 825 | + ), |
|
| 826 | + $question_ID, |
|
| 827 | + $wpdb->last_error |
|
| 828 | + ), |
|
| 829 | + __FILE__, |
|
| 830 | + __FUNCTION__, |
|
| 831 | + __LINE__ |
|
| 832 | + ); |
|
| 833 | + $this->_redirect_after_action(false, '', '', array('action' => 'default'), false); |
|
| 834 | + } |
|
| 835 | + } else { |
|
| 836 | + EE_Error::add_error( |
|
| 837 | + sprintf( |
|
| 838 | + esc_html__( |
|
| 839 | + 'Could not duplicate question with ID %d because it didn\'t exist!', |
|
| 840 | + 'event_espresso' |
|
| 841 | + ), |
|
| 842 | + $question_ID |
|
| 843 | + ), |
|
| 844 | + __FILE__, |
|
| 845 | + __FUNCTION__, |
|
| 846 | + __LINE__ |
|
| 847 | + ); |
|
| 848 | + $this->_redirect_after_action(false, '', '', array('action' => 'default'), false); |
|
| 849 | + } |
|
| 850 | + } |
|
| 851 | + |
|
| 852 | + |
|
| 853 | + /** |
|
| 854 | + * @param bool $trash |
|
| 855 | + * @throws EE_Error |
|
| 856 | + */ |
|
| 857 | + protected function _trash_or_restore_question_groups($trash = true) |
|
| 858 | + { |
|
| 859 | + $this->_trash_or_restore_items($this->_question_group_model, $trash); |
|
| 860 | + } |
|
| 861 | + |
|
| 862 | + |
|
| 863 | + /** |
|
| 864 | + *_trash_question |
|
| 865 | + * |
|
| 866 | + * @return void |
|
| 867 | + * @throws EE_Error |
|
| 868 | + */ |
|
| 869 | + protected function _trash_question() |
|
| 870 | + { |
|
| 871 | + $success = $this->_question_model->delete_by_ID((int) $this->_req_data['QST_ID']); |
|
| 872 | + $query_args = array('action' => 'default', 'status' => 'all'); |
|
| 873 | + $this->_redirect_after_action($success, $this->_question_model->item_name($success), 'trashed', $query_args); |
|
| 874 | + } |
|
| 875 | + |
|
| 876 | + |
|
| 877 | + /** |
|
| 878 | + * @param bool $trash |
|
| 879 | + * @throws EE_Error |
|
| 880 | + */ |
|
| 881 | + protected function _trash_or_restore_questions($trash = true) |
|
| 882 | + { |
|
| 883 | + $this->_trash_or_restore_items($this->_question_model, $trash); |
|
| 884 | + } |
|
| 885 | + |
|
| 886 | + |
|
| 887 | + /** |
|
| 888 | + * Internally used to delete or restore items, using the request data. Meant to be |
|
| 889 | + * flexible between question or question groups |
|
| 890 | + * |
|
| 891 | + * @param EEM_Soft_Delete_Base $model |
|
| 892 | + * @param boolean $trash whether to trash or restore |
|
| 893 | + * @throws EE_Error |
|
| 894 | + */ |
|
| 895 | + private function _trash_or_restore_items(EEM_Soft_Delete_Base $model, $trash = true) |
|
| 896 | + { |
|
| 897 | + |
|
| 898 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 899 | + |
|
| 900 | + $success = 1; |
|
| 901 | + // Checkboxes |
|
| 902 | + // echo "trash $trash"; |
|
| 903 | + // var_dump($this->_req_data['checkbox']);die; |
|
| 904 | + if (isset($this->_req_data['checkbox'])) { |
|
| 905 | + if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) { |
|
| 906 | + // if array has more than one element than success message should be plural |
|
| 907 | + $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1; |
|
| 908 | + // cycle thru bulk action checkboxes |
|
| 909 | + while (list($ID, $value) = each($this->_req_data['checkbox'])) { |
|
| 910 | + if (! $model->delete_or_restore_by_ID($trash, absint($ID))) { |
|
| 911 | + $success = 0; |
|
| 912 | + } |
|
| 913 | + } |
|
| 914 | + } else { |
|
| 915 | + // grab single id and delete |
|
| 916 | + $ID = absint($this->_req_data['checkbox']); |
|
| 917 | + if (! $model->delete_or_restore_by_ID($trash, $ID)) { |
|
| 918 | + $success = 0; |
|
| 919 | + } |
|
| 920 | + } |
|
| 921 | + } else { |
|
| 922 | + // delete via trash link |
|
| 923 | + // grab single id and delete |
|
| 924 | + $ID = absint($this->_req_data[ $model->primary_key_name() ]); |
|
| 925 | + if (! $model->delete_or_restore_by_ID($trash, $ID)) { |
|
| 926 | + $success = 0; |
|
| 927 | + } |
|
| 928 | + } |
|
| 929 | + |
|
| 930 | + |
|
| 931 | + $action = $model instanceof EEM_Question ? 'default' : 'question_groups';// strtolower( $model->item_name(2) ); |
|
| 932 | + // echo "action :$action"; |
|
| 933 | + // $action = 'questions' ? 'default' : $action; |
|
| 934 | + if ($trash) { |
|
| 935 | + $action_desc = 'trashed'; |
|
| 936 | + $status = 'trash'; |
|
| 937 | + } else { |
|
| 938 | + $action_desc = 'restored'; |
|
| 939 | + $status = 'all'; |
|
| 940 | + } |
|
| 941 | + $this->_redirect_after_action( |
|
| 942 | + $success, |
|
| 943 | + $model->item_name($success), |
|
| 944 | + $action_desc, |
|
| 945 | + array('action' => $action, 'status' => $status) |
|
| 946 | + ); |
|
| 947 | + } |
|
| 948 | + |
|
| 949 | + |
|
| 950 | + /** |
|
| 951 | + * @param $per_page |
|
| 952 | + * @param int $current_page |
|
| 953 | + * @param bool|false $count |
|
| 954 | + * @return EE_Soft_Delete_Base_Class[]|int |
|
| 955 | + * @throws EE_Error |
|
| 956 | + * @throws InvalidArgumentException |
|
| 957 | + * @throws InvalidDataTypeException |
|
| 958 | + * @throws InvalidInterfaceException |
|
| 959 | + */ |
|
| 960 | + public function get_trashed_questions($per_page, $current_page = 1, $count = false) |
|
| 961 | + { |
|
| 962 | + $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page); |
|
| 963 | + |
|
| 964 | + if ($count) { |
|
| 965 | + // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items |
|
| 966 | + $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
| 967 | + $results = $this->_question_model->count_deleted($where); |
|
| 968 | + } else { |
|
| 969 | + // note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items |
|
| 970 | + $results = $this->_question_model->get_all_deleted($query_params); |
|
| 971 | + } |
|
| 972 | + return $results; |
|
| 973 | + } |
|
| 974 | + |
|
| 975 | + |
|
| 976 | + /** |
|
| 977 | + * @param $per_page |
|
| 978 | + * @param int $current_page |
|
| 979 | + * @param bool|false $count |
|
| 980 | + * @return EE_Soft_Delete_Base_Class[]|int |
|
| 981 | + * @throws EE_Error |
|
| 982 | + * @throws InvalidArgumentException |
|
| 983 | + * @throws InvalidDataTypeException |
|
| 984 | + * @throws InvalidInterfaceException |
|
| 985 | + */ |
|
| 986 | + public function get_question_groups($per_page, $current_page = 1, $count = false) |
|
| 987 | + { |
|
| 988 | + $questionGroupModel = EEM_Question_Group::instance(); |
|
| 989 | + $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page); |
|
| 990 | + if ($count) { |
|
| 991 | + $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
| 992 | + $results = $questionGroupModel->count($where); |
|
| 993 | + } else { |
|
| 994 | + $results = $questionGroupModel->get_all($query_params); |
|
| 995 | + } |
|
| 996 | + return $results; |
|
| 997 | + } |
|
| 998 | + |
|
| 999 | + |
|
| 1000 | + /** |
|
| 1001 | + * @param $per_page |
|
| 1002 | + * @param int $current_page |
|
| 1003 | + * @param bool $count |
|
| 1004 | + * @return EE_Soft_Delete_Base_Class[]|int |
|
| 1005 | + * @throws EE_Error |
|
| 1006 | + * @throws InvalidArgumentException |
|
| 1007 | + * @throws InvalidDataTypeException |
|
| 1008 | + * @throws InvalidInterfaceException |
|
| 1009 | + */ |
|
| 1010 | + public function get_trashed_question_groups($per_page, $current_page = 1, $count = false) |
|
| 1011 | + { |
|
| 1012 | + $questionGroupModel = EEM_Question_Group::instance(); |
|
| 1013 | + $query_params = $this->get_query_params($questionGroupModel, $per_page, $current_page); |
|
| 1014 | + if ($count) { |
|
| 1015 | + $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
| 1016 | + $query_params['limit'] = null; |
|
| 1017 | + $results = $questionGroupModel->count_deleted($where); |
|
| 1018 | + } else { |
|
| 1019 | + $results = $questionGroupModel->get_all_deleted($query_params); |
|
| 1020 | + } |
|
| 1021 | + return $results; |
|
| 1022 | + } |
|
| 1023 | + |
|
| 1024 | + |
|
| 1025 | + /** |
|
| 1026 | + * method for performing updates to question order |
|
| 1027 | + * |
|
| 1028 | + * @return void results array |
|
| 1029 | + * @throws EE_Error |
|
| 1030 | + * @throws InvalidArgumentException |
|
| 1031 | + * @throws InvalidDataTypeException |
|
| 1032 | + * @throws InvalidInterfaceException |
|
| 1033 | + */ |
|
| 1034 | + public function update_question_group_order() |
|
| 1035 | + { |
|
| 1036 | + |
|
| 1037 | + $success = esc_html__('Question group order was updated successfully.', 'event_espresso'); |
|
| 1038 | + |
|
| 1039 | + // grab our row IDs |
|
| 1040 | + $row_ids = isset($this->_req_data['row_ids']) && ! empty($this->_req_data['row_ids']) |
|
| 1041 | + ? explode(',', rtrim($this->_req_data['row_ids'], ',')) |
|
| 1042 | + : array(); |
|
| 1043 | + |
|
| 1044 | + $perpage = ! empty($this->_req_data['perpage']) |
|
| 1045 | + ? (int) $this->_req_data['perpage'] |
|
| 1046 | + : null; |
|
| 1047 | + $curpage = ! empty($this->_req_data['curpage']) |
|
| 1048 | + ? (int) $this->_req_data['curpage'] |
|
| 1049 | + : null; |
|
| 1050 | + |
|
| 1051 | + if (! empty($row_ids)) { |
|
| 1052 | + // figure out where we start the row_id count at for the current page. |
|
| 1053 | + $qsgcount = empty($curpage) ? 0 : ($curpage - 1) * $perpage; |
|
| 1054 | + |
|
| 1055 | + $row_count = count($row_ids); |
|
| 1056 | + for ($i = 0; $i < $row_count; $i++) { |
|
| 1057 | + // Update the questions when re-ordering |
|
| 1058 | + $updated = EEM_Question_Group::instance()->update( |
|
| 1059 | + array('QSG_order' => $qsgcount), |
|
| 1060 | + array(array('QSG_ID' => $row_ids[ $i ])) |
|
| 1061 | + ); |
|
| 1062 | + if ($updated === false) { |
|
| 1063 | + $success = false; |
|
| 1064 | + } |
|
| 1065 | + $qsgcount++; |
|
| 1066 | + } |
|
| 1067 | + } else { |
|
| 1068 | + $success = false; |
|
| 1069 | + } |
|
| 1070 | + |
|
| 1071 | + $errors = ! $success |
|
| 1072 | + ? esc_html__('An error occurred. The question group order was not updated.', 'event_espresso') |
|
| 1073 | + : false; |
|
| 1074 | + |
|
| 1075 | + echo wp_json_encode(array('return_data' => false, 'success' => $success, 'errors' => $errors)); |
|
| 1076 | + die(); |
|
| 1077 | + } |
|
| 1078 | + |
|
| 1079 | + |
|
| 1080 | + |
|
| 1081 | + /*************************************** REGISTRATION SETTINGS ***************************************/ |
|
| 1082 | + |
|
| 1083 | + |
|
| 1084 | + /** |
|
| 1085 | + * @throws DomainException |
|
| 1086 | + * @throws EE_Error |
|
| 1087 | + * @throws InvalidArgumentException |
|
| 1088 | + * @throws InvalidDataTypeException |
|
| 1089 | + * @throws InvalidInterfaceException |
|
| 1090 | + */ |
|
| 1091 | + protected function _reg_form_settings() |
|
| 1092 | + { |
|
| 1093 | + $this->_template_args['values'] = $this->_yes_no_values; |
|
| 1094 | + add_action( |
|
| 1095 | + 'AHEE__Extend_Registration_Form_Admin_Page___reg_form_settings_template', |
|
| 1096 | + array($this, 'email_validation_settings_form'), |
|
| 1097 | + 2 |
|
| 1098 | + ); |
|
| 1099 | + $this->_template_args = (array) apply_filters( |
|
| 1100 | + 'FHEE__Extend_Registration_Form_Admin_Page___reg_form_settings___template_args', |
|
| 1101 | + $this->_template_args |
|
| 1102 | + ); |
|
| 1103 | + $this->_set_add_edit_form_tags('update_reg_form_settings'); |
|
| 1104 | + $this->_set_publish_post_box_vars(null, false, false, null, false); |
|
| 1105 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
| 1106 | + REGISTRATION_FORM_CAF_TEMPLATE_PATH . 'reg_form_settings.template.php', |
|
| 1107 | + $this->_template_args, |
|
| 1108 | + true |
|
| 1109 | + ); |
|
| 1110 | + $this->display_admin_page_with_sidebar(); |
|
| 1111 | + } |
|
| 1112 | + |
|
| 1113 | + |
|
| 1114 | + /** |
|
| 1115 | + * @return void |
|
| 1116 | + * @throws EE_Error |
|
| 1117 | + * @throws InvalidArgumentException |
|
| 1118 | + * @throws ReflectionException |
|
| 1119 | + * @throws InvalidDataTypeException |
|
| 1120 | + * @throws InvalidInterfaceException |
|
| 1121 | + */ |
|
| 1122 | + protected function _update_reg_form_settings() |
|
| 1123 | + { |
|
| 1124 | + EE_Registry::instance()->CFG->registration = $this->update_email_validation_settings_form( |
|
| 1125 | + EE_Registry::instance()->CFG->registration |
|
| 1126 | + ); |
|
| 1127 | + EE_Registry::instance()->CFG->registration = apply_filters( |
|
| 1128 | + 'FHEE__Extend_Registration_Form_Admin_Page___update_reg_form_settings__CFG_registration', |
|
| 1129 | + EE_Registry::instance()->CFG->registration |
|
| 1130 | + ); |
|
| 1131 | + $success = $this->_update_espresso_configuration( |
|
| 1132 | + esc_html__('Registration Form Options', 'event_espresso'), |
|
| 1133 | + EE_Registry::instance()->CFG, |
|
| 1134 | + __FILE__, |
|
| 1135 | + __FUNCTION__, |
|
| 1136 | + __LINE__ |
|
| 1137 | + ); |
|
| 1138 | + $this->_redirect_after_action( |
|
| 1139 | + $success, |
|
| 1140 | + esc_html__('Registration Form Options', 'event_espresso'), |
|
| 1141 | + 'updated', |
|
| 1142 | + array('action' => 'view_reg_form_settings') |
|
| 1143 | + ); |
|
| 1144 | + } |
|
| 1145 | + |
|
| 1146 | + |
|
| 1147 | + /** |
|
| 1148 | + * @return void |
|
| 1149 | + * @throws EE_Error |
|
| 1150 | + * @throws InvalidArgumentException |
|
| 1151 | + * @throws InvalidDataTypeException |
|
| 1152 | + * @throws InvalidInterfaceException |
|
| 1153 | + */ |
|
| 1154 | + public function email_validation_settings_form() |
|
| 1155 | + { |
|
| 1156 | + echo $this->_email_validation_settings_form()->get_html(); |
|
| 1157 | + } |
|
| 1158 | + |
|
| 1159 | + |
|
| 1160 | + /** |
|
| 1161 | + * _email_validation_settings_form |
|
| 1162 | + * |
|
| 1163 | + * @access protected |
|
| 1164 | + * @return EE_Form_Section_Proper |
|
| 1165 | + * @throws \EE_Error |
|
| 1166 | + */ |
|
| 1167 | + protected function _email_validation_settings_form() |
|
| 1168 | + { |
|
| 1169 | + return new EE_Form_Section_Proper( |
|
| 1170 | + array( |
|
| 1171 | + 'name' => 'email_validation_settings', |
|
| 1172 | + 'html_id' => 'email_validation_settings', |
|
| 1173 | + 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
| 1174 | + 'subsections' => apply_filters( |
|
| 1175 | + 'FHEE__Extend_Registration_Form_Admin_Page___email_validation_settings_form__form_subsections', |
|
| 1176 | + array( |
|
| 1177 | + 'email_validation_hdr' => new EE_Form_Section_HTML( |
|
| 1178 | + EEH_HTML::h2(esc_html__('Email Validation Settings', 'event_espresso')) |
|
| 1179 | + ), |
|
| 1180 | + 'email_validation_level' => new EE_Select_Input( |
|
| 1181 | + array( |
|
| 1182 | + 'basic' => esc_html__('Basic', 'event_espresso'), |
|
| 1183 | + 'wp_default' => esc_html__('WordPress Default', 'event_espresso'), |
|
| 1184 | + 'i18n' => esc_html__('International', 'event_espresso'), |
|
| 1185 | + 'i18n_dns' => esc_html__('International + DNS Check', 'event_espresso'), |
|
| 1186 | + ), |
|
| 1187 | + array( |
|
| 1188 | + 'html_label_text' => esc_html__('Email Validation Level', 'event_espresso') |
|
| 1189 | + . EEH_Template::get_help_tab_link('email_validation_info'), |
|
| 1190 | + 'html_help_text' => esc_html__( |
|
| 1191 | + 'These levels range from basic validation ( ie: [email protected] ) to more advanced checks against international email addresses (ie: üñîçøðé@example.com ) with additional MX and A record checks to confirm the domain actually exists. More information on on each level can be found within the help section.', |
|
| 1192 | + 'event_espresso' |
|
| 1193 | + ), |
|
| 1194 | + 'default' => isset( |
|
| 1195 | + EE_Registry::instance()->CFG->registration->email_validation_level |
|
| 1196 | + ) |
|
| 1197 | + ? EE_Registry::instance()->CFG->registration->email_validation_level |
|
| 1198 | + : 'wp_default', |
|
| 1199 | + 'required' => false, |
|
| 1200 | + ) |
|
| 1201 | + ), |
|
| 1202 | + ) |
|
| 1203 | + ), |
|
| 1204 | + ) |
|
| 1205 | + ); |
|
| 1206 | + } |
|
| 1207 | + |
|
| 1208 | + |
|
| 1209 | + /** |
|
| 1210 | + * @param EE_Registration_Config $EE_Registration_Config |
|
| 1211 | + * @return EE_Registration_Config |
|
| 1212 | + * @throws EE_Error |
|
| 1213 | + * @throws InvalidArgumentException |
|
| 1214 | + * @throws ReflectionException |
|
| 1215 | + * @throws InvalidDataTypeException |
|
| 1216 | + * @throws InvalidInterfaceException |
|
| 1217 | + */ |
|
| 1218 | + public function update_email_validation_settings_form(EE_Registration_Config $EE_Registration_Config) |
|
| 1219 | + { |
|
| 1220 | + $prev_email_validation_level = $EE_Registration_Config->email_validation_level; |
|
| 1221 | + try { |
|
| 1222 | + $email_validation_settings_form = $this->_email_validation_settings_form(); |
|
| 1223 | + // if not displaying a form, then check for form submission |
|
| 1224 | + if ($email_validation_settings_form->was_submitted()) { |
|
| 1225 | + // capture form data |
|
| 1226 | + $email_validation_settings_form->receive_form_submission(); |
|
| 1227 | + // validate form data |
|
| 1228 | + if ($email_validation_settings_form->is_valid()) { |
|
| 1229 | + // grab validated data from form |
|
| 1230 | + $valid_data = $email_validation_settings_form->valid_data(); |
|
| 1231 | + if (isset($valid_data['email_validation_level'])) { |
|
| 1232 | + $email_validation_level = $valid_data['email_validation_level']; |
|
| 1233 | + // now if they want to use international email addresses |
|
| 1234 | + if ($email_validation_level === 'i18n' || $email_validation_level === 'i18n_dns') { |
|
| 1235 | + // in case we need to reset their email validation level, |
|
| 1236 | + // make sure that the previous value wasn't already set to one of the i18n options. |
|
| 1237 | + if ($prev_email_validation_level === 'i18n' || $prev_email_validation_level === 'i18n_dns') { |
|
| 1238 | + // if so, then reset it back to "basic" since that is the only other option that, |
|
| 1239 | + // despite offering poor validation, supports i18n email addresses |
|
| 1240 | + $prev_email_validation_level = 'basic'; |
|
| 1241 | + } |
|
| 1242 | + // confirm our i18n email validation will work on the server |
|
| 1243 | + if (! $this->_verify_pcre_support($EE_Registration_Config, $email_validation_level)) { |
|
| 1244 | + // or reset email validation level to previous value |
|
| 1245 | + $email_validation_level = $prev_email_validation_level; |
|
| 1246 | + } |
|
| 1247 | + } |
|
| 1248 | + $EE_Registration_Config->email_validation_level = $email_validation_level; |
|
| 1249 | + } else { |
|
| 1250 | + EE_Error::add_error( |
|
| 1251 | + esc_html__( |
|
| 1252 | + 'Invalid or missing Email Validation settings. Please refresh the form and try again.', |
|
| 1253 | + 'event_espresso' |
|
| 1254 | + ), |
|
| 1255 | + __FILE__, |
|
| 1256 | + __FUNCTION__, |
|
| 1257 | + __LINE__ |
|
| 1258 | + ); |
|
| 1259 | + } |
|
| 1260 | + } else { |
|
| 1261 | + if ($email_validation_settings_form->submission_error_message() !== '') { |
|
| 1262 | + EE_Error::add_error( |
|
| 1263 | + $email_validation_settings_form->submission_error_message(), |
|
| 1264 | + __FILE__, |
|
| 1265 | + __FUNCTION__, |
|
| 1266 | + __LINE__ |
|
| 1267 | + ); |
|
| 1268 | + } |
|
| 1269 | + } |
|
| 1270 | + } |
|
| 1271 | + } catch (EE_Error $e) { |
|
| 1272 | + $e->get_error(); |
|
| 1273 | + } |
|
| 1274 | + return $EE_Registration_Config; |
|
| 1275 | + } |
|
| 1276 | + |
|
| 1277 | + |
|
| 1278 | + /** |
|
| 1279 | + * confirms that the server's PHP version has the PCRE module enabled, |
|
| 1280 | + * and that the PCRE version works with our i18n email validation |
|
| 1281 | + * |
|
| 1282 | + * @param EE_Registration_Config $EE_Registration_Config |
|
| 1283 | + * @param string $email_validation_level |
|
| 1284 | + * @return bool |
|
| 1285 | + */ |
|
| 1286 | + private function _verify_pcre_support(EE_Registration_Config $EE_Registration_Config, $email_validation_level) |
|
| 1287 | + { |
|
| 1288 | + // first check that PCRE is enabled |
|
| 1289 | + if (! defined('PREG_BAD_UTF8_ERROR')) { |
|
| 1290 | + EE_Error::add_error( |
|
| 1291 | + sprintf( |
|
| 1292 | + esc_html__( |
|
| 1293 | + 'We\'re sorry, but it appears that your server\'s version of PHP was not compiled with PCRE unicode support.%1$sPlease contact your hosting company and ask them whether the PCRE compiled with your version of PHP on your server can be been built with the "--enable-unicode-properties" and "--enable-utf8" configuration switches to enable more complex regex expressions.%1$sIf they are unable, or unwilling to do so, then your server will not support international email addresses using UTF-8 unicode characters. This means you will either have to lower your email validation level to "Basic" or "WordPress Default", or switch to a hosting company that has/can enable PCRE unicode support on the server.', |
|
| 1294 | + 'event_espresso' |
|
| 1295 | + ), |
|
| 1296 | + '<br />' |
|
| 1297 | + ), |
|
| 1298 | + __FILE__, |
|
| 1299 | + __FUNCTION__, |
|
| 1300 | + __LINE__ |
|
| 1301 | + ); |
|
| 1302 | + return false; |
|
| 1303 | + } else { |
|
| 1304 | + // PCRE support is enabled, but let's still |
|
| 1305 | + // perform a test to see if the server will support it. |
|
| 1306 | + // but first, save the updated validation level to the config, |
|
| 1307 | + // so that the validation strategy picks it up. |
|
| 1308 | + // this will get bumped back down if it doesn't work |
|
| 1309 | + $EE_Registration_Config->email_validation_level = $email_validation_level; |
|
| 1310 | + try { |
|
| 1311 | + $email_validator = new EE_Email_Validation_Strategy(); |
|
| 1312 | + $i18n_email_address = apply_filters( |
|
| 1313 | + 'FHEE__Extend_Registration_Form_Admin_Page__update_email_validation_settings_form__i18n_email_address', |
|
| 1314 | + 'jägerjü[email protected]' |
|
| 1315 | + ); |
|
| 1316 | + $email_validator->validate($i18n_email_address); |
|
| 1317 | + } catch (Exception $e) { |
|
| 1318 | + EE_Error::add_error( |
|
| 1319 | + sprintf( |
|
| 1320 | + esc_html__( |
|
| 1321 | + 'We\'re sorry, but it appears that your server\'s configuration will not support the "International" or "International + DNS Check" email validation levels.%1$sTo correct this issue, please consult with your hosting company regarding your server\'s PCRE settings.%1$sIt is recommended that your PHP version be configured to use PCRE 8.10 or newer.%1$sMore information regarding PCRE versions and installation can be found here: %2$s', |
|
| 1322 | + 'event_espresso' |
|
| 1323 | + ), |
|
| 1324 | + '<br />', |
|
| 1325 | + '<a href="http://php.net/manual/en/pcre.installation.php" target="_blank">http://php.net/manual/en/pcre.installation.php</a>' |
|
| 1326 | + ), |
|
| 1327 | + __FILE__, |
|
| 1328 | + __FUNCTION__, |
|
| 1329 | + __LINE__ |
|
| 1330 | + ); |
|
| 1331 | + return false; |
|
| 1332 | + } |
|
| 1333 | + } |
|
| 1334 | + return true; |
|
| 1335 | + } |
|
| 1336 | 1336 | } |
@@ -12,2671 +12,2671 @@ |
||
| 12 | 12 | class Events_Admin_Page extends EE_Admin_Page_CPT |
| 13 | 13 | { |
| 14 | 14 | |
| 15 | - /** |
|
| 16 | - * This will hold the event object for event_details screen. |
|
| 17 | - * |
|
| 18 | - * @access protected |
|
| 19 | - * @var EE_Event $_event |
|
| 20 | - */ |
|
| 21 | - protected $_event; |
|
| 22 | - |
|
| 23 | - |
|
| 24 | - /** |
|
| 25 | - * This will hold the category object for category_details screen. |
|
| 26 | - * |
|
| 27 | - * @var stdClass $_category |
|
| 28 | - */ |
|
| 29 | - protected $_category; |
|
| 30 | - |
|
| 31 | - |
|
| 32 | - /** |
|
| 33 | - * This will hold the event model instance |
|
| 34 | - * |
|
| 35 | - * @var EEM_Event $_event_model |
|
| 36 | - */ |
|
| 37 | - protected $_event_model; |
|
| 38 | - |
|
| 39 | - |
|
| 40 | - /** |
|
| 41 | - * @var EE_Event |
|
| 42 | - */ |
|
| 43 | - protected $_cpt_model_obj = false; |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - /** |
|
| 47 | - * Initialize page props for this admin page group. |
|
| 48 | - */ |
|
| 49 | - protected function _init_page_props() |
|
| 50 | - { |
|
| 51 | - $this->page_slug = EVENTS_PG_SLUG; |
|
| 52 | - $this->page_label = EVENTS_LABEL; |
|
| 53 | - $this->_admin_base_url = EVENTS_ADMIN_URL; |
|
| 54 | - $this->_admin_base_path = EVENTS_ADMIN; |
|
| 55 | - $this->_cpt_model_names = array( |
|
| 56 | - 'create_new' => 'EEM_Event', |
|
| 57 | - 'edit' => 'EEM_Event', |
|
| 58 | - ); |
|
| 59 | - $this->_cpt_edit_routes = array( |
|
| 60 | - 'espresso_events' => 'edit', |
|
| 61 | - ); |
|
| 62 | - add_action( |
|
| 63 | - 'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object', |
|
| 64 | - array($this, 'verify_event_edit'), |
|
| 65 | - 10, |
|
| 66 | - 2 |
|
| 67 | - ); |
|
| 68 | - } |
|
| 69 | - |
|
| 70 | - |
|
| 71 | - /** |
|
| 72 | - * Sets the ajax hooks used for this admin page group. |
|
| 73 | - */ |
|
| 74 | - protected function _ajax_hooks() |
|
| 75 | - { |
|
| 76 | - add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting')); |
|
| 77 | - } |
|
| 78 | - |
|
| 79 | - |
|
| 80 | - /** |
|
| 81 | - * Sets the page properties for this admin page group. |
|
| 82 | - */ |
|
| 83 | - protected function _define_page_props() |
|
| 84 | - { |
|
| 85 | - $this->_admin_page_title = EVENTS_LABEL; |
|
| 86 | - $this->_labels = array( |
|
| 87 | - 'buttons' => array( |
|
| 88 | - 'add' => esc_html__('Add New Event', 'event_espresso'), |
|
| 89 | - 'edit' => esc_html__('Edit Event', 'event_espresso'), |
|
| 90 | - 'delete' => esc_html__('Delete Event', 'event_espresso'), |
|
| 91 | - 'add_category' => esc_html__('Add New Category', 'event_espresso'), |
|
| 92 | - 'edit_category' => esc_html__('Edit Category', 'event_espresso'), |
|
| 93 | - 'delete_category' => esc_html__('Delete Category', 'event_espresso'), |
|
| 94 | - ), |
|
| 95 | - 'editor_title' => array( |
|
| 96 | - 'espresso_events' => esc_html__('Enter event title here', 'event_espresso'), |
|
| 97 | - ), |
|
| 98 | - 'publishbox' => array( |
|
| 99 | - 'create_new' => esc_html__('Save New Event', 'event_espresso'), |
|
| 100 | - 'edit' => esc_html__('Update Event', 'event_espresso'), |
|
| 101 | - 'add_category' => esc_html__('Save New Category', 'event_espresso'), |
|
| 102 | - 'edit_category' => esc_html__('Update Category', 'event_espresso'), |
|
| 103 | - 'template_settings' => esc_html__('Update Settings', 'event_espresso'), |
|
| 104 | - ), |
|
| 105 | - ); |
|
| 106 | - } |
|
| 107 | - |
|
| 108 | - |
|
| 109 | - /** |
|
| 110 | - * Sets the page routes property for this admin page group. |
|
| 111 | - */ |
|
| 112 | - protected function _set_page_routes() |
|
| 113 | - { |
|
| 114 | - // load formatter helper |
|
| 115 | - // load field generator helper |
|
| 116 | - // is there a evt_id in the request? |
|
| 117 | - $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID']) |
|
| 118 | - ? $this->_req_data['EVT_ID'] |
|
| 119 | - : 0; |
|
| 120 | - $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id; |
|
| 121 | - $this->_page_routes = array( |
|
| 122 | - 'default' => array( |
|
| 123 | - 'func' => '_events_overview_list_table', |
|
| 124 | - 'capability' => 'ee_read_events', |
|
| 125 | - ), |
|
| 126 | - 'create_new' => array( |
|
| 127 | - 'func' => '_create_new_cpt_item', |
|
| 128 | - 'capability' => 'ee_edit_events', |
|
| 129 | - ), |
|
| 130 | - 'edit' => array( |
|
| 131 | - 'func' => '_edit_cpt_item', |
|
| 132 | - 'capability' => 'ee_edit_event', |
|
| 133 | - 'obj_id' => $evt_id, |
|
| 134 | - ), |
|
| 135 | - 'copy_event' => array( |
|
| 136 | - 'func' => '_copy_events', |
|
| 137 | - 'capability' => 'ee_edit_event', |
|
| 138 | - 'obj_id' => $evt_id, |
|
| 139 | - 'noheader' => true, |
|
| 140 | - ), |
|
| 141 | - 'trash_event' => array( |
|
| 142 | - 'func' => '_trash_or_restore_event', |
|
| 143 | - 'args' => array('event_status' => 'trash'), |
|
| 144 | - 'capability' => 'ee_delete_event', |
|
| 145 | - 'obj_id' => $evt_id, |
|
| 146 | - 'noheader' => true, |
|
| 147 | - ), |
|
| 148 | - 'trash_events' => array( |
|
| 149 | - 'func' => '_trash_or_restore_events', |
|
| 150 | - 'args' => array('event_status' => 'trash'), |
|
| 151 | - 'capability' => 'ee_delete_events', |
|
| 152 | - 'noheader' => true, |
|
| 153 | - ), |
|
| 154 | - 'restore_event' => array( |
|
| 155 | - 'func' => '_trash_or_restore_event', |
|
| 156 | - 'args' => array('event_status' => 'draft'), |
|
| 157 | - 'capability' => 'ee_delete_event', |
|
| 158 | - 'obj_id' => $evt_id, |
|
| 159 | - 'noheader' => true, |
|
| 160 | - ), |
|
| 161 | - 'restore_events' => array( |
|
| 162 | - 'func' => '_trash_or_restore_events', |
|
| 163 | - 'args' => array('event_status' => 'draft'), |
|
| 164 | - 'capability' => 'ee_delete_events', |
|
| 165 | - 'noheader' => true, |
|
| 166 | - ), |
|
| 167 | - 'delete_event' => array( |
|
| 168 | - 'func' => '_delete_event', |
|
| 169 | - 'capability' => 'ee_delete_event', |
|
| 170 | - 'obj_id' => $evt_id, |
|
| 171 | - 'noheader' => true, |
|
| 172 | - ), |
|
| 173 | - 'delete_events' => array( |
|
| 174 | - 'func' => '_delete_events', |
|
| 175 | - 'capability' => 'ee_delete_events', |
|
| 176 | - 'noheader' => true, |
|
| 177 | - ), |
|
| 178 | - 'view_report' => array( |
|
| 179 | - 'func' => '_view_report', |
|
| 180 | - 'capablity' => 'ee_edit_events', |
|
| 181 | - ), |
|
| 182 | - 'default_event_settings' => array( |
|
| 183 | - 'func' => '_default_event_settings', |
|
| 184 | - 'capability' => 'manage_options', |
|
| 185 | - ), |
|
| 186 | - 'update_default_event_settings' => array( |
|
| 187 | - 'func' => '_update_default_event_settings', |
|
| 188 | - 'capability' => 'manage_options', |
|
| 189 | - 'noheader' => true, |
|
| 190 | - ), |
|
| 191 | - 'template_settings' => array( |
|
| 192 | - 'func' => '_template_settings', |
|
| 193 | - 'capability' => 'manage_options', |
|
| 194 | - ), |
|
| 195 | - // event category tab related |
|
| 196 | - 'add_category' => array( |
|
| 197 | - 'func' => '_category_details', |
|
| 198 | - 'capability' => 'ee_edit_event_category', |
|
| 199 | - 'args' => array('add'), |
|
| 200 | - ), |
|
| 201 | - 'edit_category' => array( |
|
| 202 | - 'func' => '_category_details', |
|
| 203 | - 'capability' => 'ee_edit_event_category', |
|
| 204 | - 'args' => array('edit'), |
|
| 205 | - ), |
|
| 206 | - 'delete_categories' => array( |
|
| 207 | - 'func' => '_delete_categories', |
|
| 208 | - 'capability' => 'ee_delete_event_category', |
|
| 209 | - 'noheader' => true, |
|
| 210 | - ), |
|
| 211 | - 'delete_category' => array( |
|
| 212 | - 'func' => '_delete_categories', |
|
| 213 | - 'capability' => 'ee_delete_event_category', |
|
| 214 | - 'noheader' => true, |
|
| 215 | - ), |
|
| 216 | - 'insert_category' => array( |
|
| 217 | - 'func' => '_insert_or_update_category', |
|
| 218 | - 'args' => array('new_category' => true), |
|
| 219 | - 'capability' => 'ee_edit_event_category', |
|
| 220 | - 'noheader' => true, |
|
| 221 | - ), |
|
| 222 | - 'update_category' => array( |
|
| 223 | - 'func' => '_insert_or_update_category', |
|
| 224 | - 'args' => array('new_category' => false), |
|
| 225 | - 'capability' => 'ee_edit_event_category', |
|
| 226 | - 'noheader' => true, |
|
| 227 | - ), |
|
| 228 | - 'category_list' => array( |
|
| 229 | - 'func' => '_category_list_table', |
|
| 230 | - 'capability' => 'ee_manage_event_categories', |
|
| 231 | - ), |
|
| 232 | - ); |
|
| 233 | - } |
|
| 234 | - |
|
| 235 | - |
|
| 236 | - /** |
|
| 237 | - * Set the _page_config property for this admin page group. |
|
| 238 | - */ |
|
| 239 | - protected function _set_page_config() |
|
| 240 | - { |
|
| 241 | - $this->_page_config = array( |
|
| 242 | - 'default' => array( |
|
| 243 | - 'nav' => array( |
|
| 244 | - 'label' => esc_html__('Overview', 'event_espresso'), |
|
| 245 | - 'order' => 10, |
|
| 246 | - ), |
|
| 247 | - 'list_table' => 'Events_Admin_List_Table', |
|
| 248 | - 'help_tabs' => array( |
|
| 249 | - 'events_overview_help_tab' => array( |
|
| 250 | - 'title' => esc_html__('Events Overview', 'event_espresso'), |
|
| 251 | - 'filename' => 'events_overview', |
|
| 252 | - ), |
|
| 253 | - 'events_overview_table_column_headings_help_tab' => array( |
|
| 254 | - 'title' => esc_html__('Events Overview Table Column Headings', 'event_espresso'), |
|
| 255 | - 'filename' => 'events_overview_table_column_headings', |
|
| 256 | - ), |
|
| 257 | - 'events_overview_filters_help_tab' => array( |
|
| 258 | - 'title' => esc_html__('Events Overview Filters', 'event_espresso'), |
|
| 259 | - 'filename' => 'events_overview_filters', |
|
| 260 | - ), |
|
| 261 | - 'events_overview_view_help_tab' => array( |
|
| 262 | - 'title' => esc_html__('Events Overview Views', 'event_espresso'), |
|
| 263 | - 'filename' => 'events_overview_views', |
|
| 264 | - ), |
|
| 265 | - 'events_overview_other_help_tab' => array( |
|
| 266 | - 'title' => esc_html__('Events Overview Other', 'event_espresso'), |
|
| 267 | - 'filename' => 'events_overview_other', |
|
| 268 | - ), |
|
| 269 | - ), |
|
| 270 | - 'help_tour' => array( |
|
| 271 | - 'Event_Overview_Help_Tour', |
|
| 272 | - // 'New_Features_Test_Help_Tour' for testing multiple help tour |
|
| 273 | - ), |
|
| 274 | - 'qtips' => array( |
|
| 275 | - 'EE_Event_List_Table_Tips', |
|
| 276 | - ), |
|
| 277 | - 'require_nonce' => false, |
|
| 278 | - ), |
|
| 279 | - 'create_new' => array( |
|
| 280 | - 'nav' => array( |
|
| 281 | - 'label' => esc_html__('Add Event', 'event_espresso'), |
|
| 282 | - 'order' => 5, |
|
| 283 | - 'persistent' => false, |
|
| 284 | - ), |
|
| 285 | - 'metaboxes' => array('_register_event_editor_meta_boxes'), |
|
| 286 | - 'help_tabs' => array( |
|
| 287 | - 'event_editor_help_tab' => array( |
|
| 288 | - 'title' => esc_html__('Event Editor', 'event_espresso'), |
|
| 289 | - 'filename' => 'event_editor', |
|
| 290 | - ), |
|
| 291 | - 'event_editor_title_richtexteditor_help_tab' => array( |
|
| 292 | - 'title' => esc_html__('Event Title & Rich Text Editor', 'event_espresso'), |
|
| 293 | - 'filename' => 'event_editor_title_richtexteditor', |
|
| 294 | - ), |
|
| 295 | - 'event_editor_venue_details_help_tab' => array( |
|
| 296 | - 'title' => esc_html__('Event Venue Details', 'event_espresso'), |
|
| 297 | - 'filename' => 'event_editor_venue_details', |
|
| 298 | - ), |
|
| 299 | - 'event_editor_event_datetimes_help_tab' => array( |
|
| 300 | - 'title' => esc_html__('Event Datetimes', 'event_espresso'), |
|
| 301 | - 'filename' => 'event_editor_event_datetimes', |
|
| 302 | - ), |
|
| 303 | - 'event_editor_event_tickets_help_tab' => array( |
|
| 304 | - 'title' => esc_html__('Event Tickets', 'event_espresso'), |
|
| 305 | - 'filename' => 'event_editor_event_tickets', |
|
| 306 | - ), |
|
| 307 | - 'event_editor_event_registration_options_help_tab' => array( |
|
| 308 | - 'title' => esc_html__('Event Registration Options', 'event_espresso'), |
|
| 309 | - 'filename' => 'event_editor_event_registration_options', |
|
| 310 | - ), |
|
| 311 | - 'event_editor_tags_categories_help_tab' => array( |
|
| 312 | - 'title' => esc_html__('Event Tags & Categories', 'event_espresso'), |
|
| 313 | - 'filename' => 'event_editor_tags_categories', |
|
| 314 | - ), |
|
| 315 | - 'event_editor_questions_registrants_help_tab' => array( |
|
| 316 | - 'title' => esc_html__('Questions for Registrants', 'event_espresso'), |
|
| 317 | - 'filename' => 'event_editor_questions_registrants', |
|
| 318 | - ), |
|
| 319 | - 'event_editor_save_new_event_help_tab' => array( |
|
| 320 | - 'title' => esc_html__('Save New Event', 'event_espresso'), |
|
| 321 | - 'filename' => 'event_editor_save_new_event', |
|
| 322 | - ), |
|
| 323 | - 'event_editor_other_help_tab' => array( |
|
| 324 | - 'title' => esc_html__('Event Other', 'event_espresso'), |
|
| 325 | - 'filename' => 'event_editor_other', |
|
| 326 | - ), |
|
| 327 | - ), |
|
| 328 | - 'help_tour' => array( |
|
| 329 | - 'Event_Editor_Help_Tour', |
|
| 330 | - ), |
|
| 331 | - 'qtips' => array('EE_Event_Editor_Decaf_Tips'), |
|
| 332 | - 'require_nonce' => false, |
|
| 333 | - ), |
|
| 334 | - 'edit' => array( |
|
| 335 | - 'nav' => array( |
|
| 336 | - 'label' => esc_html__('Edit Event', 'event_espresso'), |
|
| 337 | - 'order' => 5, |
|
| 338 | - 'persistent' => false, |
|
| 339 | - 'url' => isset($this->_req_data['post']) |
|
| 340 | - ? EE_Admin_Page::add_query_args_and_nonce( |
|
| 341 | - array('post' => $this->_req_data['post'], 'action' => 'edit'), |
|
| 342 | - $this->_current_page_view_url |
|
| 343 | - ) |
|
| 344 | - : $this->_admin_base_url, |
|
| 345 | - ), |
|
| 346 | - 'metaboxes' => array('_register_event_editor_meta_boxes'), |
|
| 347 | - 'help_tabs' => array( |
|
| 348 | - 'event_editor_help_tab' => array( |
|
| 349 | - 'title' => esc_html__('Event Editor', 'event_espresso'), |
|
| 350 | - 'filename' => 'event_editor', |
|
| 351 | - ), |
|
| 352 | - 'event_editor_title_richtexteditor_help_tab' => array( |
|
| 353 | - 'title' => esc_html__('Event Title & Rich Text Editor', 'event_espresso'), |
|
| 354 | - 'filename' => 'event_editor_title_richtexteditor', |
|
| 355 | - ), |
|
| 356 | - 'event_editor_venue_details_help_tab' => array( |
|
| 357 | - 'title' => esc_html__('Event Venue Details', 'event_espresso'), |
|
| 358 | - 'filename' => 'event_editor_venue_details', |
|
| 359 | - ), |
|
| 360 | - 'event_editor_event_datetimes_help_tab' => array( |
|
| 361 | - 'title' => esc_html__('Event Datetimes', 'event_espresso'), |
|
| 362 | - 'filename' => 'event_editor_event_datetimes', |
|
| 363 | - ), |
|
| 364 | - 'event_editor_event_tickets_help_tab' => array( |
|
| 365 | - 'title' => esc_html__('Event Tickets', 'event_espresso'), |
|
| 366 | - 'filename' => 'event_editor_event_tickets', |
|
| 367 | - ), |
|
| 368 | - 'event_editor_event_registration_options_help_tab' => array( |
|
| 369 | - 'title' => esc_html__('Event Registration Options', 'event_espresso'), |
|
| 370 | - 'filename' => 'event_editor_event_registration_options', |
|
| 371 | - ), |
|
| 372 | - 'event_editor_tags_categories_help_tab' => array( |
|
| 373 | - 'title' => esc_html__('Event Tags & Categories', 'event_espresso'), |
|
| 374 | - 'filename' => 'event_editor_tags_categories', |
|
| 375 | - ), |
|
| 376 | - 'event_editor_questions_registrants_help_tab' => array( |
|
| 377 | - 'title' => esc_html__('Questions for Registrants', 'event_espresso'), |
|
| 378 | - 'filename' => 'event_editor_questions_registrants', |
|
| 379 | - ), |
|
| 380 | - 'event_editor_save_new_event_help_tab' => array( |
|
| 381 | - 'title' => esc_html__('Save New Event', 'event_espresso'), |
|
| 382 | - 'filename' => 'event_editor_save_new_event', |
|
| 383 | - ), |
|
| 384 | - 'event_editor_other_help_tab' => array( |
|
| 385 | - 'title' => esc_html__('Event Other', 'event_espresso'), |
|
| 386 | - 'filename' => 'event_editor_other', |
|
| 387 | - ), |
|
| 388 | - ), |
|
| 389 | - 'qtips' => array('EE_Event_Editor_Decaf_Tips'), |
|
| 390 | - 'require_nonce' => false, |
|
| 391 | - ), |
|
| 392 | - 'default_event_settings' => array( |
|
| 393 | - 'nav' => array( |
|
| 394 | - 'label' => esc_html__('Default Settings', 'event_espresso'), |
|
| 395 | - 'order' => 40, |
|
| 396 | - ), |
|
| 397 | - 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 398 | - 'labels' => array( |
|
| 399 | - 'publishbox' => esc_html__('Update Settings', 'event_espresso'), |
|
| 400 | - ), |
|
| 401 | - 'help_tabs' => array( |
|
| 402 | - 'default_settings_help_tab' => array( |
|
| 403 | - 'title' => esc_html__('Default Event Settings', 'event_espresso'), |
|
| 404 | - 'filename' => 'events_default_settings', |
|
| 405 | - ), |
|
| 406 | - 'default_settings_status_help_tab' => array( |
|
| 407 | - 'title' => esc_html__('Default Registration Status', 'event_espresso'), |
|
| 408 | - 'filename' => 'events_default_settings_status', |
|
| 409 | - ), |
|
| 410 | - 'default_maximum_tickets_help_tab' => array( |
|
| 411 | - 'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'), |
|
| 412 | - 'filename' => 'events_default_settings_max_tickets', |
|
| 413 | - ), |
|
| 414 | - ), |
|
| 415 | - 'help_tour' => array('Event_Default_Settings_Help_Tour'), |
|
| 416 | - 'require_nonce' => false, |
|
| 417 | - ), |
|
| 418 | - // template settings |
|
| 419 | - 'template_settings' => array( |
|
| 420 | - 'nav' => array( |
|
| 421 | - 'label' => esc_html__('Templates', 'event_espresso'), |
|
| 422 | - 'order' => 30, |
|
| 423 | - ), |
|
| 424 | - 'metaboxes' => $this->_default_espresso_metaboxes, |
|
| 425 | - 'help_tabs' => array( |
|
| 426 | - 'general_settings_templates_help_tab' => array( |
|
| 427 | - 'title' => esc_html__('Templates', 'event_espresso'), |
|
| 428 | - 'filename' => 'general_settings_templates', |
|
| 429 | - ), |
|
| 430 | - ), |
|
| 431 | - 'help_tour' => array('Templates_Help_Tour'), |
|
| 432 | - 'require_nonce' => false, |
|
| 433 | - ), |
|
| 434 | - // event category stuff |
|
| 435 | - 'add_category' => array( |
|
| 436 | - 'nav' => array( |
|
| 437 | - 'label' => esc_html__('Add Category', 'event_espresso'), |
|
| 438 | - 'order' => 15, |
|
| 439 | - 'persistent' => false, |
|
| 440 | - ), |
|
| 441 | - 'help_tabs' => array( |
|
| 442 | - 'add_category_help_tab' => array( |
|
| 443 | - 'title' => esc_html__('Add New Event Category', 'event_espresso'), |
|
| 444 | - 'filename' => 'events_add_category', |
|
| 445 | - ), |
|
| 446 | - ), |
|
| 447 | - 'help_tour' => array('Event_Add_Category_Help_Tour'), |
|
| 448 | - 'metaboxes' => array('_publish_post_box'), |
|
| 449 | - 'require_nonce' => false, |
|
| 450 | - ), |
|
| 451 | - 'edit_category' => array( |
|
| 452 | - 'nav' => array( |
|
| 453 | - 'label' => esc_html__('Edit Category', 'event_espresso'), |
|
| 454 | - 'order' => 15, |
|
| 455 | - 'persistent' => false, |
|
| 456 | - 'url' => isset($this->_req_data['EVT_CAT_ID']) |
|
| 457 | - ? add_query_arg( |
|
| 458 | - array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']), |
|
| 459 | - $this->_current_page_view_url |
|
| 460 | - ) |
|
| 461 | - : $this->_admin_base_url, |
|
| 462 | - ), |
|
| 463 | - 'help_tabs' => array( |
|
| 464 | - 'edit_category_help_tab' => array( |
|
| 465 | - 'title' => esc_html__('Edit Event Category', 'event_espresso'), |
|
| 466 | - 'filename' => 'events_edit_category', |
|
| 467 | - ), |
|
| 468 | - ), |
|
| 469 | - /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/ |
|
| 470 | - 'metaboxes' => array('_publish_post_box'), |
|
| 471 | - 'require_nonce' => false, |
|
| 472 | - ), |
|
| 473 | - 'category_list' => array( |
|
| 474 | - 'nav' => array( |
|
| 475 | - 'label' => esc_html__('Categories', 'event_espresso'), |
|
| 476 | - 'order' => 20, |
|
| 477 | - ), |
|
| 478 | - 'list_table' => 'Event_Categories_Admin_List_Table', |
|
| 479 | - 'help_tabs' => array( |
|
| 480 | - 'events_categories_help_tab' => array( |
|
| 481 | - 'title' => esc_html__('Event Categories', 'event_espresso'), |
|
| 482 | - 'filename' => 'events_categories', |
|
| 483 | - ), |
|
| 484 | - 'events_categories_table_column_headings_help_tab' => array( |
|
| 485 | - 'title' => esc_html__('Event Categories Table Column Headings', 'event_espresso'), |
|
| 486 | - 'filename' => 'events_categories_table_column_headings', |
|
| 487 | - ), |
|
| 488 | - 'events_categories_view_help_tab' => array( |
|
| 489 | - 'title' => esc_html__('Event Categories Views', 'event_espresso'), |
|
| 490 | - 'filename' => 'events_categories_views', |
|
| 491 | - ), |
|
| 492 | - 'events_categories_other_help_tab' => array( |
|
| 493 | - 'title' => esc_html__('Event Categories Other', 'event_espresso'), |
|
| 494 | - 'filename' => 'events_categories_other', |
|
| 495 | - ), |
|
| 496 | - ), |
|
| 497 | - 'help_tour' => array( |
|
| 498 | - 'Event_Categories_Help_Tour', |
|
| 499 | - ), |
|
| 500 | - 'metaboxes' => $this->_default_espresso_metaboxes, |
|
| 501 | - 'require_nonce' => false, |
|
| 502 | - ), |
|
| 503 | - ); |
|
| 504 | - } |
|
| 505 | - |
|
| 506 | - |
|
| 507 | - /** |
|
| 508 | - * Used to register any global screen options if necessary for every route in this admin page group. |
|
| 509 | - */ |
|
| 510 | - protected function _add_screen_options() |
|
| 511 | - { |
|
| 512 | - } |
|
| 513 | - |
|
| 514 | - |
|
| 515 | - /** |
|
| 516 | - * Implementing the screen options for the 'default' route. |
|
| 517 | - */ |
|
| 518 | - protected function _add_screen_options_default() |
|
| 519 | - { |
|
| 520 | - $this->_per_page_screen_option(); |
|
| 521 | - } |
|
| 522 | - |
|
| 523 | - |
|
| 524 | - /** |
|
| 525 | - * Implementing screen options for the category list route. |
|
| 526 | - */ |
|
| 527 | - protected function _add_screen_options_category_list() |
|
| 528 | - { |
|
| 529 | - $page_title = $this->_admin_page_title; |
|
| 530 | - $this->_admin_page_title = esc_html__('Categories', 'event_espresso'); |
|
| 531 | - $this->_per_page_screen_option(); |
|
| 532 | - $this->_admin_page_title = $page_title; |
|
| 533 | - } |
|
| 534 | - |
|
| 535 | - |
|
| 536 | - /** |
|
| 537 | - * Used to register any global feature pointers for the admin page group. |
|
| 538 | - */ |
|
| 539 | - protected function _add_feature_pointers() |
|
| 540 | - { |
|
| 541 | - } |
|
| 542 | - |
|
| 543 | - |
|
| 544 | - /** |
|
| 545 | - * Registers and enqueues any global scripts and styles for the entire admin page group. |
|
| 546 | - */ |
|
| 547 | - public function load_scripts_styles() |
|
| 548 | - { |
|
| 549 | - wp_register_style( |
|
| 550 | - 'events-admin-css', |
|
| 551 | - EVENTS_ASSETS_URL . 'events-admin-page.css', |
|
| 552 | - array(), |
|
| 553 | - EVENT_ESPRESSO_VERSION |
|
| 554 | - ); |
|
| 555 | - wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION); |
|
| 556 | - wp_enqueue_style('events-admin-css'); |
|
| 557 | - wp_enqueue_style('ee-cat-admin'); |
|
| 558 | - // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details |
|
| 559 | - // registers for all views |
|
| 560 | - // scripts |
|
| 561 | - wp_register_script( |
|
| 562 | - 'event_editor_js', |
|
| 563 | - EVENTS_ASSETS_URL . 'event_editor.js', |
|
| 564 | - array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'), |
|
| 565 | - EVENT_ESPRESSO_VERSION, |
|
| 566 | - true |
|
| 567 | - ); |
|
| 568 | - } |
|
| 569 | - |
|
| 570 | - |
|
| 571 | - /** |
|
| 572 | - * Enqueuing scripts and styles specific to this view |
|
| 573 | - */ |
|
| 574 | - public function load_scripts_styles_create_new() |
|
| 575 | - { |
|
| 576 | - $this->load_scripts_styles_edit(); |
|
| 577 | - } |
|
| 578 | - |
|
| 579 | - |
|
| 580 | - /** |
|
| 581 | - * Enqueuing scripts and styles specific to this view |
|
| 582 | - */ |
|
| 583 | - public function load_scripts_styles_edit() |
|
| 584 | - { |
|
| 585 | - // styles |
|
| 586 | - wp_enqueue_style('espresso-ui-theme'); |
|
| 587 | - wp_register_style( |
|
| 588 | - 'event-editor-css', |
|
| 589 | - EVENTS_ASSETS_URL . 'event-editor.css', |
|
| 590 | - array('ee-admin-css'), |
|
| 591 | - EVENT_ESPRESSO_VERSION |
|
| 592 | - ); |
|
| 593 | - wp_enqueue_style('event-editor-css'); |
|
| 594 | - // scripts |
|
| 595 | - wp_register_script( |
|
| 596 | - 'event-datetime-metabox', |
|
| 597 | - EVENTS_ASSETS_URL . 'event-datetime-metabox.js', |
|
| 598 | - array('event_editor_js', 'ee-datepicker'), |
|
| 599 | - EVENT_ESPRESSO_VERSION |
|
| 600 | - ); |
|
| 601 | - wp_enqueue_script('event-datetime-metabox'); |
|
| 602 | - } |
|
| 603 | - |
|
| 604 | - |
|
| 605 | - /** |
|
| 606 | - * Populating the _views property for the category list table view. |
|
| 607 | - */ |
|
| 608 | - protected function _set_list_table_views_category_list() |
|
| 609 | - { |
|
| 610 | - $this->_views = array( |
|
| 611 | - 'all' => array( |
|
| 612 | - 'slug' => 'all', |
|
| 613 | - 'label' => esc_html__('All', 'event_espresso'), |
|
| 614 | - 'count' => 0, |
|
| 615 | - 'bulk_action' => array( |
|
| 616 | - 'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 617 | - ), |
|
| 618 | - ), |
|
| 619 | - ); |
|
| 620 | - } |
|
| 621 | - |
|
| 622 | - |
|
| 623 | - /** |
|
| 624 | - * For adding anything that fires on the admin_init hook for any route within this admin page group. |
|
| 625 | - */ |
|
| 626 | - public function admin_init() |
|
| 627 | - { |
|
| 628 | - EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__( |
|
| 629 | - 'Do you really want to delete this image? Please remember to update your event to complete the removal.', |
|
| 630 | - 'event_espresso' |
|
| 631 | - ); |
|
| 632 | - } |
|
| 633 | - |
|
| 634 | - |
|
| 635 | - /** |
|
| 636 | - * For adding anything that should be triggered on the admin_notices hook for any route within this admin page |
|
| 637 | - * group. |
|
| 638 | - */ |
|
| 639 | - public function admin_notices() |
|
| 640 | - { |
|
| 641 | - } |
|
| 642 | - |
|
| 643 | - |
|
| 644 | - /** |
|
| 645 | - * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within |
|
| 646 | - * this admin page group. |
|
| 647 | - */ |
|
| 648 | - public function admin_footer_scripts() |
|
| 649 | - { |
|
| 650 | - } |
|
| 651 | - |
|
| 652 | - |
|
| 653 | - /** |
|
| 654 | - * Call this function to verify if an event is public and has tickets for sale. If it does, then we need to show a |
|
| 655 | - * warning (via EE_Error::add_error()); |
|
| 656 | - * |
|
| 657 | - * @param EE_Event $event Event object |
|
| 658 | - * @param string $req_type |
|
| 659 | - * @return void |
|
| 660 | - * @throws EE_Error |
|
| 661 | - * @access public |
|
| 662 | - */ |
|
| 663 | - public function verify_event_edit($event = null, $req_type = '') |
|
| 664 | - { |
|
| 665 | - // don't need to do this when processing |
|
| 666 | - if (! empty($req_type)) { |
|
| 667 | - return; |
|
| 668 | - } |
|
| 669 | - // no event? |
|
| 670 | - if (empty($event)) { |
|
| 671 | - // set event |
|
| 672 | - $event = $this->_cpt_model_obj; |
|
| 673 | - } |
|
| 674 | - // STILL no event? |
|
| 675 | - if (! $event instanceof EE_Event) { |
|
| 676 | - return; |
|
| 677 | - } |
|
| 678 | - $orig_status = $event->status(); |
|
| 679 | - // first check if event is active. |
|
| 680 | - if ($orig_status === EEM_Event::cancelled |
|
| 681 | - || $orig_status === EEM_Event::postponed |
|
| 682 | - || $event->is_expired() |
|
| 683 | - || $event->is_inactive() |
|
| 684 | - ) { |
|
| 685 | - return; |
|
| 686 | - } |
|
| 687 | - // made it here so it IS active... next check that any of the tickets are sold. |
|
| 688 | - if ($event->is_sold_out(true)) { |
|
| 689 | - if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) { |
|
| 690 | - EE_Error::add_attention( |
|
| 691 | - sprintf( |
|
| 692 | - esc_html__( |
|
| 693 | - 'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event. However, this change is not permanent until you update the event. You can change the status back to something else before updating if you wish.', |
|
| 694 | - 'event_espresso' |
|
| 695 | - ), |
|
| 696 | - EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence') |
|
| 697 | - ) |
|
| 698 | - ); |
|
| 699 | - } |
|
| 700 | - return; |
|
| 701 | - } elseif ($orig_status === EEM_Event::sold_out) { |
|
| 702 | - EE_Error::add_attention( |
|
| 703 | - sprintf( |
|
| 704 | - esc_html__( |
|
| 705 | - 'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets. However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.', |
|
| 706 | - 'event_espresso' |
|
| 707 | - ), |
|
| 708 | - EEH_Template::pretty_status($event->status(), false, 'sentence') |
|
| 709 | - ) |
|
| 710 | - ); |
|
| 711 | - } |
|
| 712 | - // now we need to determine if the event has any tickets on sale. If not then we dont' show the error |
|
| 713 | - if (! $event->tickets_on_sale()) { |
|
| 714 | - return; |
|
| 715 | - } |
|
| 716 | - // made it here so show warning |
|
| 717 | - $this->_edit_event_warning(); |
|
| 718 | - } |
|
| 719 | - |
|
| 720 | - |
|
| 721 | - /** |
|
| 722 | - * This is the text used for when an event is being edited that is public and has tickets for sale. |
|
| 723 | - * When needed, hook this into a EE_Error::add_error() notice. |
|
| 724 | - * |
|
| 725 | - * @access protected |
|
| 726 | - * @return void |
|
| 727 | - */ |
|
| 728 | - protected function _edit_event_warning() |
|
| 729 | - { |
|
| 730 | - // we don't want to add warnings during these requests |
|
| 731 | - if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') { |
|
| 732 | - return; |
|
| 733 | - } |
|
| 734 | - EE_Error::add_attention( |
|
| 735 | - sprintf( |
|
| 736 | - esc_html__( |
|
| 737 | - 'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s', |
|
| 738 | - 'event_espresso' |
|
| 739 | - ), |
|
| 740 | - '<a class="espresso-help-tab-lnk">', |
|
| 741 | - '</a>' |
|
| 742 | - ) |
|
| 743 | - ); |
|
| 744 | - } |
|
| 745 | - |
|
| 746 | - |
|
| 747 | - /** |
|
| 748 | - * When a user is creating a new event, notify them if they haven't set their timezone. |
|
| 749 | - * Otherwise, do the normal logic |
|
| 750 | - * |
|
| 751 | - * @return string |
|
| 752 | - * @throws \EE_Error |
|
| 753 | - */ |
|
| 754 | - protected function _create_new_cpt_item() |
|
| 755 | - { |
|
| 756 | - $has_timezone_string = get_option('timezone_string'); |
|
| 757 | - // only nag them about setting their timezone if it's their first event, and they haven't already done it |
|
| 758 | - if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) { |
|
| 759 | - EE_Error::add_attention( |
|
| 760 | - sprintf( |
|
| 761 | - __( |
|
| 762 | - 'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s', |
|
| 763 | - 'event_espresso' |
|
| 764 | - ), |
|
| 765 | - '<br>', |
|
| 766 | - '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">' |
|
| 767 | - . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale()) |
|
| 768 | - . '</select>', |
|
| 769 | - '<button class="button button-secondary timezone-submit">', |
|
| 770 | - '</button><span class="spinner"></span>' |
|
| 771 | - ), |
|
| 772 | - __FILE__, |
|
| 773 | - __FUNCTION__, |
|
| 774 | - __LINE__ |
|
| 775 | - ); |
|
| 776 | - } |
|
| 777 | - return parent::_create_new_cpt_item(); |
|
| 778 | - } |
|
| 779 | - |
|
| 780 | - |
|
| 781 | - /** |
|
| 782 | - * Sets the _views property for the default route in this admin page group. |
|
| 783 | - */ |
|
| 784 | - protected function _set_list_table_views_default() |
|
| 785 | - { |
|
| 786 | - $this->_views = array( |
|
| 787 | - 'all' => array( |
|
| 788 | - 'slug' => 'all', |
|
| 789 | - 'label' => esc_html__('View All Events', 'event_espresso'), |
|
| 790 | - 'count' => 0, |
|
| 791 | - 'bulk_action' => array( |
|
| 792 | - 'trash_events' => esc_html__('Move to Trash', 'event_espresso'), |
|
| 793 | - ), |
|
| 794 | - ), |
|
| 795 | - 'draft' => array( |
|
| 796 | - 'slug' => 'draft', |
|
| 797 | - 'label' => esc_html__('Draft', 'event_espresso'), |
|
| 798 | - 'count' => 0, |
|
| 799 | - 'bulk_action' => array( |
|
| 800 | - 'trash_events' => esc_html__('Move to Trash', 'event_espresso'), |
|
| 801 | - ), |
|
| 802 | - ), |
|
| 803 | - ); |
|
| 804 | - if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) { |
|
| 805 | - $this->_views['trash'] = array( |
|
| 806 | - 'slug' => 'trash', |
|
| 807 | - 'label' => esc_html__('Trash', 'event_espresso'), |
|
| 808 | - 'count' => 0, |
|
| 809 | - 'bulk_action' => array( |
|
| 810 | - 'restore_events' => esc_html__('Restore From Trash', 'event_espresso'), |
|
| 811 | - 'delete_events' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 812 | - ), |
|
| 813 | - ); |
|
| 814 | - } |
|
| 815 | - } |
|
| 816 | - |
|
| 817 | - |
|
| 818 | - /** |
|
| 819 | - * Provides the legend item array for the default list table view. |
|
| 820 | - * |
|
| 821 | - * @return array |
|
| 822 | - */ |
|
| 823 | - protected function _event_legend_items() |
|
| 824 | - { |
|
| 825 | - $items = array( |
|
| 826 | - 'view_details' => array( |
|
| 827 | - 'class' => 'dashicons dashicons-search', |
|
| 828 | - 'desc' => esc_html__('View Event', 'event_espresso'), |
|
| 829 | - ), |
|
| 830 | - 'edit_event' => array( |
|
| 831 | - 'class' => 'ee-icon ee-icon-calendar-edit', |
|
| 832 | - 'desc' => esc_html__('Edit Event Details', 'event_espresso'), |
|
| 833 | - ), |
|
| 834 | - 'view_attendees' => array( |
|
| 835 | - 'class' => 'dashicons dashicons-groups', |
|
| 836 | - 'desc' => esc_html__('View Registrations for Event', 'event_espresso'), |
|
| 837 | - ), |
|
| 838 | - ); |
|
| 839 | - $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items); |
|
| 840 | - $statuses = array( |
|
| 841 | - 'sold_out_status' => array( |
|
| 842 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out, |
|
| 843 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'), |
|
| 844 | - ), |
|
| 845 | - 'active_status' => array( |
|
| 846 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active, |
|
| 847 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'), |
|
| 848 | - ), |
|
| 849 | - 'upcoming_status' => array( |
|
| 850 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming, |
|
| 851 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'), |
|
| 852 | - ), |
|
| 853 | - 'postponed_status' => array( |
|
| 854 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed, |
|
| 855 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'), |
|
| 856 | - ), |
|
| 857 | - 'cancelled_status' => array( |
|
| 858 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled, |
|
| 859 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'), |
|
| 860 | - ), |
|
| 861 | - 'expired_status' => array( |
|
| 862 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired, |
|
| 863 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'), |
|
| 864 | - ), |
|
| 865 | - 'inactive_status' => array( |
|
| 866 | - 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive, |
|
| 867 | - 'desc' => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'), |
|
| 868 | - ), |
|
| 869 | - ); |
|
| 870 | - $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses); |
|
| 871 | - return array_merge($items, $statuses); |
|
| 872 | - } |
|
| 873 | - |
|
| 874 | - |
|
| 875 | - /** |
|
| 876 | - * @return EEM_Event |
|
| 877 | - */ |
|
| 878 | - private function _event_model() |
|
| 879 | - { |
|
| 880 | - if (! $this->_event_model instanceof EEM_Event) { |
|
| 881 | - $this->_event_model = EE_Registry::instance()->load_model('Event'); |
|
| 882 | - } |
|
| 883 | - return $this->_event_model; |
|
| 884 | - } |
|
| 885 | - |
|
| 886 | - |
|
| 887 | - /** |
|
| 888 | - * Adds extra buttons to the WP CPT permalink field row. |
|
| 889 | - * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter. |
|
| 890 | - * |
|
| 891 | - * @param string $return the current html |
|
| 892 | - * @param int $id the post id for the page |
|
| 893 | - * @param string $new_title What the title is |
|
| 894 | - * @param string $new_slug what the slug is |
|
| 895 | - * @return string The new html string for the permalink area |
|
| 896 | - */ |
|
| 897 | - public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug) |
|
| 898 | - { |
|
| 899 | - // make sure this is only when editing |
|
| 900 | - if (! empty($id)) { |
|
| 901 | - $post = get_post($id); |
|
| 902 | - $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#" tabindex="-1">' |
|
| 903 | - . esc_html__('Shortcode', 'event_espresso') |
|
| 904 | - . '</a> '; |
|
| 905 | - $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id=' |
|
| 906 | - . $post->ID |
|
| 907 | - . ']">'; |
|
| 908 | - } |
|
| 909 | - return $return; |
|
| 910 | - } |
|
| 911 | - |
|
| 912 | - |
|
| 913 | - /** |
|
| 914 | - * _events_overview_list_table |
|
| 915 | - * This contains the logic for showing the events_overview list |
|
| 916 | - * |
|
| 917 | - * @access protected |
|
| 918 | - * @return void |
|
| 919 | - * @throws \EE_Error |
|
| 920 | - */ |
|
| 921 | - protected function _events_overview_list_table() |
|
| 922 | - { |
|
| 923 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 924 | - $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table']) |
|
| 925 | - ? (array) $this->_template_args['after_list_table'] |
|
| 926 | - : array(); |
|
| 927 | - $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br() |
|
| 928 | - . EEH_Template::get_button_or_link( |
|
| 929 | - get_post_type_archive_link('espresso_events'), |
|
| 930 | - esc_html__("View Event Archive Page", "event_espresso"), |
|
| 931 | - 'button' |
|
| 932 | - ); |
|
| 933 | - $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items()); |
|
| 934 | - $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 935 | - 'create_new', |
|
| 936 | - 'add', |
|
| 937 | - array(), |
|
| 938 | - 'add-new-h2' |
|
| 939 | - ); |
|
| 940 | - $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 941 | - } |
|
| 942 | - |
|
| 943 | - |
|
| 944 | - /** |
|
| 945 | - * this allows for extra misc actions in the default WP publish box |
|
| 946 | - * |
|
| 947 | - * @return void |
|
| 948 | - */ |
|
| 949 | - public function extra_misc_actions_publish_box() |
|
| 950 | - { |
|
| 951 | - $this->_generate_publish_box_extra_content(); |
|
| 952 | - } |
|
| 953 | - |
|
| 954 | - |
|
| 955 | - /** |
|
| 956 | - * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been |
|
| 957 | - * saved. |
|
| 958 | - * Typically you would use this to save any additional data. |
|
| 959 | - * Keep in mind also that "save_post" runs on EVERY post update to the database. |
|
| 960 | - * ALSO very important. When a post transitions from scheduled to published, |
|
| 961 | - * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from |
|
| 962 | - * other meta saves. So MAKE sure that you handle this accordingly. |
|
| 963 | - * |
|
| 964 | - * @access protected |
|
| 965 | - * @abstract |
|
| 966 | - * @param string $post_id The ID of the cpt that was saved (so you can link relationally) |
|
| 967 | - * @param object $post The post object of the cpt that was saved. |
|
| 968 | - * @return void |
|
| 969 | - * @throws \EE_Error |
|
| 970 | - */ |
|
| 971 | - protected function _insert_update_cpt_item($post_id, $post) |
|
| 972 | - { |
|
| 973 | - if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') { |
|
| 974 | - // get out we're not processing an event save. |
|
| 975 | - return; |
|
| 976 | - } |
|
| 977 | - $event_values = array( |
|
| 978 | - 'EVT_display_desc' => ! empty($this->_req_data['display_desc']) ? 1 : 0, |
|
| 979 | - 'EVT_display_ticket_selector' => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0, |
|
| 980 | - 'EVT_additional_limit' => min( |
|
| 981 | - apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255), |
|
| 982 | - ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null |
|
| 983 | - ), |
|
| 984 | - 'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status']) |
|
| 985 | - ? $this->_req_data['EVT_default_registration_status'] |
|
| 986 | - : EE_Registry::instance()->CFG->registration->default_STS_ID, |
|
| 987 | - 'EVT_member_only' => ! empty($this->_req_data['member_only']) ? 1 : 0, |
|
| 988 | - 'EVT_allow_overflow' => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0, |
|
| 989 | - 'EVT_timezone_string' => ! empty($this->_req_data['timezone_string']) |
|
| 990 | - ? $this->_req_data['timezone_string'] : null, |
|
| 991 | - 'EVT_external_URL' => ! empty($this->_req_data['externalURL']) |
|
| 992 | - ? $this->_req_data['externalURL'] : null, |
|
| 993 | - 'EVT_phone' => ! empty($this->_req_data['event_phone']) |
|
| 994 | - ? $this->_req_data['event_phone'] : null, |
|
| 995 | - ); |
|
| 996 | - // update event |
|
| 997 | - $success = $this->_event_model()->update_by_ID($event_values, $post_id); |
|
| 998 | - // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id! |
|
| 999 | - $get_one_where = array( |
|
| 1000 | - $this->_event_model()->primary_key_name() => $post_id, |
|
| 1001 | - 'OR' => array( |
|
| 1002 | - 'status' => $post->post_status, |
|
| 1003 | - // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db, |
|
| 1004 | - // but the returned object here has a status of "publish", so use the original post status as well |
|
| 1005 | - 'status*1' => $this->_req_data['original_post_status'], |
|
| 1006 | - ), |
|
| 1007 | - ); |
|
| 1008 | - $event = $this->_event_model()->get_one(array($get_one_where)); |
|
| 1009 | - // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons. |
|
| 1010 | - $event_update_callbacks = apply_filters( |
|
| 1011 | - 'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks', |
|
| 1012 | - array( |
|
| 1013 | - array($this, '_default_venue_update'), |
|
| 1014 | - array($this, '_default_tickets_update'), |
|
| 1015 | - ) |
|
| 1016 | - ); |
|
| 1017 | - $att_success = true; |
|
| 1018 | - foreach ($event_update_callbacks as $e_callback) { |
|
| 1019 | - $_success = is_callable($e_callback) |
|
| 1020 | - ? call_user_func($e_callback, $event, $this->_req_data) |
|
| 1021 | - : false; |
|
| 1022 | - // if ANY of these updates fail then we want the appropriate global error message |
|
| 1023 | - $att_success = ! $att_success ? $att_success : $_success; |
|
| 1024 | - } |
|
| 1025 | - // any errors? |
|
| 1026 | - if ($success && false === $att_success) { |
|
| 1027 | - EE_Error::add_error( |
|
| 1028 | - esc_html__( |
|
| 1029 | - 'Event Details saved successfully but something went wrong with saving attachments.', |
|
| 1030 | - 'event_espresso' |
|
| 1031 | - ), |
|
| 1032 | - __FILE__, |
|
| 1033 | - __FUNCTION__, |
|
| 1034 | - __LINE__ |
|
| 1035 | - ); |
|
| 1036 | - } elseif ($success === false) { |
|
| 1037 | - EE_Error::add_error( |
|
| 1038 | - esc_html__('Event Details did not save successfully.', 'event_espresso'), |
|
| 1039 | - __FILE__, |
|
| 1040 | - __FUNCTION__, |
|
| 1041 | - __LINE__ |
|
| 1042 | - ); |
|
| 1043 | - } |
|
| 1044 | - } |
|
| 1045 | - |
|
| 1046 | - |
|
| 1047 | - /** |
|
| 1048 | - * @see parent::restore_item() |
|
| 1049 | - * @param int $post_id |
|
| 1050 | - * @param int $revision_id |
|
| 1051 | - */ |
|
| 1052 | - protected function _restore_cpt_item($post_id, $revision_id) |
|
| 1053 | - { |
|
| 1054 | - // copy existing event meta to new post |
|
| 1055 | - $post_evt = $this->_event_model()->get_one_by_ID($post_id); |
|
| 1056 | - if ($post_evt instanceof EE_Event) { |
|
| 1057 | - // meta revision restore |
|
| 1058 | - $post_evt->restore_revision($revision_id); |
|
| 1059 | - // related objs restore |
|
| 1060 | - $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price')); |
|
| 1061 | - } |
|
| 1062 | - } |
|
| 1063 | - |
|
| 1064 | - |
|
| 1065 | - /** |
|
| 1066 | - * Attach the venue to the Event |
|
| 1067 | - * |
|
| 1068 | - * @param \EE_Event $evtobj Event Object to add the venue to |
|
| 1069 | - * @param array $data The request data from the form |
|
| 1070 | - * @return bool Success or fail. |
|
| 1071 | - */ |
|
| 1072 | - protected function _default_venue_update(\EE_Event $evtobj, $data) |
|
| 1073 | - { |
|
| 1074 | - require_once(EE_MODELS . 'EEM_Venue.model.php'); |
|
| 1075 | - $venue_model = EE_Registry::instance()->load_model('Venue'); |
|
| 1076 | - $rows_affected = null; |
|
| 1077 | - $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null; |
|
| 1078 | - // very important. If we don't have a venue name... |
|
| 1079 | - // then we'll get out because not necessary to create empty venue |
|
| 1080 | - if (empty($data['venue_title'])) { |
|
| 1081 | - return false; |
|
| 1082 | - } |
|
| 1083 | - $venue_array = array( |
|
| 1084 | - 'VNU_wp_user' => $evtobj->get('EVT_wp_user'), |
|
| 1085 | - 'VNU_name' => ! empty($data['venue_title']) ? $data['venue_title'] : null, |
|
| 1086 | - 'VNU_desc' => ! empty($data['venue_description']) ? $data['venue_description'] : null, |
|
| 1087 | - 'VNU_identifier' => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null, |
|
| 1088 | - 'VNU_short_desc' => ! empty($data['venue_short_description']) ? $data['venue_short_description'] |
|
| 1089 | - : null, |
|
| 1090 | - 'VNU_address' => ! empty($data['address']) ? $data['address'] : null, |
|
| 1091 | - 'VNU_address2' => ! empty($data['address2']) ? $data['address2'] : null, |
|
| 1092 | - 'VNU_city' => ! empty($data['city']) ? $data['city'] : null, |
|
| 1093 | - 'STA_ID' => ! empty($data['state']) ? $data['state'] : null, |
|
| 1094 | - 'CNT_ISO' => ! empty($data['countries']) ? $data['countries'] : null, |
|
| 1095 | - 'VNU_zip' => ! empty($data['zip']) ? $data['zip'] : null, |
|
| 1096 | - 'VNU_phone' => ! empty($data['venue_phone']) ? $data['venue_phone'] : null, |
|
| 1097 | - 'VNU_capacity' => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null, |
|
| 1098 | - 'VNU_url' => ! empty($data['venue_url']) ? $data['venue_url'] : null, |
|
| 1099 | - 'VNU_virtual_phone' => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null, |
|
| 1100 | - 'VNU_virtual_url' => ! empty($data['virtual_url']) ? $data['virtual_url'] : null, |
|
| 1101 | - 'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0, |
|
| 1102 | - 'status' => 'publish', |
|
| 1103 | - ); |
|
| 1104 | - // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out. |
|
| 1105 | - if (! empty($venue_id)) { |
|
| 1106 | - $update_where = array($venue_model->primary_key_name() => $venue_id); |
|
| 1107 | - $rows_affected = $venue_model->update($venue_array, array($update_where)); |
|
| 1108 | - // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present. |
|
| 1109 | - $evtobj->_add_relation_to($venue_id, 'Venue'); |
|
| 1110 | - return $rows_affected > 0 ? true : false; |
|
| 1111 | - } else { |
|
| 1112 | - // we insert the venue |
|
| 1113 | - $venue_id = $venue_model->insert($venue_array); |
|
| 1114 | - $evtobj->_add_relation_to($venue_id, 'Venue'); |
|
| 1115 | - return ! empty($venue_id) ? true : false; |
|
| 1116 | - } |
|
| 1117 | - // when we have the ancestor come in it's already been handled by the revision save. |
|
| 1118 | - } |
|
| 1119 | - |
|
| 1120 | - |
|
| 1121 | - /** |
|
| 1122 | - * Handles saving everything related to Tickets (datetimes, tickets, prices) |
|
| 1123 | - * |
|
| 1124 | - * @param EE_Event $evtobj The Event object we're attaching data to |
|
| 1125 | - * @param array $data The request data from the form |
|
| 1126 | - * @return array |
|
| 1127 | - */ |
|
| 1128 | - protected function _default_tickets_update(EE_Event $evtobj, $data) |
|
| 1129 | - { |
|
| 1130 | - $success = true; |
|
| 1131 | - $saved_dtt = null; |
|
| 1132 | - $saved_tickets = array(); |
|
| 1133 | - $incoming_date_formats = array('Y-m-d', 'h:i a'); |
|
| 1134 | - foreach ($data['edit_event_datetimes'] as $row => $dtt) { |
|
| 1135 | - // trim all values to ensure any excess whitespace is removed. |
|
| 1136 | - $dtt = array_map('trim', $dtt); |
|
| 1137 | - $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end'] |
|
| 1138 | - : $dtt['DTT_EVT_start']; |
|
| 1139 | - $datetime_values = array( |
|
| 1140 | - 'DTT_ID' => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null, |
|
| 1141 | - 'DTT_EVT_start' => $dtt['DTT_EVT_start'], |
|
| 1142 | - 'DTT_EVT_end' => $dtt['DTT_EVT_end'], |
|
| 1143 | - 'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'], |
|
| 1144 | - 'DTT_order' => $row, |
|
| 1145 | - ); |
|
| 1146 | - // if we have an id then let's get existing object first and then set the new values. Otherwise we instantiate a new object for save. |
|
| 1147 | - if (! empty($dtt['DTT_ID'])) { |
|
| 1148 | - $DTM = EE_Registry::instance() |
|
| 1149 | - ->load_model('Datetime', array($evtobj->get_timezone())) |
|
| 1150 | - ->get_one_by_ID($dtt['DTT_ID']); |
|
| 1151 | - $DTM->set_date_format($incoming_date_formats[0]); |
|
| 1152 | - $DTM->set_time_format($incoming_date_formats[1]); |
|
| 1153 | - foreach ($datetime_values as $field => $value) { |
|
| 1154 | - $DTM->set($field, $value); |
|
| 1155 | - } |
|
| 1156 | - // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it. We need to do this so we dont' TRASH the parent DTT. |
|
| 1157 | - $saved_dtts[ $DTM->ID() ] = $DTM; |
|
| 1158 | - } else { |
|
| 1159 | - $DTM = EE_Registry::instance()->load_class( |
|
| 1160 | - 'Datetime', |
|
| 1161 | - array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats), |
|
| 1162 | - false, |
|
| 1163 | - false |
|
| 1164 | - ); |
|
| 1165 | - foreach ($datetime_values as $field => $value) { |
|
| 1166 | - $DTM->set($field, $value); |
|
| 1167 | - } |
|
| 1168 | - } |
|
| 1169 | - $DTM->save(); |
|
| 1170 | - $DTT = $evtobj->_add_relation_to($DTM, 'Datetime'); |
|
| 1171 | - // load DTT helper |
|
| 1172 | - // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date. |
|
| 1173 | - if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) { |
|
| 1174 | - $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start')); |
|
| 1175 | - $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days'); |
|
| 1176 | - $DTT->save(); |
|
| 1177 | - } |
|
| 1178 | - // now we got to make sure we add the new DTT_ID to the $saved_dtts array because it is possible there was a new one created for the autosave. |
|
| 1179 | - $saved_dtt = $DTT; |
|
| 1180 | - $success = ! $success ? $success : $DTT; |
|
| 1181 | - // if ANY of these updates fail then we want the appropriate global error message. |
|
| 1182 | - // //todo this is actually sucky we need a better error message but this is what it is for now. |
|
| 1183 | - } |
|
| 1184 | - // no dtts get deleted so we don't do any of that logic here. |
|
| 1185 | - // update tickets next |
|
| 1186 | - $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array(); |
|
| 1187 | - foreach ($data['edit_tickets'] as $row => $tkt) { |
|
| 1188 | - $incoming_date_formats = array('Y-m-d', 'h:i a'); |
|
| 1189 | - $update_prices = false; |
|
| 1190 | - $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount']) |
|
| 1191 | - ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0; |
|
| 1192 | - // trim inputs to ensure any excess whitespace is removed. |
|
| 1193 | - $tkt = array_map('trim', $tkt); |
|
| 1194 | - if (empty($tkt['TKT_start_date'])) { |
|
| 1195 | - // let's use now in the set timezone. |
|
| 1196 | - $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone())); |
|
| 1197 | - $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]); |
|
| 1198 | - } |
|
| 1199 | - if (empty($tkt['TKT_end_date'])) { |
|
| 1200 | - // use the start date of the first datetime |
|
| 1201 | - $dtt = $evtobj->first_datetime(); |
|
| 1202 | - $tkt['TKT_end_date'] = $dtt->start_date_and_time( |
|
| 1203 | - $incoming_date_formats[0], |
|
| 1204 | - $incoming_date_formats[1] |
|
| 1205 | - ); |
|
| 1206 | - } |
|
| 1207 | - $TKT_values = array( |
|
| 1208 | - 'TKT_ID' => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null, |
|
| 1209 | - 'TTM_ID' => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0, |
|
| 1210 | - 'TKT_name' => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '', |
|
| 1211 | - 'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '', |
|
| 1212 | - 'TKT_start_date' => $tkt['TKT_start_date'], |
|
| 1213 | - 'TKT_end_date' => $tkt['TKT_end_date'], |
|
| 1214 | - 'TKT_qty' => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'], |
|
| 1215 | - 'TKT_uses' => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'], |
|
| 1216 | - 'TKT_min' => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'], |
|
| 1217 | - 'TKT_max' => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'], |
|
| 1218 | - 'TKT_row' => $row, |
|
| 1219 | - 'TKT_order' => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row, |
|
| 1220 | - 'TKT_price' => $ticket_price, |
|
| 1221 | - ); |
|
| 1222 | - // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well. |
|
| 1223 | - if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) { |
|
| 1224 | - $TKT_values['TKT_ID'] = 0; |
|
| 1225 | - $TKT_values['TKT_is_default'] = 0; |
|
| 1226 | - $TKT_values['TKT_price'] = $ticket_price; |
|
| 1227 | - $update_prices = true; |
|
| 1228 | - } |
|
| 1229 | - // if we have a TKT_ID then we need to get that existing TKT_obj and update it |
|
| 1230 | - // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified. |
|
| 1231 | - // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived. |
|
| 1232 | - if (! empty($tkt['TKT_ID'])) { |
|
| 1233 | - $TKT = EE_Registry::instance() |
|
| 1234 | - ->load_model('Ticket', array($evtobj->get_timezone())) |
|
| 1235 | - ->get_one_by_ID($tkt['TKT_ID']); |
|
| 1236 | - if ($TKT instanceof EE_Ticket) { |
|
| 1237 | - $ticket_sold = $TKT->count_related( |
|
| 1238 | - 'Registration', |
|
| 1239 | - array( |
|
| 1240 | - array( |
|
| 1241 | - 'STS_ID' => array( |
|
| 1242 | - 'NOT IN', |
|
| 1243 | - array(EEM_Registration::status_id_incomplete), |
|
| 1244 | - ), |
|
| 1245 | - ), |
|
| 1246 | - ) |
|
| 1247 | - ) > 0 ? true : false; |
|
| 1248 | - // let's just check the total price for the existing ticket and determine if it matches the new total price. if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket. |
|
| 1249 | - $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price') |
|
| 1250 | - && ! $TKT->get('TKT_deleted'); |
|
| 1251 | - $TKT->set_date_format($incoming_date_formats[0]); |
|
| 1252 | - $TKT->set_time_format($incoming_date_formats[1]); |
|
| 1253 | - // set new values |
|
| 1254 | - foreach ($TKT_values as $field => $value) { |
|
| 1255 | - if ($field == 'TKT_qty') { |
|
| 1256 | - $TKT->set_qty($value); |
|
| 1257 | - } else { |
|
| 1258 | - $TKT->set($field, $value); |
|
| 1259 | - } |
|
| 1260 | - } |
|
| 1261 | - // if $create_new_TKT is false then we can safely update the existing ticket. Otherwise we have to create a new ticket. |
|
| 1262 | - if ($create_new_TKT) { |
|
| 1263 | - // archive the old ticket first |
|
| 1264 | - $TKT->set('TKT_deleted', 1); |
|
| 1265 | - $TKT->save(); |
|
| 1266 | - // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine. |
|
| 1267 | - $saved_tickets[ $TKT->ID() ] = $TKT; |
|
| 1268 | - // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it. |
|
| 1269 | - $TKT = clone $TKT; |
|
| 1270 | - $TKT->set('TKT_ID', 0); |
|
| 1271 | - $TKT->set('TKT_deleted', 0); |
|
| 1272 | - $TKT->set('TKT_price', $ticket_price); |
|
| 1273 | - $TKT->set('TKT_sold', 0); |
|
| 1274 | - // now we need to make sure that $new prices are created as well and attached to new ticket. |
|
| 1275 | - $update_prices = true; |
|
| 1276 | - } |
|
| 1277 | - // make sure price is set if it hasn't been already |
|
| 1278 | - $TKT->set('TKT_price', $ticket_price); |
|
| 1279 | - } |
|
| 1280 | - } else { |
|
| 1281 | - // no TKT_id so a new TKT |
|
| 1282 | - $TKT_values['TKT_price'] = $ticket_price; |
|
| 1283 | - $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false); |
|
| 1284 | - if ($TKT instanceof EE_Ticket) { |
|
| 1285 | - // need to reset values to properly account for the date formats |
|
| 1286 | - $TKT->set_date_format($incoming_date_formats[0]); |
|
| 1287 | - $TKT->set_time_format($incoming_date_formats[1]); |
|
| 1288 | - $TKT->set_timezone($evtobj->get_timezone()); |
|
| 1289 | - // set new values |
|
| 1290 | - foreach ($TKT_values as $field => $value) { |
|
| 1291 | - if ($field == 'TKT_qty') { |
|
| 1292 | - $TKT->set_qty($value); |
|
| 1293 | - } else { |
|
| 1294 | - $TKT->set($field, $value); |
|
| 1295 | - } |
|
| 1296 | - } |
|
| 1297 | - $update_prices = true; |
|
| 1298 | - } |
|
| 1299 | - } |
|
| 1300 | - // cap ticket qty by datetime reg limits |
|
| 1301 | - $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit'))); |
|
| 1302 | - // update ticket. |
|
| 1303 | - $TKT->save(); |
|
| 1304 | - // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date. |
|
| 1305 | - if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) { |
|
| 1306 | - $TKT->set('TKT_end_date', $TKT->get('TKT_start_date')); |
|
| 1307 | - $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days'); |
|
| 1308 | - $TKT->save(); |
|
| 1309 | - } |
|
| 1310 | - // initially let's add the ticket to the dtt |
|
| 1311 | - $saved_dtt->_add_relation_to($TKT, 'Ticket'); |
|
| 1312 | - $saved_tickets[ $TKT->ID() ] = $TKT; |
|
| 1313 | - // add prices to ticket |
|
| 1314 | - $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices); |
|
| 1315 | - } |
|
| 1316 | - // however now we need to handle permanently deleting tickets via the ui. Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold. However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db. |
|
| 1317 | - $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets; |
|
| 1318 | - $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets)); |
|
| 1319 | - foreach ($tickets_removed as $id) { |
|
| 1320 | - $id = absint($id); |
|
| 1321 | - // get the ticket for this id |
|
| 1322 | - $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id); |
|
| 1323 | - // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold) |
|
| 1324 | - $dtts = $tkt_to_remove->get_many_related('Datetime'); |
|
| 1325 | - foreach ($dtts as $dtt) { |
|
| 1326 | - $tkt_to_remove->_remove_relation_to($dtt, 'Datetime'); |
|
| 1327 | - } |
|
| 1328 | - // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived)) |
|
| 1329 | - $tkt_to_remove->delete_related_permanently('Price'); |
|
| 1330 | - // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships) |
|
| 1331 | - $tkt_to_remove->delete_permanently(); |
|
| 1332 | - } |
|
| 1333 | - return array($saved_dtt, $saved_tickets); |
|
| 1334 | - } |
|
| 1335 | - |
|
| 1336 | - |
|
| 1337 | - /** |
|
| 1338 | - * This attaches a list of given prices to a ticket. |
|
| 1339 | - * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change |
|
| 1340 | - * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old |
|
| 1341 | - * price info and prices are automatically "archived" via the ticket. |
|
| 1342 | - * |
|
| 1343 | - * @access private |
|
| 1344 | - * @param array $prices Array of prices from the form. |
|
| 1345 | - * @param EE_Ticket $ticket EE_Ticket object that prices are being attached to. |
|
| 1346 | - * @param bool $new_prices Whether attach existing incoming prices or create new ones. |
|
| 1347 | - * @return void |
|
| 1348 | - */ |
|
| 1349 | - private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false) |
|
| 1350 | - { |
|
| 1351 | - foreach ($prices as $row => $prc) { |
|
| 1352 | - $PRC_values = array( |
|
| 1353 | - 'PRC_ID' => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null, |
|
| 1354 | - 'PRT_ID' => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null, |
|
| 1355 | - 'PRC_amount' => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0, |
|
| 1356 | - 'PRC_name' => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '', |
|
| 1357 | - 'PRC_desc' => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '', |
|
| 1358 | - 'PRC_is_default' => 0, // make sure prices are NOT set as default from this context |
|
| 1359 | - 'PRC_order' => $row, |
|
| 1360 | - ); |
|
| 1361 | - if ($new_prices || empty($PRC_values['PRC_ID'])) { |
|
| 1362 | - $PRC_values['PRC_ID'] = 0; |
|
| 1363 | - $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false); |
|
| 1364 | - } else { |
|
| 1365 | - $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']); |
|
| 1366 | - // update this price with new values |
|
| 1367 | - foreach ($PRC_values as $field => $newprc) { |
|
| 1368 | - $PRC->set($field, $newprc); |
|
| 1369 | - } |
|
| 1370 | - $PRC->save(); |
|
| 1371 | - } |
|
| 1372 | - $ticket->_add_relation_to($PRC, 'Price'); |
|
| 1373 | - } |
|
| 1374 | - } |
|
| 1375 | - |
|
| 1376 | - |
|
| 1377 | - /** |
|
| 1378 | - * Add in our autosave ajax handlers |
|
| 1379 | - * |
|
| 1380 | - */ |
|
| 1381 | - protected function _ee_autosave_create_new() |
|
| 1382 | - { |
|
| 1383 | - } |
|
| 1384 | - |
|
| 1385 | - |
|
| 1386 | - /** |
|
| 1387 | - * More autosave handlers. |
|
| 1388 | - */ |
|
| 1389 | - protected function _ee_autosave_edit() |
|
| 1390 | - { |
|
| 1391 | - return; // TEMPORARILY EXITING CAUSE THIS IS A TODO |
|
| 1392 | - } |
|
| 1393 | - |
|
| 1394 | - |
|
| 1395 | - /** |
|
| 1396 | - * _generate_publish_box_extra_content |
|
| 1397 | - */ |
|
| 1398 | - private function _generate_publish_box_extra_content() |
|
| 1399 | - { |
|
| 1400 | - // load formatter helper |
|
| 1401 | - // args for getting related registrations |
|
| 1402 | - $approved_query_args = array( |
|
| 1403 | - array( |
|
| 1404 | - 'REG_deleted' => 0, |
|
| 1405 | - 'STS_ID' => EEM_Registration::status_id_approved, |
|
| 1406 | - ), |
|
| 1407 | - ); |
|
| 1408 | - $not_approved_query_args = array( |
|
| 1409 | - array( |
|
| 1410 | - 'REG_deleted' => 0, |
|
| 1411 | - 'STS_ID' => EEM_Registration::status_id_not_approved, |
|
| 1412 | - ), |
|
| 1413 | - ); |
|
| 1414 | - $pending_payment_query_args = array( |
|
| 1415 | - array( |
|
| 1416 | - 'REG_deleted' => 0, |
|
| 1417 | - 'STS_ID' => EEM_Registration::status_id_pending_payment, |
|
| 1418 | - ), |
|
| 1419 | - ); |
|
| 1420 | - // publish box |
|
| 1421 | - $publish_box_extra_args = array( |
|
| 1422 | - 'view_approved_reg_url' => add_query_arg( |
|
| 1423 | - array( |
|
| 1424 | - 'action' => 'default', |
|
| 1425 | - 'event_id' => $this->_cpt_model_obj->ID(), |
|
| 1426 | - '_reg_status' => EEM_Registration::status_id_approved, |
|
| 1427 | - ), |
|
| 1428 | - REG_ADMIN_URL |
|
| 1429 | - ), |
|
| 1430 | - 'view_not_approved_reg_url' => add_query_arg( |
|
| 1431 | - array( |
|
| 1432 | - 'action' => 'default', |
|
| 1433 | - 'event_id' => $this->_cpt_model_obj->ID(), |
|
| 1434 | - '_reg_status' => EEM_Registration::status_id_not_approved, |
|
| 1435 | - ), |
|
| 1436 | - REG_ADMIN_URL |
|
| 1437 | - ), |
|
| 1438 | - 'view_pending_payment_reg_url' => add_query_arg( |
|
| 1439 | - array( |
|
| 1440 | - 'action' => 'default', |
|
| 1441 | - 'event_id' => $this->_cpt_model_obj->ID(), |
|
| 1442 | - '_reg_status' => EEM_Registration::status_id_pending_payment, |
|
| 1443 | - ), |
|
| 1444 | - REG_ADMIN_URL |
|
| 1445 | - ), |
|
| 1446 | - 'approved_regs' => $this->_cpt_model_obj->count_related( |
|
| 1447 | - 'Registration', |
|
| 1448 | - $approved_query_args |
|
| 1449 | - ), |
|
| 1450 | - 'not_approved_regs' => $this->_cpt_model_obj->count_related( |
|
| 1451 | - 'Registration', |
|
| 1452 | - $not_approved_query_args |
|
| 1453 | - ), |
|
| 1454 | - 'pending_payment_regs' => $this->_cpt_model_obj->count_related( |
|
| 1455 | - 'Registration', |
|
| 1456 | - $pending_payment_query_args |
|
| 1457 | - ), |
|
| 1458 | - 'misc_pub_section_class' => apply_filters( |
|
| 1459 | - 'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class', |
|
| 1460 | - 'misc-pub-section' |
|
| 1461 | - ), |
|
| 1462 | - ); |
|
| 1463 | - ob_start(); |
|
| 1464 | - do_action( |
|
| 1465 | - 'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add', |
|
| 1466 | - $this->_cpt_model_obj |
|
| 1467 | - ); |
|
| 1468 | - $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean(); |
|
| 1469 | - // load template |
|
| 1470 | - EEH_Template::display_template( |
|
| 1471 | - EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php', |
|
| 1472 | - $publish_box_extra_args |
|
| 1473 | - ); |
|
| 1474 | - } |
|
| 1475 | - |
|
| 1476 | - |
|
| 1477 | - /** |
|
| 1478 | - * @return EE_Event |
|
| 1479 | - */ |
|
| 1480 | - public function get_event_object() |
|
| 1481 | - { |
|
| 1482 | - return $this->_cpt_model_obj; |
|
| 1483 | - } |
|
| 1484 | - |
|
| 1485 | - |
|
| 1486 | - |
|
| 1487 | - |
|
| 1488 | - /** METABOXES * */ |
|
| 1489 | - /** |
|
| 1490 | - * _register_event_editor_meta_boxes |
|
| 1491 | - * add all metaboxes related to the event_editor |
|
| 1492 | - * |
|
| 1493 | - * @return void |
|
| 1494 | - */ |
|
| 1495 | - protected function _register_event_editor_meta_boxes() |
|
| 1496 | - { |
|
| 1497 | - $this->verify_cpt_object(); |
|
| 1498 | - add_meta_box( |
|
| 1499 | - 'espresso_event_editor_tickets', |
|
| 1500 | - esc_html__('Event Datetime & Ticket', 'event_espresso'), |
|
| 1501 | - array($this, 'ticket_metabox'), |
|
| 1502 | - $this->page_slug, |
|
| 1503 | - 'normal', |
|
| 1504 | - 'high' |
|
| 1505 | - ); |
|
| 1506 | - add_meta_box( |
|
| 1507 | - 'espresso_event_editor_event_options', |
|
| 1508 | - esc_html__('Event Registration Options', 'event_espresso'), |
|
| 1509 | - array($this, 'registration_options_meta_box'), |
|
| 1510 | - $this->page_slug, |
|
| 1511 | - 'side', |
|
| 1512 | - 'default' |
|
| 1513 | - ); |
|
| 1514 | - // NOTE: if you're looking for other metaboxes in here, |
|
| 1515 | - // where a metabox has a related management page in the admin |
|
| 1516 | - // you will find it setup in the related management page's "_Hooks" file. |
|
| 1517 | - // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php". |
|
| 1518 | - } |
|
| 1519 | - |
|
| 1520 | - |
|
| 1521 | - /** |
|
| 1522 | - * @throws DomainException |
|
| 1523 | - * @throws EE_Error |
|
| 1524 | - */ |
|
| 1525 | - public function ticket_metabox() |
|
| 1526 | - { |
|
| 1527 | - $existing_datetime_ids = $existing_ticket_ids = array(); |
|
| 1528 | - // defaults for template args |
|
| 1529 | - $template_args = array( |
|
| 1530 | - 'existing_datetime_ids' => '', |
|
| 1531 | - 'event_datetime_help_link' => '', |
|
| 1532 | - 'ticket_options_help_link' => '', |
|
| 1533 | - 'time' => null, |
|
| 1534 | - 'ticket_rows' => '', |
|
| 1535 | - 'existing_ticket_ids' => '', |
|
| 1536 | - 'total_ticket_rows' => 1, |
|
| 1537 | - 'ticket_js_structure' => '', |
|
| 1538 | - 'trash_icon' => 'ee-lock-icon', |
|
| 1539 | - 'disabled' => '', |
|
| 1540 | - ); |
|
| 1541 | - $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null; |
|
| 1542 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 1543 | - /** |
|
| 1544 | - * 1. Start with retrieving Datetimes |
|
| 1545 | - * 2. Fore each datetime get related tickets |
|
| 1546 | - * 3. For each ticket get related prices |
|
| 1547 | - */ |
|
| 1548 | - $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id); |
|
| 1549 | - /** @type EE_Datetime $first_datetime */ |
|
| 1550 | - $first_datetime = reset($times); |
|
| 1551 | - // do we get related tickets? |
|
| 1552 | - if ($first_datetime instanceof EE_Datetime |
|
| 1553 | - && $first_datetime->ID() !== 0 |
|
| 1554 | - ) { |
|
| 1555 | - $existing_datetime_ids[] = $first_datetime->get('DTT_ID'); |
|
| 1556 | - $template_args['time'] = $first_datetime; |
|
| 1557 | - $related_tickets = $first_datetime->tickets( |
|
| 1558 | - array( |
|
| 1559 | - array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)), |
|
| 1560 | - 'default_where_conditions' => 'none', |
|
| 1561 | - ) |
|
| 1562 | - ); |
|
| 1563 | - if (! empty($related_tickets)) { |
|
| 1564 | - $template_args['total_ticket_rows'] = count($related_tickets); |
|
| 1565 | - $row = 0; |
|
| 1566 | - foreach ($related_tickets as $ticket) { |
|
| 1567 | - $existing_ticket_ids[] = $ticket->get('TKT_ID'); |
|
| 1568 | - $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row); |
|
| 1569 | - $row++; |
|
| 1570 | - } |
|
| 1571 | - } else { |
|
| 1572 | - $template_args['total_ticket_rows'] = 1; |
|
| 1573 | - /** @type EE_Ticket $ticket */ |
|
| 1574 | - $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object(); |
|
| 1575 | - $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket); |
|
| 1576 | - } |
|
| 1577 | - } else { |
|
| 1578 | - $template_args['time'] = $times[0]; |
|
| 1579 | - /** @type EE_Ticket $ticket */ |
|
| 1580 | - $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets(); |
|
| 1581 | - $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]); |
|
| 1582 | - // NOTE: we're just sending the first default row |
|
| 1583 | - // (decaf can't manage default tickets so this should be sufficient); |
|
| 1584 | - } |
|
| 1585 | - $template_args['event_datetime_help_link'] = $this->_get_help_tab_link( |
|
| 1586 | - 'event_editor_event_datetimes_help_tab' |
|
| 1587 | - ); |
|
| 1588 | - $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info'); |
|
| 1589 | - $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids); |
|
| 1590 | - $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids); |
|
| 1591 | - $template_args['ticket_js_structure'] = $this->_get_ticket_row( |
|
| 1592 | - EE_Registry::instance()->load_model('Ticket')->create_default_object(), |
|
| 1593 | - true |
|
| 1594 | - ); |
|
| 1595 | - $template = apply_filters( |
|
| 1596 | - 'FHEE__Events_Admin_Page__ticket_metabox__template', |
|
| 1597 | - EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php' |
|
| 1598 | - ); |
|
| 1599 | - EEH_Template::display_template($template, $template_args); |
|
| 1600 | - } |
|
| 1601 | - |
|
| 1602 | - |
|
| 1603 | - /** |
|
| 1604 | - * Setup an individual ticket form for the decaf event editor page |
|
| 1605 | - * |
|
| 1606 | - * @access private |
|
| 1607 | - * @param EE_Ticket $ticket the ticket object |
|
| 1608 | - * @param boolean $skeleton whether we're generating a skeleton for js manipulation |
|
| 1609 | - * @param int $row |
|
| 1610 | - * @return string generated html for the ticket row. |
|
| 1611 | - */ |
|
| 1612 | - private function _get_ticket_row($ticket, $skeleton = false, $row = 0) |
|
| 1613 | - { |
|
| 1614 | - $template_args = array( |
|
| 1615 | - 'tkt_status_class' => ' tkt-status-' . $ticket->ticket_status(), |
|
| 1616 | - 'tkt_archive_class' => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived' |
|
| 1617 | - : '', |
|
| 1618 | - 'ticketrow' => $skeleton ? 'TICKETNUM' : $row, |
|
| 1619 | - 'TKT_ID' => $ticket->get('TKT_ID'), |
|
| 1620 | - 'TKT_name' => $ticket->get('TKT_name'), |
|
| 1621 | - 'TKT_start_date' => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'), |
|
| 1622 | - 'TKT_end_date' => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'), |
|
| 1623 | - 'TKT_is_default' => $ticket->get('TKT_is_default'), |
|
| 1624 | - 'TKT_qty' => $ticket->get_pretty('TKT_qty', 'input'), |
|
| 1625 | - 'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets', |
|
| 1626 | - 'TKT_sold' => $skeleton ? 0 : $ticket->get('TKT_sold'), |
|
| 1627 | - 'trash_icon' => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted'))) |
|
| 1628 | - && (! empty($ticket) && $ticket->get('TKT_sold') === 0) |
|
| 1629 | - ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon', |
|
| 1630 | - 'disabled' => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? '' |
|
| 1631 | - : ' disabled=disabled', |
|
| 1632 | - ); |
|
| 1633 | - $price = $ticket->ID() !== 0 |
|
| 1634 | - ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none')) |
|
| 1635 | - : EE_Registry::instance()->load_model('Price')->create_default_object(); |
|
| 1636 | - $price_args = array( |
|
| 1637 | - 'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign, |
|
| 1638 | - 'PRC_amount' => $price->get('PRC_amount'), |
|
| 1639 | - 'PRT_ID' => $price->get('PRT_ID'), |
|
| 1640 | - 'PRC_ID' => $price->get('PRC_ID'), |
|
| 1641 | - 'PRC_is_default' => $price->get('PRC_is_default'), |
|
| 1642 | - ); |
|
| 1643 | - // make sure we have default start and end dates if skeleton |
|
| 1644 | - // handle rows that should NOT be empty |
|
| 1645 | - if (empty($template_args['TKT_start_date'])) { |
|
| 1646 | - // if empty then the start date will be now. |
|
| 1647 | - $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp')); |
|
| 1648 | - } |
|
| 1649 | - if (empty($template_args['TKT_end_date'])) { |
|
| 1650 | - // get the earliest datetime (if present); |
|
| 1651 | - $earliest_dtt = $this->_cpt_model_obj->ID() > 0 |
|
| 1652 | - ? $this->_cpt_model_obj->get_first_related( |
|
| 1653 | - 'Datetime', |
|
| 1654 | - array('order_by' => array('DTT_EVT_start' => 'ASC')) |
|
| 1655 | - ) |
|
| 1656 | - : null; |
|
| 1657 | - if (! empty($earliest_dtt)) { |
|
| 1658 | - $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a'); |
|
| 1659 | - } else { |
|
| 1660 | - $template_args['TKT_end_date'] = date( |
|
| 1661 | - 'Y-m-d h:i a', |
|
| 1662 | - mktime(0, 0, 0, date("m"), date("d") + 7, date("Y")) |
|
| 1663 | - ); |
|
| 1664 | - } |
|
| 1665 | - } |
|
| 1666 | - $template_args = array_merge($template_args, $price_args); |
|
| 1667 | - $template = apply_filters( |
|
| 1668 | - 'FHEE__Events_Admin_Page__get_ticket_row__template', |
|
| 1669 | - EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php', |
|
| 1670 | - $ticket |
|
| 1671 | - ); |
|
| 1672 | - return EEH_Template::display_template($template, $template_args, true); |
|
| 1673 | - } |
|
| 1674 | - |
|
| 1675 | - |
|
| 1676 | - /** |
|
| 1677 | - * @throws DomainException |
|
| 1678 | - */ |
|
| 1679 | - public function registration_options_meta_box() |
|
| 1680 | - { |
|
| 1681 | - $yes_no_values = array( |
|
| 1682 | - array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')), |
|
| 1683 | - array('id' => false, 'text' => esc_html__('No', 'event_espresso')), |
|
| 1684 | - ); |
|
| 1685 | - $default_reg_status_values = EEM_Registration::reg_status_array( |
|
| 1686 | - array( |
|
| 1687 | - EEM_Registration::status_id_cancelled, |
|
| 1688 | - EEM_Registration::status_id_declined, |
|
| 1689 | - EEM_Registration::status_id_incomplete, |
|
| 1690 | - ), |
|
| 1691 | - true |
|
| 1692 | - ); |
|
| 1693 | - // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active()); |
|
| 1694 | - $template_args['_event'] = $this->_cpt_model_obj; |
|
| 1695 | - $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false); |
|
| 1696 | - $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit(); |
|
| 1697 | - $template_args['default_registration_status'] = EEH_Form_Fields::select_input( |
|
| 1698 | - 'default_reg_status', |
|
| 1699 | - $default_reg_status_values, |
|
| 1700 | - $this->_cpt_model_obj->default_registration_status() |
|
| 1701 | - ); |
|
| 1702 | - $template_args['display_description'] = EEH_Form_Fields::select_input( |
|
| 1703 | - 'display_desc', |
|
| 1704 | - $yes_no_values, |
|
| 1705 | - $this->_cpt_model_obj->display_description() |
|
| 1706 | - ); |
|
| 1707 | - $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input( |
|
| 1708 | - 'display_ticket_selector', |
|
| 1709 | - $yes_no_values, |
|
| 1710 | - $this->_cpt_model_obj->display_ticket_selector(), |
|
| 1711 | - '', |
|
| 1712 | - '', |
|
| 1713 | - false |
|
| 1714 | - ); |
|
| 1715 | - $template_args['additional_registration_options'] = apply_filters( |
|
| 1716 | - 'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options', |
|
| 1717 | - '', |
|
| 1718 | - $template_args, |
|
| 1719 | - $yes_no_values, |
|
| 1720 | - $default_reg_status_values |
|
| 1721 | - ); |
|
| 1722 | - EEH_Template::display_template( |
|
| 1723 | - EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php', |
|
| 1724 | - $template_args |
|
| 1725 | - ); |
|
| 1726 | - } |
|
| 1727 | - |
|
| 1728 | - |
|
| 1729 | - /** |
|
| 1730 | - * _get_events() |
|
| 1731 | - * This method simply returns all the events (for the given _view and paging) |
|
| 1732 | - * |
|
| 1733 | - * @access public |
|
| 1734 | - * @param int $per_page count of items per page (20 default); |
|
| 1735 | - * @param int $current_page what is the current page being viewed. |
|
| 1736 | - * @param bool $count if TRUE then we just return a count of ALL events matching the given _view. |
|
| 1737 | - * If FALSE then we return an array of event objects |
|
| 1738 | - * that match the given _view and paging parameters. |
|
| 1739 | - * @return array an array of event objects. |
|
| 1740 | - */ |
|
| 1741 | - public function get_events($per_page = 10, $current_page = 1, $count = false) |
|
| 1742 | - { |
|
| 1743 | - $EEME = $this->_event_model(); |
|
| 1744 | - $offset = ($current_page - 1) * $per_page; |
|
| 1745 | - $limit = $count ? null : $offset . ',' . $per_page; |
|
| 1746 | - $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID'; |
|
| 1747 | - $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC"; |
|
| 1748 | - if (isset($this->_req_data['month_range'])) { |
|
| 1749 | - $pieces = explode(' ', $this->_req_data['month_range'], 3); |
|
| 1750 | - // simulate the FIRST day of the month, that fixes issues for months like February |
|
| 1751 | - // where PHP doesn't know what to assume for date. |
|
| 1752 | - // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437 |
|
| 1753 | - $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : ''; |
|
| 1754 | - $year_r = ! empty($pieces[1]) ? $pieces[1] : ''; |
|
| 1755 | - } |
|
| 1756 | - $where = array(); |
|
| 1757 | - $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null; |
|
| 1758 | - // determine what post_status our condition will have for the query. |
|
| 1759 | - switch ($status) { |
|
| 1760 | - case 'month': |
|
| 1761 | - case 'today': |
|
| 1762 | - case null: |
|
| 1763 | - case 'all': |
|
| 1764 | - break; |
|
| 1765 | - case 'draft': |
|
| 1766 | - $where['status'] = array('IN', array('draft', 'auto-draft')); |
|
| 1767 | - break; |
|
| 1768 | - default: |
|
| 1769 | - $where['status'] = $status; |
|
| 1770 | - } |
|
| 1771 | - // categories? |
|
| 1772 | - $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0 |
|
| 1773 | - ? $this->_req_data['EVT_CAT'] : null; |
|
| 1774 | - if (! empty($category)) { |
|
| 1775 | - $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories'; |
|
| 1776 | - $where['Term_Taxonomy.term_id'] = $category; |
|
| 1777 | - } |
|
| 1778 | - // date where conditions |
|
| 1779 | - $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start'); |
|
| 1780 | - if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') { |
|
| 1781 | - $DateTime = new DateTime( |
|
| 1782 | - $year_r . '-' . $month_r . '-01 00:00:00', |
|
| 1783 | - new DateTimeZone(EEM_Datetime::instance()->get_timezone()) |
|
| 1784 | - ); |
|
| 1785 | - $start = $DateTime->format(implode(' ', $start_formats)); |
|
| 1786 | - $end = $DateTime->setDate( |
|
| 1787 | - $year_r, |
|
| 1788 | - $month_r, |
|
| 1789 | - $DateTime |
|
| 1790 | - ->format('t') |
|
| 1791 | - )->setTime(23, 59, 59) |
|
| 1792 | - ->format(implode(' ', $start_formats)); |
|
| 1793 | - $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end)); |
|
| 1794 | - } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') { |
|
| 1795 | - $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone())); |
|
| 1796 | - $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats)); |
|
| 1797 | - $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats)); |
|
| 1798 | - $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end)); |
|
| 1799 | - } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') { |
|
| 1800 | - $now = date('Y-m-01'); |
|
| 1801 | - $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone())); |
|
| 1802 | - $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats)); |
|
| 1803 | - $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t')) |
|
| 1804 | - ->setTime(23, 59, 59) |
|
| 1805 | - ->format(implode(' ', $start_formats)); |
|
| 1806 | - $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end)); |
|
| 1807 | - } |
|
| 1808 | - if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) { |
|
| 1809 | - $where['EVT_wp_user'] = get_current_user_id(); |
|
| 1810 | - } else { |
|
| 1811 | - if (! isset($where['status'])) { |
|
| 1812 | - if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) { |
|
| 1813 | - $where['OR'] = array( |
|
| 1814 | - 'status*restrict_private' => array('!=', 'private'), |
|
| 1815 | - 'AND' => array( |
|
| 1816 | - 'status*inclusive' => array('=', 'private'), |
|
| 1817 | - 'EVT_wp_user' => get_current_user_id(), |
|
| 1818 | - ), |
|
| 1819 | - ); |
|
| 1820 | - } |
|
| 1821 | - } |
|
| 1822 | - } |
|
| 1823 | - if (isset($this->_req_data['EVT_wp_user'])) { |
|
| 1824 | - if ($this->_req_data['EVT_wp_user'] != get_current_user_id() |
|
| 1825 | - && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events') |
|
| 1826 | - ) { |
|
| 1827 | - $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user']; |
|
| 1828 | - } |
|
| 1829 | - } |
|
| 1830 | - // search query handling |
|
| 1831 | - if (isset($this->_req_data['s'])) { |
|
| 1832 | - $search_string = '%' . $this->_req_data['s'] . '%'; |
|
| 1833 | - $where['OR'] = array( |
|
| 1834 | - 'EVT_name' => array('LIKE', $search_string), |
|
| 1835 | - 'EVT_desc' => array('LIKE', $search_string), |
|
| 1836 | - 'EVT_short_desc' => array('LIKE', $search_string), |
|
| 1837 | - ); |
|
| 1838 | - } |
|
| 1839 | - $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data); |
|
| 1840 | - $query_params = apply_filters( |
|
| 1841 | - 'FHEE__Events_Admin_Page__get_events__query_params', |
|
| 1842 | - array( |
|
| 1843 | - $where, |
|
| 1844 | - 'limit' => $limit, |
|
| 1845 | - 'order_by' => $orderby, |
|
| 1846 | - 'order' => $order, |
|
| 1847 | - 'group_by' => 'EVT_ID', |
|
| 1848 | - ), |
|
| 1849 | - $this->_req_data |
|
| 1850 | - ); |
|
| 1851 | - // let's first check if we have special requests coming in. |
|
| 1852 | - if (isset($this->_req_data['active_status'])) { |
|
| 1853 | - switch ($this->_req_data['active_status']) { |
|
| 1854 | - case 'upcoming': |
|
| 1855 | - return $EEME->get_upcoming_events($query_params, $count); |
|
| 1856 | - break; |
|
| 1857 | - case 'expired': |
|
| 1858 | - return $EEME->get_expired_events($query_params, $count); |
|
| 1859 | - break; |
|
| 1860 | - case 'active': |
|
| 1861 | - return $EEME->get_active_events($query_params, $count); |
|
| 1862 | - break; |
|
| 1863 | - case 'inactive': |
|
| 1864 | - return $EEME->get_inactive_events($query_params, $count); |
|
| 1865 | - break; |
|
| 1866 | - } |
|
| 1867 | - } |
|
| 1868 | - $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params); |
|
| 1869 | - return $events; |
|
| 1870 | - } |
|
| 1871 | - |
|
| 1872 | - |
|
| 1873 | - /** |
|
| 1874 | - * handling for WordPress CPT actions (trash, restore, delete) |
|
| 1875 | - * |
|
| 1876 | - * @param string $post_id |
|
| 1877 | - */ |
|
| 1878 | - public function trash_cpt_item($post_id) |
|
| 1879 | - { |
|
| 1880 | - $this->_req_data['EVT_ID'] = $post_id; |
|
| 1881 | - $this->_trash_or_restore_event('trash', false); |
|
| 1882 | - } |
|
| 1883 | - |
|
| 1884 | - |
|
| 1885 | - /** |
|
| 1886 | - * @param string $post_id |
|
| 1887 | - */ |
|
| 1888 | - public function restore_cpt_item($post_id) |
|
| 1889 | - { |
|
| 1890 | - $this->_req_data['EVT_ID'] = $post_id; |
|
| 1891 | - $this->_trash_or_restore_event('draft', false); |
|
| 1892 | - } |
|
| 1893 | - |
|
| 1894 | - |
|
| 1895 | - /** |
|
| 1896 | - * @param string $post_id |
|
| 1897 | - */ |
|
| 1898 | - public function delete_cpt_item($post_id) |
|
| 1899 | - { |
|
| 1900 | - $this->_req_data['EVT_ID'] = $post_id; |
|
| 1901 | - $this->_delete_event(false); |
|
| 1902 | - } |
|
| 1903 | - |
|
| 1904 | - |
|
| 1905 | - /** |
|
| 1906 | - * _trash_or_restore_event |
|
| 1907 | - * |
|
| 1908 | - * @access protected |
|
| 1909 | - * @param string $event_status |
|
| 1910 | - * @param bool $redirect_after |
|
| 1911 | - */ |
|
| 1912 | - protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true) |
|
| 1913 | - { |
|
| 1914 | - // determine the event id and set to array. |
|
| 1915 | - $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false; |
|
| 1916 | - // loop thru events |
|
| 1917 | - if ($EVT_ID) { |
|
| 1918 | - // clean status |
|
| 1919 | - $event_status = sanitize_key($event_status); |
|
| 1920 | - // grab status |
|
| 1921 | - if (! empty($event_status)) { |
|
| 1922 | - $success = $this->_change_event_status($EVT_ID, $event_status); |
|
| 1923 | - } else { |
|
| 1924 | - $success = false; |
|
| 1925 | - $msg = esc_html__( |
|
| 1926 | - 'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.', |
|
| 1927 | - 'event_espresso' |
|
| 1928 | - ); |
|
| 1929 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1930 | - } |
|
| 1931 | - } else { |
|
| 1932 | - $success = false; |
|
| 1933 | - $msg = esc_html__( |
|
| 1934 | - 'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.', |
|
| 1935 | - 'event_espresso' |
|
| 1936 | - ); |
|
| 1937 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1938 | - } |
|
| 1939 | - $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash'; |
|
| 1940 | - if ($redirect_after) { |
|
| 1941 | - $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default')); |
|
| 1942 | - } |
|
| 1943 | - } |
|
| 1944 | - |
|
| 1945 | - |
|
| 1946 | - /** |
|
| 1947 | - * _trash_or_restore_events |
|
| 1948 | - * |
|
| 1949 | - * @access protected |
|
| 1950 | - * @param string $event_status |
|
| 1951 | - * @return void |
|
| 1952 | - */ |
|
| 1953 | - protected function _trash_or_restore_events($event_status = 'trash') |
|
| 1954 | - { |
|
| 1955 | - // clean status |
|
| 1956 | - $event_status = sanitize_key($event_status); |
|
| 1957 | - // grab status |
|
| 1958 | - if (! empty($event_status)) { |
|
| 1959 | - $success = true; |
|
| 1960 | - // determine the event id and set to array. |
|
| 1961 | - $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array(); |
|
| 1962 | - // loop thru events |
|
| 1963 | - foreach ($EVT_IDs as $EVT_ID) { |
|
| 1964 | - if ($EVT_ID = absint($EVT_ID)) { |
|
| 1965 | - $results = $this->_change_event_status($EVT_ID, $event_status); |
|
| 1966 | - $success = $results !== false ? $success : false; |
|
| 1967 | - } else { |
|
| 1968 | - $msg = sprintf( |
|
| 1969 | - esc_html__( |
|
| 1970 | - 'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.', |
|
| 1971 | - 'event_espresso' |
|
| 1972 | - ), |
|
| 1973 | - $EVT_ID |
|
| 1974 | - ); |
|
| 1975 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1976 | - $success = false; |
|
| 1977 | - } |
|
| 1978 | - } |
|
| 1979 | - } else { |
|
| 1980 | - $success = false; |
|
| 1981 | - $msg = esc_html__( |
|
| 1982 | - 'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.', |
|
| 1983 | - 'event_espresso' |
|
| 1984 | - ); |
|
| 1985 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1986 | - } |
|
| 1987 | - // in order to force a pluralized result message we need to send back a success status greater than 1 |
|
| 1988 | - $success = $success ? 2 : false; |
|
| 1989 | - $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash'; |
|
| 1990 | - $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default')); |
|
| 1991 | - } |
|
| 1992 | - |
|
| 1993 | - |
|
| 1994 | - /** |
|
| 1995 | - * _trash_or_restore_events |
|
| 1996 | - * |
|
| 1997 | - * @access private |
|
| 1998 | - * @param int $EVT_ID |
|
| 1999 | - * @param string $event_status |
|
| 2000 | - * @return bool |
|
| 2001 | - */ |
|
| 2002 | - private function _change_event_status($EVT_ID = 0, $event_status = '') |
|
| 2003 | - { |
|
| 2004 | - // grab event id |
|
| 2005 | - if (! $EVT_ID) { |
|
| 2006 | - $msg = esc_html__( |
|
| 2007 | - 'An error occurred. No Event ID or an invalid Event ID was received.', |
|
| 2008 | - 'event_espresso' |
|
| 2009 | - ); |
|
| 2010 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2011 | - return false; |
|
| 2012 | - } |
|
| 2013 | - $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID); |
|
| 2014 | - // clean status |
|
| 2015 | - $event_status = sanitize_key($event_status); |
|
| 2016 | - // grab status |
|
| 2017 | - if (empty($event_status)) { |
|
| 2018 | - $msg = esc_html__( |
|
| 2019 | - 'An error occurred. No Event Status or an invalid Event Status was received.', |
|
| 2020 | - 'event_espresso' |
|
| 2021 | - ); |
|
| 2022 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2023 | - return false; |
|
| 2024 | - } |
|
| 2025 | - // was event trashed or restored ? |
|
| 2026 | - switch ($event_status) { |
|
| 2027 | - case 'draft': |
|
| 2028 | - $action = 'restored from the trash'; |
|
| 2029 | - $hook = 'AHEE_event_restored_from_trash'; |
|
| 2030 | - break; |
|
| 2031 | - case 'trash': |
|
| 2032 | - $action = 'moved to the trash'; |
|
| 2033 | - $hook = 'AHEE_event_moved_to_trash'; |
|
| 2034 | - break; |
|
| 2035 | - default: |
|
| 2036 | - $action = 'updated'; |
|
| 2037 | - $hook = false; |
|
| 2038 | - } |
|
| 2039 | - // use class to change status |
|
| 2040 | - $this->_cpt_model_obj->set_status($event_status); |
|
| 2041 | - $success = $this->_cpt_model_obj->save(); |
|
| 2042 | - if ($success === false) { |
|
| 2043 | - $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action); |
|
| 2044 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2045 | - return false; |
|
| 2046 | - } |
|
| 2047 | - if ($hook) { |
|
| 2048 | - do_action($hook); |
|
| 2049 | - } |
|
| 2050 | - return true; |
|
| 2051 | - } |
|
| 2052 | - |
|
| 2053 | - |
|
| 2054 | - /** |
|
| 2055 | - * _delete_event |
|
| 2056 | - * |
|
| 2057 | - * @access protected |
|
| 2058 | - * @param bool $redirect_after |
|
| 2059 | - */ |
|
| 2060 | - protected function _delete_event($redirect_after = true) |
|
| 2061 | - { |
|
| 2062 | - // determine the event id and set to array. |
|
| 2063 | - $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null; |
|
| 2064 | - $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID; |
|
| 2065 | - // loop thru events |
|
| 2066 | - if ($EVT_ID) { |
|
| 2067 | - $success = $this->_permanently_delete_event($EVT_ID); |
|
| 2068 | - // get list of events with no prices |
|
| 2069 | - $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array()); |
|
| 2070 | - // remove this event from the list of events with no prices |
|
| 2071 | - if (isset($espresso_no_ticket_prices[ $EVT_ID ])) { |
|
| 2072 | - unset($espresso_no_ticket_prices[ $EVT_ID ]); |
|
| 2073 | - } |
|
| 2074 | - update_option('ee_no_ticket_prices', $espresso_no_ticket_prices); |
|
| 2075 | - } else { |
|
| 2076 | - $success = false; |
|
| 2077 | - $msg = esc_html__( |
|
| 2078 | - 'An error occurred. An event could not be deleted because a valid event ID was not not supplied.', |
|
| 2079 | - 'event_espresso' |
|
| 2080 | - ); |
|
| 2081 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2082 | - } |
|
| 2083 | - if ($redirect_after) { |
|
| 2084 | - $this->_redirect_after_action( |
|
| 2085 | - $success, |
|
| 2086 | - 'Event', |
|
| 2087 | - 'deleted', |
|
| 2088 | - array('action' => 'default', 'status' => 'trash') |
|
| 2089 | - ); |
|
| 2090 | - } |
|
| 2091 | - } |
|
| 2092 | - |
|
| 2093 | - |
|
| 2094 | - /** |
|
| 2095 | - * _delete_events |
|
| 2096 | - * |
|
| 2097 | - * @access protected |
|
| 2098 | - * @return void |
|
| 2099 | - */ |
|
| 2100 | - protected function _delete_events() |
|
| 2101 | - { |
|
| 2102 | - $success = true; |
|
| 2103 | - // get list of events with no prices |
|
| 2104 | - $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array()); |
|
| 2105 | - // determine the event id and set to array. |
|
| 2106 | - $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array(); |
|
| 2107 | - // loop thru events |
|
| 2108 | - foreach ($EVT_IDs as $EVT_ID) { |
|
| 2109 | - $EVT_ID = absint($EVT_ID); |
|
| 2110 | - if ($EVT_ID) { |
|
| 2111 | - $results = $this->_permanently_delete_event($EVT_ID); |
|
| 2112 | - $success = $results !== false ? $success : false; |
|
| 2113 | - // remove this event from the list of events with no prices |
|
| 2114 | - unset($espresso_no_ticket_prices[ $EVT_ID ]); |
|
| 2115 | - } else { |
|
| 2116 | - $success = false; |
|
| 2117 | - $msg = esc_html__( |
|
| 2118 | - 'An error occurred. An event could not be deleted because a valid event ID was not not supplied.', |
|
| 2119 | - 'event_espresso' |
|
| 2120 | - ); |
|
| 2121 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2122 | - } |
|
| 2123 | - } |
|
| 2124 | - update_option('ee_no_ticket_prices', $espresso_no_ticket_prices); |
|
| 2125 | - // in order to force a pluralized result message we need to send back a success status greater than 1 |
|
| 2126 | - $success = $success ? 2 : false; |
|
| 2127 | - $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default')); |
|
| 2128 | - } |
|
| 2129 | - |
|
| 2130 | - |
|
| 2131 | - /** |
|
| 2132 | - * _permanently_delete_event |
|
| 2133 | - * |
|
| 2134 | - * @access private |
|
| 2135 | - * @param int $EVT_ID |
|
| 2136 | - * @return bool |
|
| 2137 | - */ |
|
| 2138 | - private function _permanently_delete_event($EVT_ID = 0) |
|
| 2139 | - { |
|
| 2140 | - // grab event id |
|
| 2141 | - if (! $EVT_ID) { |
|
| 2142 | - $msg = esc_html__( |
|
| 2143 | - 'An error occurred. No Event ID or an invalid Event ID was received.', |
|
| 2144 | - 'event_espresso' |
|
| 2145 | - ); |
|
| 2146 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2147 | - return false; |
|
| 2148 | - } |
|
| 2149 | - if (! $this->_cpt_model_obj instanceof EE_Event |
|
| 2150 | - || $this->_cpt_model_obj->ID() !== $EVT_ID |
|
| 2151 | - ) { |
|
| 2152 | - $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID); |
|
| 2153 | - } |
|
| 2154 | - if (! $this->_cpt_model_obj instanceof EE_Event) { |
|
| 2155 | - return false; |
|
| 2156 | - } |
|
| 2157 | - // need to delete related tickets and prices first. |
|
| 2158 | - $datetimes = $this->_cpt_model_obj->get_many_related('Datetime'); |
|
| 2159 | - foreach ($datetimes as $datetime) { |
|
| 2160 | - $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime'); |
|
| 2161 | - $tickets = $datetime->get_many_related('Ticket'); |
|
| 2162 | - foreach ($tickets as $ticket) { |
|
| 2163 | - $ticket->_remove_relation_to($datetime, 'Datetime'); |
|
| 2164 | - $ticket->delete_related_permanently('Price'); |
|
| 2165 | - $ticket->delete_permanently(); |
|
| 2166 | - } |
|
| 2167 | - $datetime->delete(); |
|
| 2168 | - } |
|
| 2169 | - // what about related venues or terms? |
|
| 2170 | - $venues = $this->_cpt_model_obj->get_many_related('Venue'); |
|
| 2171 | - foreach ($venues as $venue) { |
|
| 2172 | - $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue'); |
|
| 2173 | - } |
|
| 2174 | - // any attached question groups? |
|
| 2175 | - $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group'); |
|
| 2176 | - if (! empty($question_groups)) { |
|
| 2177 | - foreach ($question_groups as $question_group) { |
|
| 2178 | - $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group'); |
|
| 2179 | - } |
|
| 2180 | - } |
|
| 2181 | - // Message Template Groups |
|
| 2182 | - $this->_cpt_model_obj->_remove_relations('Message_Template_Group'); |
|
| 2183 | - /** @type EE_Term_Taxonomy[] $term_taxonomies */ |
|
| 2184 | - $term_taxonomies = $this->_cpt_model_obj->term_taxonomies(); |
|
| 2185 | - foreach ($term_taxonomies as $term_taxonomy) { |
|
| 2186 | - $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy); |
|
| 2187 | - } |
|
| 2188 | - $success = $this->_cpt_model_obj->delete_permanently(); |
|
| 2189 | - // did it all go as planned ? |
|
| 2190 | - if ($success) { |
|
| 2191 | - $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID); |
|
| 2192 | - EE_Error::add_success($msg); |
|
| 2193 | - } else { |
|
| 2194 | - $msg = sprintf( |
|
| 2195 | - esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'), |
|
| 2196 | - $EVT_ID |
|
| 2197 | - ); |
|
| 2198 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2199 | - return false; |
|
| 2200 | - } |
|
| 2201 | - do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID); |
|
| 2202 | - return true; |
|
| 2203 | - } |
|
| 2204 | - |
|
| 2205 | - |
|
| 2206 | - /** |
|
| 2207 | - * get total number of events |
|
| 2208 | - * |
|
| 2209 | - * @access public |
|
| 2210 | - * @return int |
|
| 2211 | - */ |
|
| 2212 | - public function total_events() |
|
| 2213 | - { |
|
| 2214 | - $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true); |
|
| 2215 | - return $count; |
|
| 2216 | - } |
|
| 2217 | - |
|
| 2218 | - |
|
| 2219 | - /** |
|
| 2220 | - * get total number of draft events |
|
| 2221 | - * |
|
| 2222 | - * @access public |
|
| 2223 | - * @return int |
|
| 2224 | - */ |
|
| 2225 | - public function total_events_draft() |
|
| 2226 | - { |
|
| 2227 | - $where = array( |
|
| 2228 | - 'status' => array('IN', array('draft', 'auto-draft')), |
|
| 2229 | - ); |
|
| 2230 | - $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true); |
|
| 2231 | - return $count; |
|
| 2232 | - } |
|
| 2233 | - |
|
| 2234 | - |
|
| 2235 | - /** |
|
| 2236 | - * get total number of trashed events |
|
| 2237 | - * |
|
| 2238 | - * @access public |
|
| 2239 | - * @return int |
|
| 2240 | - */ |
|
| 2241 | - public function total_trashed_events() |
|
| 2242 | - { |
|
| 2243 | - $where = array( |
|
| 2244 | - 'status' => 'trash', |
|
| 2245 | - ); |
|
| 2246 | - $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true); |
|
| 2247 | - return $count; |
|
| 2248 | - } |
|
| 2249 | - |
|
| 2250 | - |
|
| 2251 | - /** |
|
| 2252 | - * _default_event_settings |
|
| 2253 | - * This generates the Default Settings Tab |
|
| 2254 | - * |
|
| 2255 | - * @return void |
|
| 2256 | - * @throws EE_Error |
|
| 2257 | - */ |
|
| 2258 | - protected function _default_event_settings() |
|
| 2259 | - { |
|
| 2260 | - $this->_set_add_edit_form_tags('update_default_event_settings'); |
|
| 2261 | - $this->_set_publish_post_box_vars(null, false, false, null, false); |
|
| 2262 | - $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html(); |
|
| 2263 | - $this->display_admin_page_with_sidebar(); |
|
| 2264 | - } |
|
| 2265 | - |
|
| 2266 | - |
|
| 2267 | - /** |
|
| 2268 | - * Return the form for event settings. |
|
| 2269 | - * |
|
| 2270 | - * @return EE_Form_Section_Proper |
|
| 2271 | - * @throws EE_Error |
|
| 2272 | - */ |
|
| 2273 | - protected function _default_event_settings_form() |
|
| 2274 | - { |
|
| 2275 | - $registration_config = EE_Registry::instance()->CFG->registration; |
|
| 2276 | - $registration_stati_for_selection = EEM_Registration::reg_status_array( |
|
| 2277 | - // exclude |
|
| 2278 | - array( |
|
| 2279 | - EEM_Registration::status_id_cancelled, |
|
| 2280 | - EEM_Registration::status_id_declined, |
|
| 2281 | - EEM_Registration::status_id_incomplete, |
|
| 2282 | - EEM_Registration::status_id_wait_list, |
|
| 2283 | - ), |
|
| 2284 | - true |
|
| 2285 | - ); |
|
| 2286 | - return new EE_Form_Section_Proper( |
|
| 2287 | - array( |
|
| 2288 | - 'name' => 'update_default_event_settings', |
|
| 2289 | - 'html_id' => 'update_default_event_settings', |
|
| 2290 | - 'html_class' => 'form-table', |
|
| 2291 | - 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
| 2292 | - 'subsections' => apply_filters( |
|
| 2293 | - 'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections', |
|
| 2294 | - array( |
|
| 2295 | - 'default_reg_status' => new EE_Select_Input( |
|
| 2296 | - $registration_stati_for_selection, |
|
| 2297 | - array( |
|
| 2298 | - 'default' => isset($registration_config->default_STS_ID) |
|
| 2299 | - && array_key_exists( |
|
| 2300 | - $registration_config->default_STS_ID, |
|
| 2301 | - $registration_stati_for_selection |
|
| 2302 | - ) |
|
| 2303 | - ? sanitize_text_field($registration_config->default_STS_ID) |
|
| 2304 | - : EEM_Registration::status_id_pending_payment, |
|
| 2305 | - 'html_label_text' => esc_html__('Default Registration Status', 'event_espresso') |
|
| 2306 | - . EEH_Template::get_help_tab_link( |
|
| 2307 | - 'default_settings_status_help_tab' |
|
| 2308 | - ), |
|
| 2309 | - 'html_help_text' => esc_html__( |
|
| 2310 | - 'This setting allows you to preselect what the default registration status setting is when creating an event. Note that changing this setting does NOT retroactively apply it to existing events.', |
|
| 2311 | - 'event_espresso' |
|
| 2312 | - ), |
|
| 2313 | - ) |
|
| 2314 | - ), |
|
| 2315 | - 'default_max_tickets' => new EE_Integer_Input( |
|
| 2316 | - array( |
|
| 2317 | - 'default' => isset($registration_config->default_maximum_number_of_tickets) |
|
| 2318 | - ? $registration_config->default_maximum_number_of_tickets |
|
| 2319 | - : EEM_Event::get_default_additional_limit(), |
|
| 2320 | - 'html_label_text' => esc_html__( |
|
| 2321 | - 'Default Maximum Tickets Allowed Per Order:', |
|
| 2322 | - 'event_espresso' |
|
| 2323 | - ) |
|
| 2324 | - . EEH_Template::get_help_tab_link( |
|
| 2325 | - 'default_maximum_tickets_help_tab"' |
|
| 2326 | - ), |
|
| 2327 | - 'html_help_text' => esc_html__( |
|
| 2328 | - 'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.', |
|
| 2329 | - 'event_espresso' |
|
| 2330 | - ), |
|
| 2331 | - ) |
|
| 2332 | - ), |
|
| 2333 | - ) |
|
| 2334 | - ), |
|
| 2335 | - ) |
|
| 2336 | - ); |
|
| 2337 | - } |
|
| 2338 | - |
|
| 2339 | - |
|
| 2340 | - /** |
|
| 2341 | - * _update_default_event_settings |
|
| 2342 | - * |
|
| 2343 | - * @access protected |
|
| 2344 | - * @return void |
|
| 2345 | - * @throws EE_Error |
|
| 2346 | - */ |
|
| 2347 | - protected function _update_default_event_settings() |
|
| 2348 | - { |
|
| 2349 | - $registration_config = EE_Registry::instance()->CFG->registration; |
|
| 2350 | - $form = $this->_default_event_settings_form(); |
|
| 2351 | - if ($form->was_submitted()) { |
|
| 2352 | - $form->receive_form_submission(); |
|
| 2353 | - if ($form->is_valid()) { |
|
| 2354 | - $valid_data = $form->valid_data(); |
|
| 2355 | - if (isset($valid_data['default_reg_status'])) { |
|
| 2356 | - $registration_config->default_STS_ID = $valid_data['default_reg_status']; |
|
| 2357 | - } |
|
| 2358 | - if (isset($valid_data['default_max_tickets'])) { |
|
| 2359 | - $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets']; |
|
| 2360 | - } |
|
| 2361 | - // update because data was valid! |
|
| 2362 | - EE_Registry::instance()->CFG->update_espresso_config(); |
|
| 2363 | - EE_Error::overwrite_success(); |
|
| 2364 | - EE_Error::add_success( |
|
| 2365 | - __('Default Event Settings were updated', 'event_espresso') |
|
| 2366 | - ); |
|
| 2367 | - } |
|
| 2368 | - } |
|
| 2369 | - $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true); |
|
| 2370 | - } |
|
| 2371 | - |
|
| 2372 | - |
|
| 2373 | - /************* Templates *************/ |
|
| 2374 | - protected function _template_settings() |
|
| 2375 | - { |
|
| 2376 | - $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso'); |
|
| 2377 | - $this->_template_args['preview_img'] = '<img src="' |
|
| 2378 | - . EVENTS_ASSETS_URL |
|
| 2379 | - . DS |
|
| 2380 | - . 'images' |
|
| 2381 | - . DS |
|
| 2382 | - . 'caffeinated_template_features.jpg" alt="' |
|
| 2383 | - . esc_attr__('Template Settings Preview screenshot', 'event_espresso') |
|
| 2384 | - . '" />'; |
|
| 2385 | - $this->_template_args['preview_text'] = '<strong>' |
|
| 2386 | - . esc_html__( |
|
| 2387 | - 'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.', |
|
| 2388 | - 'event_espresso' |
|
| 2389 | - ) . '</strong>'; |
|
| 2390 | - $this->display_admin_caf_preview_page('template_settings_tab'); |
|
| 2391 | - } |
|
| 2392 | - |
|
| 2393 | - |
|
| 2394 | - /** Event Category Stuff **/ |
|
| 2395 | - /** |
|
| 2396 | - * set the _category property with the category object for the loaded page. |
|
| 2397 | - * |
|
| 2398 | - * @access private |
|
| 2399 | - * @return void |
|
| 2400 | - */ |
|
| 2401 | - private function _set_category_object() |
|
| 2402 | - { |
|
| 2403 | - if (isset($this->_category->id) && ! empty($this->_category->id)) { |
|
| 2404 | - return; |
|
| 2405 | - } //already have the category object so get out. |
|
| 2406 | - // set default category object |
|
| 2407 | - $this->_set_empty_category_object(); |
|
| 2408 | - // only set if we've got an id |
|
| 2409 | - if (! isset($this->_req_data['EVT_CAT_ID'])) { |
|
| 2410 | - return; |
|
| 2411 | - } |
|
| 2412 | - $category_id = absint($this->_req_data['EVT_CAT_ID']); |
|
| 2413 | - $term = get_term($category_id, 'espresso_event_categories'); |
|
| 2414 | - if (! empty($term)) { |
|
| 2415 | - $this->_category->category_name = $term->name; |
|
| 2416 | - $this->_category->category_identifier = $term->slug; |
|
| 2417 | - $this->_category->category_desc = $term->description; |
|
| 2418 | - $this->_category->id = $term->term_id; |
|
| 2419 | - $this->_category->parent = $term->parent; |
|
| 2420 | - } |
|
| 2421 | - } |
|
| 2422 | - |
|
| 2423 | - |
|
| 2424 | - /** |
|
| 2425 | - * Clears out category properties. |
|
| 2426 | - */ |
|
| 2427 | - private function _set_empty_category_object() |
|
| 2428 | - { |
|
| 2429 | - $this->_category = new stdClass(); |
|
| 2430 | - $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = ''; |
|
| 2431 | - $this->_category->id = $this->_category->parent = 0; |
|
| 2432 | - } |
|
| 2433 | - |
|
| 2434 | - |
|
| 2435 | - /** |
|
| 2436 | - * @throws EE_Error |
|
| 2437 | - */ |
|
| 2438 | - protected function _category_list_table() |
|
| 2439 | - { |
|
| 2440 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 2441 | - $this->_search_btn_label = esc_html__('Categories', 'event_espresso'); |
|
| 2442 | - $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 2443 | - 'add_category', |
|
| 2444 | - 'add_category', |
|
| 2445 | - array(), |
|
| 2446 | - 'add-new-h2' |
|
| 2447 | - ); |
|
| 2448 | - $this->display_admin_list_table_page_with_sidebar(); |
|
| 2449 | - } |
|
| 2450 | - |
|
| 2451 | - |
|
| 2452 | - /** |
|
| 2453 | - * Output category details view. |
|
| 2454 | - */ |
|
| 2455 | - protected function _category_details($view) |
|
| 2456 | - { |
|
| 2457 | - // load formatter helper |
|
| 2458 | - // load field generator helper |
|
| 2459 | - $route = $view == 'edit' ? 'update_category' : 'insert_category'; |
|
| 2460 | - $this->_set_add_edit_form_tags($route); |
|
| 2461 | - $this->_set_category_object(); |
|
| 2462 | - $id = ! empty($this->_category->id) ? $this->_category->id : ''; |
|
| 2463 | - $delete_action = 'delete_category'; |
|
| 2464 | - // custom redirect |
|
| 2465 | - $redirect = EE_Admin_Page::add_query_args_and_nonce( |
|
| 2466 | - array('action' => 'category_list'), |
|
| 2467 | - $this->_admin_base_url |
|
| 2468 | - ); |
|
| 2469 | - $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect); |
|
| 2470 | - // take care of contents |
|
| 2471 | - $this->_template_args['admin_page_content'] = $this->_category_details_content(); |
|
| 2472 | - $this->display_admin_page_with_sidebar(); |
|
| 2473 | - } |
|
| 2474 | - |
|
| 2475 | - |
|
| 2476 | - /** |
|
| 2477 | - * Output category details content. |
|
| 2478 | - */ |
|
| 2479 | - protected function _category_details_content() |
|
| 2480 | - { |
|
| 2481 | - $editor_args['category_desc'] = array( |
|
| 2482 | - 'type' => 'wp_editor', |
|
| 2483 | - 'value' => EEH_Formatter::admin_format_content($this->_category->category_desc), |
|
| 2484 | - 'class' => 'my_editor_custom', |
|
| 2485 | - 'wpeditor_args' => array('media_buttons' => false), |
|
| 2486 | - ); |
|
| 2487 | - $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array'); |
|
| 2488 | - $all_terms = get_terms( |
|
| 2489 | - array('espresso_event_categories'), |
|
| 2490 | - array('hide_empty' => 0, 'exclude' => array($this->_category->id)) |
|
| 2491 | - ); |
|
| 2492 | - // setup category select for term parents. |
|
| 2493 | - $category_select_values[] = array( |
|
| 2494 | - 'text' => esc_html__('No Parent', 'event_espresso'), |
|
| 2495 | - 'id' => 0, |
|
| 2496 | - ); |
|
| 2497 | - foreach ($all_terms as $term) { |
|
| 2498 | - $category_select_values[] = array( |
|
| 2499 | - 'text' => $term->name, |
|
| 2500 | - 'id' => $term->term_id, |
|
| 2501 | - ); |
|
| 2502 | - } |
|
| 2503 | - $category_select = EEH_Form_Fields::select_input( |
|
| 2504 | - 'category_parent', |
|
| 2505 | - $category_select_values, |
|
| 2506 | - $this->_category->parent |
|
| 2507 | - ); |
|
| 2508 | - $template_args = array( |
|
| 2509 | - 'category' => $this->_category, |
|
| 2510 | - 'category_select' => $category_select, |
|
| 2511 | - 'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'), |
|
| 2512 | - 'category_desc_editor' => $_wp_editor['category_desc']['field'], |
|
| 2513 | - 'disable' => '', |
|
| 2514 | - 'disabled_message' => false, |
|
| 2515 | - ); |
|
| 2516 | - $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php'; |
|
| 2517 | - return EEH_Template::display_template($template, $template_args, true); |
|
| 2518 | - } |
|
| 2519 | - |
|
| 2520 | - |
|
| 2521 | - /** |
|
| 2522 | - * Handles deleting categories. |
|
| 2523 | - */ |
|
| 2524 | - protected function _delete_categories() |
|
| 2525 | - { |
|
| 2526 | - $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID'] |
|
| 2527 | - : (array) $this->_req_data['category_id']; |
|
| 2528 | - foreach ($cat_ids as $cat_id) { |
|
| 2529 | - $this->_delete_category($cat_id); |
|
| 2530 | - } |
|
| 2531 | - // doesn't matter what page we're coming from... we're going to the same place after delete. |
|
| 2532 | - $query_args = array( |
|
| 2533 | - 'action' => 'category_list', |
|
| 2534 | - ); |
|
| 2535 | - $this->_redirect_after_action(0, '', '', $query_args); |
|
| 2536 | - } |
|
| 2537 | - |
|
| 2538 | - |
|
| 2539 | - /** |
|
| 2540 | - * Handles deleting specific category. |
|
| 2541 | - * |
|
| 2542 | - * @param int $cat_id |
|
| 2543 | - */ |
|
| 2544 | - protected function _delete_category($cat_id) |
|
| 2545 | - { |
|
| 2546 | - $cat_id = absint($cat_id); |
|
| 2547 | - wp_delete_term($cat_id, 'espresso_event_categories'); |
|
| 2548 | - } |
|
| 2549 | - |
|
| 2550 | - |
|
| 2551 | - /** |
|
| 2552 | - * Handles triggering the update or insertion of a new category. |
|
| 2553 | - * |
|
| 2554 | - * @param bool $new_category true means we're triggering the insert of a new category. |
|
| 2555 | - */ |
|
| 2556 | - protected function _insert_or_update_category($new_category) |
|
| 2557 | - { |
|
| 2558 | - $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true); |
|
| 2559 | - $success = 0; // we already have a success message so lets not send another. |
|
| 2560 | - if ($cat_id) { |
|
| 2561 | - $query_args = array( |
|
| 2562 | - 'action' => 'edit_category', |
|
| 2563 | - 'EVT_CAT_ID' => $cat_id, |
|
| 2564 | - ); |
|
| 2565 | - } else { |
|
| 2566 | - $query_args = array('action' => 'add_category'); |
|
| 2567 | - } |
|
| 2568 | - $this->_redirect_after_action($success, '', '', $query_args, true); |
|
| 2569 | - } |
|
| 2570 | - |
|
| 2571 | - |
|
| 2572 | - /** |
|
| 2573 | - * Inserts or updates category |
|
| 2574 | - * |
|
| 2575 | - * @param bool $update (true indicates we're updating a category). |
|
| 2576 | - * @return bool|mixed|string |
|
| 2577 | - */ |
|
| 2578 | - private function _insert_category($update = false) |
|
| 2579 | - { |
|
| 2580 | - $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : ''; |
|
| 2581 | - $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : ''; |
|
| 2582 | - $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : ''; |
|
| 2583 | - $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0; |
|
| 2584 | - if (empty($category_name)) { |
|
| 2585 | - $msg = esc_html__('You must add a name for the category.', 'event_espresso'); |
|
| 2586 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2587 | - return false; |
|
| 2588 | - } |
|
| 2589 | - $term_args = array( |
|
| 2590 | - 'name' => $category_name, |
|
| 2591 | - 'description' => $category_desc, |
|
| 2592 | - 'parent' => $category_parent, |
|
| 2593 | - ); |
|
| 2594 | - // was the category_identifier input disabled? |
|
| 2595 | - if (isset($this->_req_data['category_identifier'])) { |
|
| 2596 | - $term_args['slug'] = $this->_req_data['category_identifier']; |
|
| 2597 | - } |
|
| 2598 | - $insert_ids = $update |
|
| 2599 | - ? wp_update_term($cat_id, 'espresso_event_categories', $term_args) |
|
| 2600 | - : wp_insert_term($category_name, 'espresso_event_categories', $term_args); |
|
| 2601 | - if (! is_array($insert_ids)) { |
|
| 2602 | - $msg = esc_html__( |
|
| 2603 | - 'An error occurred and the category has not been saved to the database.', |
|
| 2604 | - 'event_espresso' |
|
| 2605 | - ); |
|
| 2606 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2607 | - } else { |
|
| 2608 | - $cat_id = $insert_ids['term_id']; |
|
| 2609 | - $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name); |
|
| 2610 | - EE_Error::add_success($msg); |
|
| 2611 | - } |
|
| 2612 | - return $cat_id; |
|
| 2613 | - } |
|
| 2614 | - |
|
| 2615 | - |
|
| 2616 | - /** |
|
| 2617 | - * Gets categories or count of categories matching the arguments in the request. |
|
| 2618 | - * |
|
| 2619 | - * @param int $per_page |
|
| 2620 | - * @param int $current_page |
|
| 2621 | - * @param bool $count |
|
| 2622 | - * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int |
|
| 2623 | - */ |
|
| 2624 | - public function get_categories($per_page = 10, $current_page = 1, $count = false) |
|
| 2625 | - { |
|
| 2626 | - // testing term stuff |
|
| 2627 | - $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id'; |
|
| 2628 | - $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC'; |
|
| 2629 | - $limit = ($current_page - 1) * $per_page; |
|
| 2630 | - $where = array('taxonomy' => 'espresso_event_categories'); |
|
| 2631 | - if (isset($this->_req_data['s'])) { |
|
| 2632 | - $sstr = '%' . $this->_req_data['s'] . '%'; |
|
| 2633 | - $where['OR'] = array( |
|
| 2634 | - 'Term.name' => array('LIKE', $sstr), |
|
| 2635 | - 'description' => array('LIKE', $sstr), |
|
| 2636 | - ); |
|
| 2637 | - } |
|
| 2638 | - $query_params = array( |
|
| 2639 | - $where, |
|
| 2640 | - 'order_by' => array($orderby => $order), |
|
| 2641 | - 'limit' => $limit . ',' . $per_page, |
|
| 2642 | - 'force_join' => array('Term'), |
|
| 2643 | - ); |
|
| 2644 | - $categories = $count |
|
| 2645 | - ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id') |
|
| 2646 | - : EEM_Term_Taxonomy::instance()->get_all($query_params); |
|
| 2647 | - return $categories; |
|
| 2648 | - } |
|
| 2649 | - |
|
| 2650 | - /* end category stuff */ |
|
| 2651 | - /**************/ |
|
| 2652 | - |
|
| 2653 | - |
|
| 2654 | - /** |
|
| 2655 | - * Callback for the `ee_save_timezone_setting` ajax action. |
|
| 2656 | - * |
|
| 2657 | - * @throws EE_Error |
|
| 2658 | - */ |
|
| 2659 | - public function save_timezonestring_setting() |
|
| 2660 | - { |
|
| 2661 | - $timezone_string = isset($this->_req_data['timezone_selected']) |
|
| 2662 | - ? $this->_req_data['timezone_selected'] |
|
| 2663 | - : ''; |
|
| 2664 | - if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) { |
|
| 2665 | - EE_Error::add_error( |
|
| 2666 | - esc_html('An invalid timezone string submitted.', 'event_espresso'), |
|
| 2667 | - __FILE__, |
|
| 2668 | - __FUNCTION__, |
|
| 2669 | - __LINE__ |
|
| 2670 | - ); |
|
| 2671 | - $this->_template_args['error'] = true; |
|
| 2672 | - $this->_return_json(); |
|
| 2673 | - } |
|
| 2674 | - |
|
| 2675 | - update_option('timezone_string', $timezone_string); |
|
| 2676 | - EE_Error::add_success( |
|
| 2677 | - esc_html__('Your timezone string was updated.', 'event_espresso') |
|
| 2678 | - ); |
|
| 2679 | - $this->_template_args['success'] = true; |
|
| 2680 | - $this->_return_json(true, array('action' => 'create_new')); |
|
| 2681 | - } |
|
| 15 | + /** |
|
| 16 | + * This will hold the event object for event_details screen. |
|
| 17 | + * |
|
| 18 | + * @access protected |
|
| 19 | + * @var EE_Event $_event |
|
| 20 | + */ |
|
| 21 | + protected $_event; |
|
| 22 | + |
|
| 23 | + |
|
| 24 | + /** |
|
| 25 | + * This will hold the category object for category_details screen. |
|
| 26 | + * |
|
| 27 | + * @var stdClass $_category |
|
| 28 | + */ |
|
| 29 | + protected $_category; |
|
| 30 | + |
|
| 31 | + |
|
| 32 | + /** |
|
| 33 | + * This will hold the event model instance |
|
| 34 | + * |
|
| 35 | + * @var EEM_Event $_event_model |
|
| 36 | + */ |
|
| 37 | + protected $_event_model; |
|
| 38 | + |
|
| 39 | + |
|
| 40 | + /** |
|
| 41 | + * @var EE_Event |
|
| 42 | + */ |
|
| 43 | + protected $_cpt_model_obj = false; |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + /** |
|
| 47 | + * Initialize page props for this admin page group. |
|
| 48 | + */ |
|
| 49 | + protected function _init_page_props() |
|
| 50 | + { |
|
| 51 | + $this->page_slug = EVENTS_PG_SLUG; |
|
| 52 | + $this->page_label = EVENTS_LABEL; |
|
| 53 | + $this->_admin_base_url = EVENTS_ADMIN_URL; |
|
| 54 | + $this->_admin_base_path = EVENTS_ADMIN; |
|
| 55 | + $this->_cpt_model_names = array( |
|
| 56 | + 'create_new' => 'EEM_Event', |
|
| 57 | + 'edit' => 'EEM_Event', |
|
| 58 | + ); |
|
| 59 | + $this->_cpt_edit_routes = array( |
|
| 60 | + 'espresso_events' => 'edit', |
|
| 61 | + ); |
|
| 62 | + add_action( |
|
| 63 | + 'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object', |
|
| 64 | + array($this, 'verify_event_edit'), |
|
| 65 | + 10, |
|
| 66 | + 2 |
|
| 67 | + ); |
|
| 68 | + } |
|
| 69 | + |
|
| 70 | + |
|
| 71 | + /** |
|
| 72 | + * Sets the ajax hooks used for this admin page group. |
|
| 73 | + */ |
|
| 74 | + protected function _ajax_hooks() |
|
| 75 | + { |
|
| 76 | + add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting')); |
|
| 77 | + } |
|
| 78 | + |
|
| 79 | + |
|
| 80 | + /** |
|
| 81 | + * Sets the page properties for this admin page group. |
|
| 82 | + */ |
|
| 83 | + protected function _define_page_props() |
|
| 84 | + { |
|
| 85 | + $this->_admin_page_title = EVENTS_LABEL; |
|
| 86 | + $this->_labels = array( |
|
| 87 | + 'buttons' => array( |
|
| 88 | + 'add' => esc_html__('Add New Event', 'event_espresso'), |
|
| 89 | + 'edit' => esc_html__('Edit Event', 'event_espresso'), |
|
| 90 | + 'delete' => esc_html__('Delete Event', 'event_espresso'), |
|
| 91 | + 'add_category' => esc_html__('Add New Category', 'event_espresso'), |
|
| 92 | + 'edit_category' => esc_html__('Edit Category', 'event_espresso'), |
|
| 93 | + 'delete_category' => esc_html__('Delete Category', 'event_espresso'), |
|
| 94 | + ), |
|
| 95 | + 'editor_title' => array( |
|
| 96 | + 'espresso_events' => esc_html__('Enter event title here', 'event_espresso'), |
|
| 97 | + ), |
|
| 98 | + 'publishbox' => array( |
|
| 99 | + 'create_new' => esc_html__('Save New Event', 'event_espresso'), |
|
| 100 | + 'edit' => esc_html__('Update Event', 'event_espresso'), |
|
| 101 | + 'add_category' => esc_html__('Save New Category', 'event_espresso'), |
|
| 102 | + 'edit_category' => esc_html__('Update Category', 'event_espresso'), |
|
| 103 | + 'template_settings' => esc_html__('Update Settings', 'event_espresso'), |
|
| 104 | + ), |
|
| 105 | + ); |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + |
|
| 109 | + /** |
|
| 110 | + * Sets the page routes property for this admin page group. |
|
| 111 | + */ |
|
| 112 | + protected function _set_page_routes() |
|
| 113 | + { |
|
| 114 | + // load formatter helper |
|
| 115 | + // load field generator helper |
|
| 116 | + // is there a evt_id in the request? |
|
| 117 | + $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID']) |
|
| 118 | + ? $this->_req_data['EVT_ID'] |
|
| 119 | + : 0; |
|
| 120 | + $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id; |
|
| 121 | + $this->_page_routes = array( |
|
| 122 | + 'default' => array( |
|
| 123 | + 'func' => '_events_overview_list_table', |
|
| 124 | + 'capability' => 'ee_read_events', |
|
| 125 | + ), |
|
| 126 | + 'create_new' => array( |
|
| 127 | + 'func' => '_create_new_cpt_item', |
|
| 128 | + 'capability' => 'ee_edit_events', |
|
| 129 | + ), |
|
| 130 | + 'edit' => array( |
|
| 131 | + 'func' => '_edit_cpt_item', |
|
| 132 | + 'capability' => 'ee_edit_event', |
|
| 133 | + 'obj_id' => $evt_id, |
|
| 134 | + ), |
|
| 135 | + 'copy_event' => array( |
|
| 136 | + 'func' => '_copy_events', |
|
| 137 | + 'capability' => 'ee_edit_event', |
|
| 138 | + 'obj_id' => $evt_id, |
|
| 139 | + 'noheader' => true, |
|
| 140 | + ), |
|
| 141 | + 'trash_event' => array( |
|
| 142 | + 'func' => '_trash_or_restore_event', |
|
| 143 | + 'args' => array('event_status' => 'trash'), |
|
| 144 | + 'capability' => 'ee_delete_event', |
|
| 145 | + 'obj_id' => $evt_id, |
|
| 146 | + 'noheader' => true, |
|
| 147 | + ), |
|
| 148 | + 'trash_events' => array( |
|
| 149 | + 'func' => '_trash_or_restore_events', |
|
| 150 | + 'args' => array('event_status' => 'trash'), |
|
| 151 | + 'capability' => 'ee_delete_events', |
|
| 152 | + 'noheader' => true, |
|
| 153 | + ), |
|
| 154 | + 'restore_event' => array( |
|
| 155 | + 'func' => '_trash_or_restore_event', |
|
| 156 | + 'args' => array('event_status' => 'draft'), |
|
| 157 | + 'capability' => 'ee_delete_event', |
|
| 158 | + 'obj_id' => $evt_id, |
|
| 159 | + 'noheader' => true, |
|
| 160 | + ), |
|
| 161 | + 'restore_events' => array( |
|
| 162 | + 'func' => '_trash_or_restore_events', |
|
| 163 | + 'args' => array('event_status' => 'draft'), |
|
| 164 | + 'capability' => 'ee_delete_events', |
|
| 165 | + 'noheader' => true, |
|
| 166 | + ), |
|
| 167 | + 'delete_event' => array( |
|
| 168 | + 'func' => '_delete_event', |
|
| 169 | + 'capability' => 'ee_delete_event', |
|
| 170 | + 'obj_id' => $evt_id, |
|
| 171 | + 'noheader' => true, |
|
| 172 | + ), |
|
| 173 | + 'delete_events' => array( |
|
| 174 | + 'func' => '_delete_events', |
|
| 175 | + 'capability' => 'ee_delete_events', |
|
| 176 | + 'noheader' => true, |
|
| 177 | + ), |
|
| 178 | + 'view_report' => array( |
|
| 179 | + 'func' => '_view_report', |
|
| 180 | + 'capablity' => 'ee_edit_events', |
|
| 181 | + ), |
|
| 182 | + 'default_event_settings' => array( |
|
| 183 | + 'func' => '_default_event_settings', |
|
| 184 | + 'capability' => 'manage_options', |
|
| 185 | + ), |
|
| 186 | + 'update_default_event_settings' => array( |
|
| 187 | + 'func' => '_update_default_event_settings', |
|
| 188 | + 'capability' => 'manage_options', |
|
| 189 | + 'noheader' => true, |
|
| 190 | + ), |
|
| 191 | + 'template_settings' => array( |
|
| 192 | + 'func' => '_template_settings', |
|
| 193 | + 'capability' => 'manage_options', |
|
| 194 | + ), |
|
| 195 | + // event category tab related |
|
| 196 | + 'add_category' => array( |
|
| 197 | + 'func' => '_category_details', |
|
| 198 | + 'capability' => 'ee_edit_event_category', |
|
| 199 | + 'args' => array('add'), |
|
| 200 | + ), |
|
| 201 | + 'edit_category' => array( |
|
| 202 | + 'func' => '_category_details', |
|
| 203 | + 'capability' => 'ee_edit_event_category', |
|
| 204 | + 'args' => array('edit'), |
|
| 205 | + ), |
|
| 206 | + 'delete_categories' => array( |
|
| 207 | + 'func' => '_delete_categories', |
|
| 208 | + 'capability' => 'ee_delete_event_category', |
|
| 209 | + 'noheader' => true, |
|
| 210 | + ), |
|
| 211 | + 'delete_category' => array( |
|
| 212 | + 'func' => '_delete_categories', |
|
| 213 | + 'capability' => 'ee_delete_event_category', |
|
| 214 | + 'noheader' => true, |
|
| 215 | + ), |
|
| 216 | + 'insert_category' => array( |
|
| 217 | + 'func' => '_insert_or_update_category', |
|
| 218 | + 'args' => array('new_category' => true), |
|
| 219 | + 'capability' => 'ee_edit_event_category', |
|
| 220 | + 'noheader' => true, |
|
| 221 | + ), |
|
| 222 | + 'update_category' => array( |
|
| 223 | + 'func' => '_insert_or_update_category', |
|
| 224 | + 'args' => array('new_category' => false), |
|
| 225 | + 'capability' => 'ee_edit_event_category', |
|
| 226 | + 'noheader' => true, |
|
| 227 | + ), |
|
| 228 | + 'category_list' => array( |
|
| 229 | + 'func' => '_category_list_table', |
|
| 230 | + 'capability' => 'ee_manage_event_categories', |
|
| 231 | + ), |
|
| 232 | + ); |
|
| 233 | + } |
|
| 234 | + |
|
| 235 | + |
|
| 236 | + /** |
|
| 237 | + * Set the _page_config property for this admin page group. |
|
| 238 | + */ |
|
| 239 | + protected function _set_page_config() |
|
| 240 | + { |
|
| 241 | + $this->_page_config = array( |
|
| 242 | + 'default' => array( |
|
| 243 | + 'nav' => array( |
|
| 244 | + 'label' => esc_html__('Overview', 'event_espresso'), |
|
| 245 | + 'order' => 10, |
|
| 246 | + ), |
|
| 247 | + 'list_table' => 'Events_Admin_List_Table', |
|
| 248 | + 'help_tabs' => array( |
|
| 249 | + 'events_overview_help_tab' => array( |
|
| 250 | + 'title' => esc_html__('Events Overview', 'event_espresso'), |
|
| 251 | + 'filename' => 'events_overview', |
|
| 252 | + ), |
|
| 253 | + 'events_overview_table_column_headings_help_tab' => array( |
|
| 254 | + 'title' => esc_html__('Events Overview Table Column Headings', 'event_espresso'), |
|
| 255 | + 'filename' => 'events_overview_table_column_headings', |
|
| 256 | + ), |
|
| 257 | + 'events_overview_filters_help_tab' => array( |
|
| 258 | + 'title' => esc_html__('Events Overview Filters', 'event_espresso'), |
|
| 259 | + 'filename' => 'events_overview_filters', |
|
| 260 | + ), |
|
| 261 | + 'events_overview_view_help_tab' => array( |
|
| 262 | + 'title' => esc_html__('Events Overview Views', 'event_espresso'), |
|
| 263 | + 'filename' => 'events_overview_views', |
|
| 264 | + ), |
|
| 265 | + 'events_overview_other_help_tab' => array( |
|
| 266 | + 'title' => esc_html__('Events Overview Other', 'event_espresso'), |
|
| 267 | + 'filename' => 'events_overview_other', |
|
| 268 | + ), |
|
| 269 | + ), |
|
| 270 | + 'help_tour' => array( |
|
| 271 | + 'Event_Overview_Help_Tour', |
|
| 272 | + // 'New_Features_Test_Help_Tour' for testing multiple help tour |
|
| 273 | + ), |
|
| 274 | + 'qtips' => array( |
|
| 275 | + 'EE_Event_List_Table_Tips', |
|
| 276 | + ), |
|
| 277 | + 'require_nonce' => false, |
|
| 278 | + ), |
|
| 279 | + 'create_new' => array( |
|
| 280 | + 'nav' => array( |
|
| 281 | + 'label' => esc_html__('Add Event', 'event_espresso'), |
|
| 282 | + 'order' => 5, |
|
| 283 | + 'persistent' => false, |
|
| 284 | + ), |
|
| 285 | + 'metaboxes' => array('_register_event_editor_meta_boxes'), |
|
| 286 | + 'help_tabs' => array( |
|
| 287 | + 'event_editor_help_tab' => array( |
|
| 288 | + 'title' => esc_html__('Event Editor', 'event_espresso'), |
|
| 289 | + 'filename' => 'event_editor', |
|
| 290 | + ), |
|
| 291 | + 'event_editor_title_richtexteditor_help_tab' => array( |
|
| 292 | + 'title' => esc_html__('Event Title & Rich Text Editor', 'event_espresso'), |
|
| 293 | + 'filename' => 'event_editor_title_richtexteditor', |
|
| 294 | + ), |
|
| 295 | + 'event_editor_venue_details_help_tab' => array( |
|
| 296 | + 'title' => esc_html__('Event Venue Details', 'event_espresso'), |
|
| 297 | + 'filename' => 'event_editor_venue_details', |
|
| 298 | + ), |
|
| 299 | + 'event_editor_event_datetimes_help_tab' => array( |
|
| 300 | + 'title' => esc_html__('Event Datetimes', 'event_espresso'), |
|
| 301 | + 'filename' => 'event_editor_event_datetimes', |
|
| 302 | + ), |
|
| 303 | + 'event_editor_event_tickets_help_tab' => array( |
|
| 304 | + 'title' => esc_html__('Event Tickets', 'event_espresso'), |
|
| 305 | + 'filename' => 'event_editor_event_tickets', |
|
| 306 | + ), |
|
| 307 | + 'event_editor_event_registration_options_help_tab' => array( |
|
| 308 | + 'title' => esc_html__('Event Registration Options', 'event_espresso'), |
|
| 309 | + 'filename' => 'event_editor_event_registration_options', |
|
| 310 | + ), |
|
| 311 | + 'event_editor_tags_categories_help_tab' => array( |
|
| 312 | + 'title' => esc_html__('Event Tags & Categories', 'event_espresso'), |
|
| 313 | + 'filename' => 'event_editor_tags_categories', |
|
| 314 | + ), |
|
| 315 | + 'event_editor_questions_registrants_help_tab' => array( |
|
| 316 | + 'title' => esc_html__('Questions for Registrants', 'event_espresso'), |
|
| 317 | + 'filename' => 'event_editor_questions_registrants', |
|
| 318 | + ), |
|
| 319 | + 'event_editor_save_new_event_help_tab' => array( |
|
| 320 | + 'title' => esc_html__('Save New Event', 'event_espresso'), |
|
| 321 | + 'filename' => 'event_editor_save_new_event', |
|
| 322 | + ), |
|
| 323 | + 'event_editor_other_help_tab' => array( |
|
| 324 | + 'title' => esc_html__('Event Other', 'event_espresso'), |
|
| 325 | + 'filename' => 'event_editor_other', |
|
| 326 | + ), |
|
| 327 | + ), |
|
| 328 | + 'help_tour' => array( |
|
| 329 | + 'Event_Editor_Help_Tour', |
|
| 330 | + ), |
|
| 331 | + 'qtips' => array('EE_Event_Editor_Decaf_Tips'), |
|
| 332 | + 'require_nonce' => false, |
|
| 333 | + ), |
|
| 334 | + 'edit' => array( |
|
| 335 | + 'nav' => array( |
|
| 336 | + 'label' => esc_html__('Edit Event', 'event_espresso'), |
|
| 337 | + 'order' => 5, |
|
| 338 | + 'persistent' => false, |
|
| 339 | + 'url' => isset($this->_req_data['post']) |
|
| 340 | + ? EE_Admin_Page::add_query_args_and_nonce( |
|
| 341 | + array('post' => $this->_req_data['post'], 'action' => 'edit'), |
|
| 342 | + $this->_current_page_view_url |
|
| 343 | + ) |
|
| 344 | + : $this->_admin_base_url, |
|
| 345 | + ), |
|
| 346 | + 'metaboxes' => array('_register_event_editor_meta_boxes'), |
|
| 347 | + 'help_tabs' => array( |
|
| 348 | + 'event_editor_help_tab' => array( |
|
| 349 | + 'title' => esc_html__('Event Editor', 'event_espresso'), |
|
| 350 | + 'filename' => 'event_editor', |
|
| 351 | + ), |
|
| 352 | + 'event_editor_title_richtexteditor_help_tab' => array( |
|
| 353 | + 'title' => esc_html__('Event Title & Rich Text Editor', 'event_espresso'), |
|
| 354 | + 'filename' => 'event_editor_title_richtexteditor', |
|
| 355 | + ), |
|
| 356 | + 'event_editor_venue_details_help_tab' => array( |
|
| 357 | + 'title' => esc_html__('Event Venue Details', 'event_espresso'), |
|
| 358 | + 'filename' => 'event_editor_venue_details', |
|
| 359 | + ), |
|
| 360 | + 'event_editor_event_datetimes_help_tab' => array( |
|
| 361 | + 'title' => esc_html__('Event Datetimes', 'event_espresso'), |
|
| 362 | + 'filename' => 'event_editor_event_datetimes', |
|
| 363 | + ), |
|
| 364 | + 'event_editor_event_tickets_help_tab' => array( |
|
| 365 | + 'title' => esc_html__('Event Tickets', 'event_espresso'), |
|
| 366 | + 'filename' => 'event_editor_event_tickets', |
|
| 367 | + ), |
|
| 368 | + 'event_editor_event_registration_options_help_tab' => array( |
|
| 369 | + 'title' => esc_html__('Event Registration Options', 'event_espresso'), |
|
| 370 | + 'filename' => 'event_editor_event_registration_options', |
|
| 371 | + ), |
|
| 372 | + 'event_editor_tags_categories_help_tab' => array( |
|
| 373 | + 'title' => esc_html__('Event Tags & Categories', 'event_espresso'), |
|
| 374 | + 'filename' => 'event_editor_tags_categories', |
|
| 375 | + ), |
|
| 376 | + 'event_editor_questions_registrants_help_tab' => array( |
|
| 377 | + 'title' => esc_html__('Questions for Registrants', 'event_espresso'), |
|
| 378 | + 'filename' => 'event_editor_questions_registrants', |
|
| 379 | + ), |
|
| 380 | + 'event_editor_save_new_event_help_tab' => array( |
|
| 381 | + 'title' => esc_html__('Save New Event', 'event_espresso'), |
|
| 382 | + 'filename' => 'event_editor_save_new_event', |
|
| 383 | + ), |
|
| 384 | + 'event_editor_other_help_tab' => array( |
|
| 385 | + 'title' => esc_html__('Event Other', 'event_espresso'), |
|
| 386 | + 'filename' => 'event_editor_other', |
|
| 387 | + ), |
|
| 388 | + ), |
|
| 389 | + 'qtips' => array('EE_Event_Editor_Decaf_Tips'), |
|
| 390 | + 'require_nonce' => false, |
|
| 391 | + ), |
|
| 392 | + 'default_event_settings' => array( |
|
| 393 | + 'nav' => array( |
|
| 394 | + 'label' => esc_html__('Default Settings', 'event_espresso'), |
|
| 395 | + 'order' => 40, |
|
| 396 | + ), |
|
| 397 | + 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
| 398 | + 'labels' => array( |
|
| 399 | + 'publishbox' => esc_html__('Update Settings', 'event_espresso'), |
|
| 400 | + ), |
|
| 401 | + 'help_tabs' => array( |
|
| 402 | + 'default_settings_help_tab' => array( |
|
| 403 | + 'title' => esc_html__('Default Event Settings', 'event_espresso'), |
|
| 404 | + 'filename' => 'events_default_settings', |
|
| 405 | + ), |
|
| 406 | + 'default_settings_status_help_tab' => array( |
|
| 407 | + 'title' => esc_html__('Default Registration Status', 'event_espresso'), |
|
| 408 | + 'filename' => 'events_default_settings_status', |
|
| 409 | + ), |
|
| 410 | + 'default_maximum_tickets_help_tab' => array( |
|
| 411 | + 'title' => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'), |
|
| 412 | + 'filename' => 'events_default_settings_max_tickets', |
|
| 413 | + ), |
|
| 414 | + ), |
|
| 415 | + 'help_tour' => array('Event_Default_Settings_Help_Tour'), |
|
| 416 | + 'require_nonce' => false, |
|
| 417 | + ), |
|
| 418 | + // template settings |
|
| 419 | + 'template_settings' => array( |
|
| 420 | + 'nav' => array( |
|
| 421 | + 'label' => esc_html__('Templates', 'event_espresso'), |
|
| 422 | + 'order' => 30, |
|
| 423 | + ), |
|
| 424 | + 'metaboxes' => $this->_default_espresso_metaboxes, |
|
| 425 | + 'help_tabs' => array( |
|
| 426 | + 'general_settings_templates_help_tab' => array( |
|
| 427 | + 'title' => esc_html__('Templates', 'event_espresso'), |
|
| 428 | + 'filename' => 'general_settings_templates', |
|
| 429 | + ), |
|
| 430 | + ), |
|
| 431 | + 'help_tour' => array('Templates_Help_Tour'), |
|
| 432 | + 'require_nonce' => false, |
|
| 433 | + ), |
|
| 434 | + // event category stuff |
|
| 435 | + 'add_category' => array( |
|
| 436 | + 'nav' => array( |
|
| 437 | + 'label' => esc_html__('Add Category', 'event_espresso'), |
|
| 438 | + 'order' => 15, |
|
| 439 | + 'persistent' => false, |
|
| 440 | + ), |
|
| 441 | + 'help_tabs' => array( |
|
| 442 | + 'add_category_help_tab' => array( |
|
| 443 | + 'title' => esc_html__('Add New Event Category', 'event_espresso'), |
|
| 444 | + 'filename' => 'events_add_category', |
|
| 445 | + ), |
|
| 446 | + ), |
|
| 447 | + 'help_tour' => array('Event_Add_Category_Help_Tour'), |
|
| 448 | + 'metaboxes' => array('_publish_post_box'), |
|
| 449 | + 'require_nonce' => false, |
|
| 450 | + ), |
|
| 451 | + 'edit_category' => array( |
|
| 452 | + 'nav' => array( |
|
| 453 | + 'label' => esc_html__('Edit Category', 'event_espresso'), |
|
| 454 | + 'order' => 15, |
|
| 455 | + 'persistent' => false, |
|
| 456 | + 'url' => isset($this->_req_data['EVT_CAT_ID']) |
|
| 457 | + ? add_query_arg( |
|
| 458 | + array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']), |
|
| 459 | + $this->_current_page_view_url |
|
| 460 | + ) |
|
| 461 | + : $this->_admin_base_url, |
|
| 462 | + ), |
|
| 463 | + 'help_tabs' => array( |
|
| 464 | + 'edit_category_help_tab' => array( |
|
| 465 | + 'title' => esc_html__('Edit Event Category', 'event_espresso'), |
|
| 466 | + 'filename' => 'events_edit_category', |
|
| 467 | + ), |
|
| 468 | + ), |
|
| 469 | + /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/ |
|
| 470 | + 'metaboxes' => array('_publish_post_box'), |
|
| 471 | + 'require_nonce' => false, |
|
| 472 | + ), |
|
| 473 | + 'category_list' => array( |
|
| 474 | + 'nav' => array( |
|
| 475 | + 'label' => esc_html__('Categories', 'event_espresso'), |
|
| 476 | + 'order' => 20, |
|
| 477 | + ), |
|
| 478 | + 'list_table' => 'Event_Categories_Admin_List_Table', |
|
| 479 | + 'help_tabs' => array( |
|
| 480 | + 'events_categories_help_tab' => array( |
|
| 481 | + 'title' => esc_html__('Event Categories', 'event_espresso'), |
|
| 482 | + 'filename' => 'events_categories', |
|
| 483 | + ), |
|
| 484 | + 'events_categories_table_column_headings_help_tab' => array( |
|
| 485 | + 'title' => esc_html__('Event Categories Table Column Headings', 'event_espresso'), |
|
| 486 | + 'filename' => 'events_categories_table_column_headings', |
|
| 487 | + ), |
|
| 488 | + 'events_categories_view_help_tab' => array( |
|
| 489 | + 'title' => esc_html__('Event Categories Views', 'event_espresso'), |
|
| 490 | + 'filename' => 'events_categories_views', |
|
| 491 | + ), |
|
| 492 | + 'events_categories_other_help_tab' => array( |
|
| 493 | + 'title' => esc_html__('Event Categories Other', 'event_espresso'), |
|
| 494 | + 'filename' => 'events_categories_other', |
|
| 495 | + ), |
|
| 496 | + ), |
|
| 497 | + 'help_tour' => array( |
|
| 498 | + 'Event_Categories_Help_Tour', |
|
| 499 | + ), |
|
| 500 | + 'metaboxes' => $this->_default_espresso_metaboxes, |
|
| 501 | + 'require_nonce' => false, |
|
| 502 | + ), |
|
| 503 | + ); |
|
| 504 | + } |
|
| 505 | + |
|
| 506 | + |
|
| 507 | + /** |
|
| 508 | + * Used to register any global screen options if necessary for every route in this admin page group. |
|
| 509 | + */ |
|
| 510 | + protected function _add_screen_options() |
|
| 511 | + { |
|
| 512 | + } |
|
| 513 | + |
|
| 514 | + |
|
| 515 | + /** |
|
| 516 | + * Implementing the screen options for the 'default' route. |
|
| 517 | + */ |
|
| 518 | + protected function _add_screen_options_default() |
|
| 519 | + { |
|
| 520 | + $this->_per_page_screen_option(); |
|
| 521 | + } |
|
| 522 | + |
|
| 523 | + |
|
| 524 | + /** |
|
| 525 | + * Implementing screen options for the category list route. |
|
| 526 | + */ |
|
| 527 | + protected function _add_screen_options_category_list() |
|
| 528 | + { |
|
| 529 | + $page_title = $this->_admin_page_title; |
|
| 530 | + $this->_admin_page_title = esc_html__('Categories', 'event_espresso'); |
|
| 531 | + $this->_per_page_screen_option(); |
|
| 532 | + $this->_admin_page_title = $page_title; |
|
| 533 | + } |
|
| 534 | + |
|
| 535 | + |
|
| 536 | + /** |
|
| 537 | + * Used to register any global feature pointers for the admin page group. |
|
| 538 | + */ |
|
| 539 | + protected function _add_feature_pointers() |
|
| 540 | + { |
|
| 541 | + } |
|
| 542 | + |
|
| 543 | + |
|
| 544 | + /** |
|
| 545 | + * Registers and enqueues any global scripts and styles for the entire admin page group. |
|
| 546 | + */ |
|
| 547 | + public function load_scripts_styles() |
|
| 548 | + { |
|
| 549 | + wp_register_style( |
|
| 550 | + 'events-admin-css', |
|
| 551 | + EVENTS_ASSETS_URL . 'events-admin-page.css', |
|
| 552 | + array(), |
|
| 553 | + EVENT_ESPRESSO_VERSION |
|
| 554 | + ); |
|
| 555 | + wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION); |
|
| 556 | + wp_enqueue_style('events-admin-css'); |
|
| 557 | + wp_enqueue_style('ee-cat-admin'); |
|
| 558 | + // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details |
|
| 559 | + // registers for all views |
|
| 560 | + // scripts |
|
| 561 | + wp_register_script( |
|
| 562 | + 'event_editor_js', |
|
| 563 | + EVENTS_ASSETS_URL . 'event_editor.js', |
|
| 564 | + array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'), |
|
| 565 | + EVENT_ESPRESSO_VERSION, |
|
| 566 | + true |
|
| 567 | + ); |
|
| 568 | + } |
|
| 569 | + |
|
| 570 | + |
|
| 571 | + /** |
|
| 572 | + * Enqueuing scripts and styles specific to this view |
|
| 573 | + */ |
|
| 574 | + public function load_scripts_styles_create_new() |
|
| 575 | + { |
|
| 576 | + $this->load_scripts_styles_edit(); |
|
| 577 | + } |
|
| 578 | + |
|
| 579 | + |
|
| 580 | + /** |
|
| 581 | + * Enqueuing scripts and styles specific to this view |
|
| 582 | + */ |
|
| 583 | + public function load_scripts_styles_edit() |
|
| 584 | + { |
|
| 585 | + // styles |
|
| 586 | + wp_enqueue_style('espresso-ui-theme'); |
|
| 587 | + wp_register_style( |
|
| 588 | + 'event-editor-css', |
|
| 589 | + EVENTS_ASSETS_URL . 'event-editor.css', |
|
| 590 | + array('ee-admin-css'), |
|
| 591 | + EVENT_ESPRESSO_VERSION |
|
| 592 | + ); |
|
| 593 | + wp_enqueue_style('event-editor-css'); |
|
| 594 | + // scripts |
|
| 595 | + wp_register_script( |
|
| 596 | + 'event-datetime-metabox', |
|
| 597 | + EVENTS_ASSETS_URL . 'event-datetime-metabox.js', |
|
| 598 | + array('event_editor_js', 'ee-datepicker'), |
|
| 599 | + EVENT_ESPRESSO_VERSION |
|
| 600 | + ); |
|
| 601 | + wp_enqueue_script('event-datetime-metabox'); |
|
| 602 | + } |
|
| 603 | + |
|
| 604 | + |
|
| 605 | + /** |
|
| 606 | + * Populating the _views property for the category list table view. |
|
| 607 | + */ |
|
| 608 | + protected function _set_list_table_views_category_list() |
|
| 609 | + { |
|
| 610 | + $this->_views = array( |
|
| 611 | + 'all' => array( |
|
| 612 | + 'slug' => 'all', |
|
| 613 | + 'label' => esc_html__('All', 'event_espresso'), |
|
| 614 | + 'count' => 0, |
|
| 615 | + 'bulk_action' => array( |
|
| 616 | + 'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 617 | + ), |
|
| 618 | + ), |
|
| 619 | + ); |
|
| 620 | + } |
|
| 621 | + |
|
| 622 | + |
|
| 623 | + /** |
|
| 624 | + * For adding anything that fires on the admin_init hook for any route within this admin page group. |
|
| 625 | + */ |
|
| 626 | + public function admin_init() |
|
| 627 | + { |
|
| 628 | + EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__( |
|
| 629 | + 'Do you really want to delete this image? Please remember to update your event to complete the removal.', |
|
| 630 | + 'event_espresso' |
|
| 631 | + ); |
|
| 632 | + } |
|
| 633 | + |
|
| 634 | + |
|
| 635 | + /** |
|
| 636 | + * For adding anything that should be triggered on the admin_notices hook for any route within this admin page |
|
| 637 | + * group. |
|
| 638 | + */ |
|
| 639 | + public function admin_notices() |
|
| 640 | + { |
|
| 641 | + } |
|
| 642 | + |
|
| 643 | + |
|
| 644 | + /** |
|
| 645 | + * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within |
|
| 646 | + * this admin page group. |
|
| 647 | + */ |
|
| 648 | + public function admin_footer_scripts() |
|
| 649 | + { |
|
| 650 | + } |
|
| 651 | + |
|
| 652 | + |
|
| 653 | + /** |
|
| 654 | + * Call this function to verify if an event is public and has tickets for sale. If it does, then we need to show a |
|
| 655 | + * warning (via EE_Error::add_error()); |
|
| 656 | + * |
|
| 657 | + * @param EE_Event $event Event object |
|
| 658 | + * @param string $req_type |
|
| 659 | + * @return void |
|
| 660 | + * @throws EE_Error |
|
| 661 | + * @access public |
|
| 662 | + */ |
|
| 663 | + public function verify_event_edit($event = null, $req_type = '') |
|
| 664 | + { |
|
| 665 | + // don't need to do this when processing |
|
| 666 | + if (! empty($req_type)) { |
|
| 667 | + return; |
|
| 668 | + } |
|
| 669 | + // no event? |
|
| 670 | + if (empty($event)) { |
|
| 671 | + // set event |
|
| 672 | + $event = $this->_cpt_model_obj; |
|
| 673 | + } |
|
| 674 | + // STILL no event? |
|
| 675 | + if (! $event instanceof EE_Event) { |
|
| 676 | + return; |
|
| 677 | + } |
|
| 678 | + $orig_status = $event->status(); |
|
| 679 | + // first check if event is active. |
|
| 680 | + if ($orig_status === EEM_Event::cancelled |
|
| 681 | + || $orig_status === EEM_Event::postponed |
|
| 682 | + || $event->is_expired() |
|
| 683 | + || $event->is_inactive() |
|
| 684 | + ) { |
|
| 685 | + return; |
|
| 686 | + } |
|
| 687 | + // made it here so it IS active... next check that any of the tickets are sold. |
|
| 688 | + if ($event->is_sold_out(true)) { |
|
| 689 | + if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) { |
|
| 690 | + EE_Error::add_attention( |
|
| 691 | + sprintf( |
|
| 692 | + esc_html__( |
|
| 693 | + 'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event. However, this change is not permanent until you update the event. You can change the status back to something else before updating if you wish.', |
|
| 694 | + 'event_espresso' |
|
| 695 | + ), |
|
| 696 | + EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence') |
|
| 697 | + ) |
|
| 698 | + ); |
|
| 699 | + } |
|
| 700 | + return; |
|
| 701 | + } elseif ($orig_status === EEM_Event::sold_out) { |
|
| 702 | + EE_Error::add_attention( |
|
| 703 | + sprintf( |
|
| 704 | + esc_html__( |
|
| 705 | + 'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets. However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.', |
|
| 706 | + 'event_espresso' |
|
| 707 | + ), |
|
| 708 | + EEH_Template::pretty_status($event->status(), false, 'sentence') |
|
| 709 | + ) |
|
| 710 | + ); |
|
| 711 | + } |
|
| 712 | + // now we need to determine if the event has any tickets on sale. If not then we dont' show the error |
|
| 713 | + if (! $event->tickets_on_sale()) { |
|
| 714 | + return; |
|
| 715 | + } |
|
| 716 | + // made it here so show warning |
|
| 717 | + $this->_edit_event_warning(); |
|
| 718 | + } |
|
| 719 | + |
|
| 720 | + |
|
| 721 | + /** |
|
| 722 | + * This is the text used for when an event is being edited that is public and has tickets for sale. |
|
| 723 | + * When needed, hook this into a EE_Error::add_error() notice. |
|
| 724 | + * |
|
| 725 | + * @access protected |
|
| 726 | + * @return void |
|
| 727 | + */ |
|
| 728 | + protected function _edit_event_warning() |
|
| 729 | + { |
|
| 730 | + // we don't want to add warnings during these requests |
|
| 731 | + if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') { |
|
| 732 | + return; |
|
| 733 | + } |
|
| 734 | + EE_Error::add_attention( |
|
| 735 | + sprintf( |
|
| 736 | + esc_html__( |
|
| 737 | + 'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s', |
|
| 738 | + 'event_espresso' |
|
| 739 | + ), |
|
| 740 | + '<a class="espresso-help-tab-lnk">', |
|
| 741 | + '</a>' |
|
| 742 | + ) |
|
| 743 | + ); |
|
| 744 | + } |
|
| 745 | + |
|
| 746 | + |
|
| 747 | + /** |
|
| 748 | + * When a user is creating a new event, notify them if they haven't set their timezone. |
|
| 749 | + * Otherwise, do the normal logic |
|
| 750 | + * |
|
| 751 | + * @return string |
|
| 752 | + * @throws \EE_Error |
|
| 753 | + */ |
|
| 754 | + protected function _create_new_cpt_item() |
|
| 755 | + { |
|
| 756 | + $has_timezone_string = get_option('timezone_string'); |
|
| 757 | + // only nag them about setting their timezone if it's their first event, and they haven't already done it |
|
| 758 | + if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) { |
|
| 759 | + EE_Error::add_attention( |
|
| 760 | + sprintf( |
|
| 761 | + __( |
|
| 762 | + 'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s', |
|
| 763 | + 'event_espresso' |
|
| 764 | + ), |
|
| 765 | + '<br>', |
|
| 766 | + '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">' |
|
| 767 | + . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale()) |
|
| 768 | + . '</select>', |
|
| 769 | + '<button class="button button-secondary timezone-submit">', |
|
| 770 | + '</button><span class="spinner"></span>' |
|
| 771 | + ), |
|
| 772 | + __FILE__, |
|
| 773 | + __FUNCTION__, |
|
| 774 | + __LINE__ |
|
| 775 | + ); |
|
| 776 | + } |
|
| 777 | + return parent::_create_new_cpt_item(); |
|
| 778 | + } |
|
| 779 | + |
|
| 780 | + |
|
| 781 | + /** |
|
| 782 | + * Sets the _views property for the default route in this admin page group. |
|
| 783 | + */ |
|
| 784 | + protected function _set_list_table_views_default() |
|
| 785 | + { |
|
| 786 | + $this->_views = array( |
|
| 787 | + 'all' => array( |
|
| 788 | + 'slug' => 'all', |
|
| 789 | + 'label' => esc_html__('View All Events', 'event_espresso'), |
|
| 790 | + 'count' => 0, |
|
| 791 | + 'bulk_action' => array( |
|
| 792 | + 'trash_events' => esc_html__('Move to Trash', 'event_espresso'), |
|
| 793 | + ), |
|
| 794 | + ), |
|
| 795 | + 'draft' => array( |
|
| 796 | + 'slug' => 'draft', |
|
| 797 | + 'label' => esc_html__('Draft', 'event_espresso'), |
|
| 798 | + 'count' => 0, |
|
| 799 | + 'bulk_action' => array( |
|
| 800 | + 'trash_events' => esc_html__('Move to Trash', 'event_espresso'), |
|
| 801 | + ), |
|
| 802 | + ), |
|
| 803 | + ); |
|
| 804 | + if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) { |
|
| 805 | + $this->_views['trash'] = array( |
|
| 806 | + 'slug' => 'trash', |
|
| 807 | + 'label' => esc_html__('Trash', 'event_espresso'), |
|
| 808 | + 'count' => 0, |
|
| 809 | + 'bulk_action' => array( |
|
| 810 | + 'restore_events' => esc_html__('Restore From Trash', 'event_espresso'), |
|
| 811 | + 'delete_events' => esc_html__('Delete Permanently', 'event_espresso'), |
|
| 812 | + ), |
|
| 813 | + ); |
|
| 814 | + } |
|
| 815 | + } |
|
| 816 | + |
|
| 817 | + |
|
| 818 | + /** |
|
| 819 | + * Provides the legend item array for the default list table view. |
|
| 820 | + * |
|
| 821 | + * @return array |
|
| 822 | + */ |
|
| 823 | + protected function _event_legend_items() |
|
| 824 | + { |
|
| 825 | + $items = array( |
|
| 826 | + 'view_details' => array( |
|
| 827 | + 'class' => 'dashicons dashicons-search', |
|
| 828 | + 'desc' => esc_html__('View Event', 'event_espresso'), |
|
| 829 | + ), |
|
| 830 | + 'edit_event' => array( |
|
| 831 | + 'class' => 'ee-icon ee-icon-calendar-edit', |
|
| 832 | + 'desc' => esc_html__('Edit Event Details', 'event_espresso'), |
|
| 833 | + ), |
|
| 834 | + 'view_attendees' => array( |
|
| 835 | + 'class' => 'dashicons dashicons-groups', |
|
| 836 | + 'desc' => esc_html__('View Registrations for Event', 'event_espresso'), |
|
| 837 | + ), |
|
| 838 | + ); |
|
| 839 | + $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items); |
|
| 840 | + $statuses = array( |
|
| 841 | + 'sold_out_status' => array( |
|
| 842 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out, |
|
| 843 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'), |
|
| 844 | + ), |
|
| 845 | + 'active_status' => array( |
|
| 846 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active, |
|
| 847 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'), |
|
| 848 | + ), |
|
| 849 | + 'upcoming_status' => array( |
|
| 850 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming, |
|
| 851 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'), |
|
| 852 | + ), |
|
| 853 | + 'postponed_status' => array( |
|
| 854 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed, |
|
| 855 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'), |
|
| 856 | + ), |
|
| 857 | + 'cancelled_status' => array( |
|
| 858 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled, |
|
| 859 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'), |
|
| 860 | + ), |
|
| 861 | + 'expired_status' => array( |
|
| 862 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired, |
|
| 863 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'), |
|
| 864 | + ), |
|
| 865 | + 'inactive_status' => array( |
|
| 866 | + 'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive, |
|
| 867 | + 'desc' => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'), |
|
| 868 | + ), |
|
| 869 | + ); |
|
| 870 | + $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses); |
|
| 871 | + return array_merge($items, $statuses); |
|
| 872 | + } |
|
| 873 | + |
|
| 874 | + |
|
| 875 | + /** |
|
| 876 | + * @return EEM_Event |
|
| 877 | + */ |
|
| 878 | + private function _event_model() |
|
| 879 | + { |
|
| 880 | + if (! $this->_event_model instanceof EEM_Event) { |
|
| 881 | + $this->_event_model = EE_Registry::instance()->load_model('Event'); |
|
| 882 | + } |
|
| 883 | + return $this->_event_model; |
|
| 884 | + } |
|
| 885 | + |
|
| 886 | + |
|
| 887 | + /** |
|
| 888 | + * Adds extra buttons to the WP CPT permalink field row. |
|
| 889 | + * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter. |
|
| 890 | + * |
|
| 891 | + * @param string $return the current html |
|
| 892 | + * @param int $id the post id for the page |
|
| 893 | + * @param string $new_title What the title is |
|
| 894 | + * @param string $new_slug what the slug is |
|
| 895 | + * @return string The new html string for the permalink area |
|
| 896 | + */ |
|
| 897 | + public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug) |
|
| 898 | + { |
|
| 899 | + // make sure this is only when editing |
|
| 900 | + if (! empty($id)) { |
|
| 901 | + $post = get_post($id); |
|
| 902 | + $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#" tabindex="-1">' |
|
| 903 | + . esc_html__('Shortcode', 'event_espresso') |
|
| 904 | + . '</a> '; |
|
| 905 | + $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id=' |
|
| 906 | + . $post->ID |
|
| 907 | + . ']">'; |
|
| 908 | + } |
|
| 909 | + return $return; |
|
| 910 | + } |
|
| 911 | + |
|
| 912 | + |
|
| 913 | + /** |
|
| 914 | + * _events_overview_list_table |
|
| 915 | + * This contains the logic for showing the events_overview list |
|
| 916 | + * |
|
| 917 | + * @access protected |
|
| 918 | + * @return void |
|
| 919 | + * @throws \EE_Error |
|
| 920 | + */ |
|
| 921 | + protected function _events_overview_list_table() |
|
| 922 | + { |
|
| 923 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 924 | + $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table']) |
|
| 925 | + ? (array) $this->_template_args['after_list_table'] |
|
| 926 | + : array(); |
|
| 927 | + $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br() |
|
| 928 | + . EEH_Template::get_button_or_link( |
|
| 929 | + get_post_type_archive_link('espresso_events'), |
|
| 930 | + esc_html__("View Event Archive Page", "event_espresso"), |
|
| 931 | + 'button' |
|
| 932 | + ); |
|
| 933 | + $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items()); |
|
| 934 | + $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 935 | + 'create_new', |
|
| 936 | + 'add', |
|
| 937 | + array(), |
|
| 938 | + 'add-new-h2' |
|
| 939 | + ); |
|
| 940 | + $this->display_admin_list_table_page_with_no_sidebar(); |
|
| 941 | + } |
|
| 942 | + |
|
| 943 | + |
|
| 944 | + /** |
|
| 945 | + * this allows for extra misc actions in the default WP publish box |
|
| 946 | + * |
|
| 947 | + * @return void |
|
| 948 | + */ |
|
| 949 | + public function extra_misc_actions_publish_box() |
|
| 950 | + { |
|
| 951 | + $this->_generate_publish_box_extra_content(); |
|
| 952 | + } |
|
| 953 | + |
|
| 954 | + |
|
| 955 | + /** |
|
| 956 | + * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been |
|
| 957 | + * saved. |
|
| 958 | + * Typically you would use this to save any additional data. |
|
| 959 | + * Keep in mind also that "save_post" runs on EVERY post update to the database. |
|
| 960 | + * ALSO very important. When a post transitions from scheduled to published, |
|
| 961 | + * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from |
|
| 962 | + * other meta saves. So MAKE sure that you handle this accordingly. |
|
| 963 | + * |
|
| 964 | + * @access protected |
|
| 965 | + * @abstract |
|
| 966 | + * @param string $post_id The ID of the cpt that was saved (so you can link relationally) |
|
| 967 | + * @param object $post The post object of the cpt that was saved. |
|
| 968 | + * @return void |
|
| 969 | + * @throws \EE_Error |
|
| 970 | + */ |
|
| 971 | + protected function _insert_update_cpt_item($post_id, $post) |
|
| 972 | + { |
|
| 973 | + if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') { |
|
| 974 | + // get out we're not processing an event save. |
|
| 975 | + return; |
|
| 976 | + } |
|
| 977 | + $event_values = array( |
|
| 978 | + 'EVT_display_desc' => ! empty($this->_req_data['display_desc']) ? 1 : 0, |
|
| 979 | + 'EVT_display_ticket_selector' => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0, |
|
| 980 | + 'EVT_additional_limit' => min( |
|
| 981 | + apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255), |
|
| 982 | + ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null |
|
| 983 | + ), |
|
| 984 | + 'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status']) |
|
| 985 | + ? $this->_req_data['EVT_default_registration_status'] |
|
| 986 | + : EE_Registry::instance()->CFG->registration->default_STS_ID, |
|
| 987 | + 'EVT_member_only' => ! empty($this->_req_data['member_only']) ? 1 : 0, |
|
| 988 | + 'EVT_allow_overflow' => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0, |
|
| 989 | + 'EVT_timezone_string' => ! empty($this->_req_data['timezone_string']) |
|
| 990 | + ? $this->_req_data['timezone_string'] : null, |
|
| 991 | + 'EVT_external_URL' => ! empty($this->_req_data['externalURL']) |
|
| 992 | + ? $this->_req_data['externalURL'] : null, |
|
| 993 | + 'EVT_phone' => ! empty($this->_req_data['event_phone']) |
|
| 994 | + ? $this->_req_data['event_phone'] : null, |
|
| 995 | + ); |
|
| 996 | + // update event |
|
| 997 | + $success = $this->_event_model()->update_by_ID($event_values, $post_id); |
|
| 998 | + // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id! |
|
| 999 | + $get_one_where = array( |
|
| 1000 | + $this->_event_model()->primary_key_name() => $post_id, |
|
| 1001 | + 'OR' => array( |
|
| 1002 | + 'status' => $post->post_status, |
|
| 1003 | + // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db, |
|
| 1004 | + // but the returned object here has a status of "publish", so use the original post status as well |
|
| 1005 | + 'status*1' => $this->_req_data['original_post_status'], |
|
| 1006 | + ), |
|
| 1007 | + ); |
|
| 1008 | + $event = $this->_event_model()->get_one(array($get_one_where)); |
|
| 1009 | + // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons. |
|
| 1010 | + $event_update_callbacks = apply_filters( |
|
| 1011 | + 'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks', |
|
| 1012 | + array( |
|
| 1013 | + array($this, '_default_venue_update'), |
|
| 1014 | + array($this, '_default_tickets_update'), |
|
| 1015 | + ) |
|
| 1016 | + ); |
|
| 1017 | + $att_success = true; |
|
| 1018 | + foreach ($event_update_callbacks as $e_callback) { |
|
| 1019 | + $_success = is_callable($e_callback) |
|
| 1020 | + ? call_user_func($e_callback, $event, $this->_req_data) |
|
| 1021 | + : false; |
|
| 1022 | + // if ANY of these updates fail then we want the appropriate global error message |
|
| 1023 | + $att_success = ! $att_success ? $att_success : $_success; |
|
| 1024 | + } |
|
| 1025 | + // any errors? |
|
| 1026 | + if ($success && false === $att_success) { |
|
| 1027 | + EE_Error::add_error( |
|
| 1028 | + esc_html__( |
|
| 1029 | + 'Event Details saved successfully but something went wrong with saving attachments.', |
|
| 1030 | + 'event_espresso' |
|
| 1031 | + ), |
|
| 1032 | + __FILE__, |
|
| 1033 | + __FUNCTION__, |
|
| 1034 | + __LINE__ |
|
| 1035 | + ); |
|
| 1036 | + } elseif ($success === false) { |
|
| 1037 | + EE_Error::add_error( |
|
| 1038 | + esc_html__('Event Details did not save successfully.', 'event_espresso'), |
|
| 1039 | + __FILE__, |
|
| 1040 | + __FUNCTION__, |
|
| 1041 | + __LINE__ |
|
| 1042 | + ); |
|
| 1043 | + } |
|
| 1044 | + } |
|
| 1045 | + |
|
| 1046 | + |
|
| 1047 | + /** |
|
| 1048 | + * @see parent::restore_item() |
|
| 1049 | + * @param int $post_id |
|
| 1050 | + * @param int $revision_id |
|
| 1051 | + */ |
|
| 1052 | + protected function _restore_cpt_item($post_id, $revision_id) |
|
| 1053 | + { |
|
| 1054 | + // copy existing event meta to new post |
|
| 1055 | + $post_evt = $this->_event_model()->get_one_by_ID($post_id); |
|
| 1056 | + if ($post_evt instanceof EE_Event) { |
|
| 1057 | + // meta revision restore |
|
| 1058 | + $post_evt->restore_revision($revision_id); |
|
| 1059 | + // related objs restore |
|
| 1060 | + $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price')); |
|
| 1061 | + } |
|
| 1062 | + } |
|
| 1063 | + |
|
| 1064 | + |
|
| 1065 | + /** |
|
| 1066 | + * Attach the venue to the Event |
|
| 1067 | + * |
|
| 1068 | + * @param \EE_Event $evtobj Event Object to add the venue to |
|
| 1069 | + * @param array $data The request data from the form |
|
| 1070 | + * @return bool Success or fail. |
|
| 1071 | + */ |
|
| 1072 | + protected function _default_venue_update(\EE_Event $evtobj, $data) |
|
| 1073 | + { |
|
| 1074 | + require_once(EE_MODELS . 'EEM_Venue.model.php'); |
|
| 1075 | + $venue_model = EE_Registry::instance()->load_model('Venue'); |
|
| 1076 | + $rows_affected = null; |
|
| 1077 | + $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null; |
|
| 1078 | + // very important. If we don't have a venue name... |
|
| 1079 | + // then we'll get out because not necessary to create empty venue |
|
| 1080 | + if (empty($data['venue_title'])) { |
|
| 1081 | + return false; |
|
| 1082 | + } |
|
| 1083 | + $venue_array = array( |
|
| 1084 | + 'VNU_wp_user' => $evtobj->get('EVT_wp_user'), |
|
| 1085 | + 'VNU_name' => ! empty($data['venue_title']) ? $data['venue_title'] : null, |
|
| 1086 | + 'VNU_desc' => ! empty($data['venue_description']) ? $data['venue_description'] : null, |
|
| 1087 | + 'VNU_identifier' => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null, |
|
| 1088 | + 'VNU_short_desc' => ! empty($data['venue_short_description']) ? $data['venue_short_description'] |
|
| 1089 | + : null, |
|
| 1090 | + 'VNU_address' => ! empty($data['address']) ? $data['address'] : null, |
|
| 1091 | + 'VNU_address2' => ! empty($data['address2']) ? $data['address2'] : null, |
|
| 1092 | + 'VNU_city' => ! empty($data['city']) ? $data['city'] : null, |
|
| 1093 | + 'STA_ID' => ! empty($data['state']) ? $data['state'] : null, |
|
| 1094 | + 'CNT_ISO' => ! empty($data['countries']) ? $data['countries'] : null, |
|
| 1095 | + 'VNU_zip' => ! empty($data['zip']) ? $data['zip'] : null, |
|
| 1096 | + 'VNU_phone' => ! empty($data['venue_phone']) ? $data['venue_phone'] : null, |
|
| 1097 | + 'VNU_capacity' => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null, |
|
| 1098 | + 'VNU_url' => ! empty($data['venue_url']) ? $data['venue_url'] : null, |
|
| 1099 | + 'VNU_virtual_phone' => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null, |
|
| 1100 | + 'VNU_virtual_url' => ! empty($data['virtual_url']) ? $data['virtual_url'] : null, |
|
| 1101 | + 'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0, |
|
| 1102 | + 'status' => 'publish', |
|
| 1103 | + ); |
|
| 1104 | + // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out. |
|
| 1105 | + if (! empty($venue_id)) { |
|
| 1106 | + $update_where = array($venue_model->primary_key_name() => $venue_id); |
|
| 1107 | + $rows_affected = $venue_model->update($venue_array, array($update_where)); |
|
| 1108 | + // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present. |
|
| 1109 | + $evtobj->_add_relation_to($venue_id, 'Venue'); |
|
| 1110 | + return $rows_affected > 0 ? true : false; |
|
| 1111 | + } else { |
|
| 1112 | + // we insert the venue |
|
| 1113 | + $venue_id = $venue_model->insert($venue_array); |
|
| 1114 | + $evtobj->_add_relation_to($venue_id, 'Venue'); |
|
| 1115 | + return ! empty($venue_id) ? true : false; |
|
| 1116 | + } |
|
| 1117 | + // when we have the ancestor come in it's already been handled by the revision save. |
|
| 1118 | + } |
|
| 1119 | + |
|
| 1120 | + |
|
| 1121 | + /** |
|
| 1122 | + * Handles saving everything related to Tickets (datetimes, tickets, prices) |
|
| 1123 | + * |
|
| 1124 | + * @param EE_Event $evtobj The Event object we're attaching data to |
|
| 1125 | + * @param array $data The request data from the form |
|
| 1126 | + * @return array |
|
| 1127 | + */ |
|
| 1128 | + protected function _default_tickets_update(EE_Event $evtobj, $data) |
|
| 1129 | + { |
|
| 1130 | + $success = true; |
|
| 1131 | + $saved_dtt = null; |
|
| 1132 | + $saved_tickets = array(); |
|
| 1133 | + $incoming_date_formats = array('Y-m-d', 'h:i a'); |
|
| 1134 | + foreach ($data['edit_event_datetimes'] as $row => $dtt) { |
|
| 1135 | + // trim all values to ensure any excess whitespace is removed. |
|
| 1136 | + $dtt = array_map('trim', $dtt); |
|
| 1137 | + $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end'] |
|
| 1138 | + : $dtt['DTT_EVT_start']; |
|
| 1139 | + $datetime_values = array( |
|
| 1140 | + 'DTT_ID' => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null, |
|
| 1141 | + 'DTT_EVT_start' => $dtt['DTT_EVT_start'], |
|
| 1142 | + 'DTT_EVT_end' => $dtt['DTT_EVT_end'], |
|
| 1143 | + 'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'], |
|
| 1144 | + 'DTT_order' => $row, |
|
| 1145 | + ); |
|
| 1146 | + // if we have an id then let's get existing object first and then set the new values. Otherwise we instantiate a new object for save. |
|
| 1147 | + if (! empty($dtt['DTT_ID'])) { |
|
| 1148 | + $DTM = EE_Registry::instance() |
|
| 1149 | + ->load_model('Datetime', array($evtobj->get_timezone())) |
|
| 1150 | + ->get_one_by_ID($dtt['DTT_ID']); |
|
| 1151 | + $DTM->set_date_format($incoming_date_formats[0]); |
|
| 1152 | + $DTM->set_time_format($incoming_date_formats[1]); |
|
| 1153 | + foreach ($datetime_values as $field => $value) { |
|
| 1154 | + $DTM->set($field, $value); |
|
| 1155 | + } |
|
| 1156 | + // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it. We need to do this so we dont' TRASH the parent DTT. |
|
| 1157 | + $saved_dtts[ $DTM->ID() ] = $DTM; |
|
| 1158 | + } else { |
|
| 1159 | + $DTM = EE_Registry::instance()->load_class( |
|
| 1160 | + 'Datetime', |
|
| 1161 | + array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats), |
|
| 1162 | + false, |
|
| 1163 | + false |
|
| 1164 | + ); |
|
| 1165 | + foreach ($datetime_values as $field => $value) { |
|
| 1166 | + $DTM->set($field, $value); |
|
| 1167 | + } |
|
| 1168 | + } |
|
| 1169 | + $DTM->save(); |
|
| 1170 | + $DTT = $evtobj->_add_relation_to($DTM, 'Datetime'); |
|
| 1171 | + // load DTT helper |
|
| 1172 | + // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date. |
|
| 1173 | + if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) { |
|
| 1174 | + $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start')); |
|
| 1175 | + $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days'); |
|
| 1176 | + $DTT->save(); |
|
| 1177 | + } |
|
| 1178 | + // now we got to make sure we add the new DTT_ID to the $saved_dtts array because it is possible there was a new one created for the autosave. |
|
| 1179 | + $saved_dtt = $DTT; |
|
| 1180 | + $success = ! $success ? $success : $DTT; |
|
| 1181 | + // if ANY of these updates fail then we want the appropriate global error message. |
|
| 1182 | + // //todo this is actually sucky we need a better error message but this is what it is for now. |
|
| 1183 | + } |
|
| 1184 | + // no dtts get deleted so we don't do any of that logic here. |
|
| 1185 | + // update tickets next |
|
| 1186 | + $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array(); |
|
| 1187 | + foreach ($data['edit_tickets'] as $row => $tkt) { |
|
| 1188 | + $incoming_date_formats = array('Y-m-d', 'h:i a'); |
|
| 1189 | + $update_prices = false; |
|
| 1190 | + $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount']) |
|
| 1191 | + ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0; |
|
| 1192 | + // trim inputs to ensure any excess whitespace is removed. |
|
| 1193 | + $tkt = array_map('trim', $tkt); |
|
| 1194 | + if (empty($tkt['TKT_start_date'])) { |
|
| 1195 | + // let's use now in the set timezone. |
|
| 1196 | + $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone())); |
|
| 1197 | + $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]); |
|
| 1198 | + } |
|
| 1199 | + if (empty($tkt['TKT_end_date'])) { |
|
| 1200 | + // use the start date of the first datetime |
|
| 1201 | + $dtt = $evtobj->first_datetime(); |
|
| 1202 | + $tkt['TKT_end_date'] = $dtt->start_date_and_time( |
|
| 1203 | + $incoming_date_formats[0], |
|
| 1204 | + $incoming_date_formats[1] |
|
| 1205 | + ); |
|
| 1206 | + } |
|
| 1207 | + $TKT_values = array( |
|
| 1208 | + 'TKT_ID' => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null, |
|
| 1209 | + 'TTM_ID' => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0, |
|
| 1210 | + 'TKT_name' => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '', |
|
| 1211 | + 'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '', |
|
| 1212 | + 'TKT_start_date' => $tkt['TKT_start_date'], |
|
| 1213 | + 'TKT_end_date' => $tkt['TKT_end_date'], |
|
| 1214 | + 'TKT_qty' => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'], |
|
| 1215 | + 'TKT_uses' => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'], |
|
| 1216 | + 'TKT_min' => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'], |
|
| 1217 | + 'TKT_max' => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'], |
|
| 1218 | + 'TKT_row' => $row, |
|
| 1219 | + 'TKT_order' => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row, |
|
| 1220 | + 'TKT_price' => $ticket_price, |
|
| 1221 | + ); |
|
| 1222 | + // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well. |
|
| 1223 | + if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) { |
|
| 1224 | + $TKT_values['TKT_ID'] = 0; |
|
| 1225 | + $TKT_values['TKT_is_default'] = 0; |
|
| 1226 | + $TKT_values['TKT_price'] = $ticket_price; |
|
| 1227 | + $update_prices = true; |
|
| 1228 | + } |
|
| 1229 | + // if we have a TKT_ID then we need to get that existing TKT_obj and update it |
|
| 1230 | + // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified. |
|
| 1231 | + // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived. |
|
| 1232 | + if (! empty($tkt['TKT_ID'])) { |
|
| 1233 | + $TKT = EE_Registry::instance() |
|
| 1234 | + ->load_model('Ticket', array($evtobj->get_timezone())) |
|
| 1235 | + ->get_one_by_ID($tkt['TKT_ID']); |
|
| 1236 | + if ($TKT instanceof EE_Ticket) { |
|
| 1237 | + $ticket_sold = $TKT->count_related( |
|
| 1238 | + 'Registration', |
|
| 1239 | + array( |
|
| 1240 | + array( |
|
| 1241 | + 'STS_ID' => array( |
|
| 1242 | + 'NOT IN', |
|
| 1243 | + array(EEM_Registration::status_id_incomplete), |
|
| 1244 | + ), |
|
| 1245 | + ), |
|
| 1246 | + ) |
|
| 1247 | + ) > 0 ? true : false; |
|
| 1248 | + // let's just check the total price for the existing ticket and determine if it matches the new total price. if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket. |
|
| 1249 | + $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price') |
|
| 1250 | + && ! $TKT->get('TKT_deleted'); |
|
| 1251 | + $TKT->set_date_format($incoming_date_formats[0]); |
|
| 1252 | + $TKT->set_time_format($incoming_date_formats[1]); |
|
| 1253 | + // set new values |
|
| 1254 | + foreach ($TKT_values as $field => $value) { |
|
| 1255 | + if ($field == 'TKT_qty') { |
|
| 1256 | + $TKT->set_qty($value); |
|
| 1257 | + } else { |
|
| 1258 | + $TKT->set($field, $value); |
|
| 1259 | + } |
|
| 1260 | + } |
|
| 1261 | + // if $create_new_TKT is false then we can safely update the existing ticket. Otherwise we have to create a new ticket. |
|
| 1262 | + if ($create_new_TKT) { |
|
| 1263 | + // archive the old ticket first |
|
| 1264 | + $TKT->set('TKT_deleted', 1); |
|
| 1265 | + $TKT->save(); |
|
| 1266 | + // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine. |
|
| 1267 | + $saved_tickets[ $TKT->ID() ] = $TKT; |
|
| 1268 | + // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it. |
|
| 1269 | + $TKT = clone $TKT; |
|
| 1270 | + $TKT->set('TKT_ID', 0); |
|
| 1271 | + $TKT->set('TKT_deleted', 0); |
|
| 1272 | + $TKT->set('TKT_price', $ticket_price); |
|
| 1273 | + $TKT->set('TKT_sold', 0); |
|
| 1274 | + // now we need to make sure that $new prices are created as well and attached to new ticket. |
|
| 1275 | + $update_prices = true; |
|
| 1276 | + } |
|
| 1277 | + // make sure price is set if it hasn't been already |
|
| 1278 | + $TKT->set('TKT_price', $ticket_price); |
|
| 1279 | + } |
|
| 1280 | + } else { |
|
| 1281 | + // no TKT_id so a new TKT |
|
| 1282 | + $TKT_values['TKT_price'] = $ticket_price; |
|
| 1283 | + $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false); |
|
| 1284 | + if ($TKT instanceof EE_Ticket) { |
|
| 1285 | + // need to reset values to properly account for the date formats |
|
| 1286 | + $TKT->set_date_format($incoming_date_formats[0]); |
|
| 1287 | + $TKT->set_time_format($incoming_date_formats[1]); |
|
| 1288 | + $TKT->set_timezone($evtobj->get_timezone()); |
|
| 1289 | + // set new values |
|
| 1290 | + foreach ($TKT_values as $field => $value) { |
|
| 1291 | + if ($field == 'TKT_qty') { |
|
| 1292 | + $TKT->set_qty($value); |
|
| 1293 | + } else { |
|
| 1294 | + $TKT->set($field, $value); |
|
| 1295 | + } |
|
| 1296 | + } |
|
| 1297 | + $update_prices = true; |
|
| 1298 | + } |
|
| 1299 | + } |
|
| 1300 | + // cap ticket qty by datetime reg limits |
|
| 1301 | + $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit'))); |
|
| 1302 | + // update ticket. |
|
| 1303 | + $TKT->save(); |
|
| 1304 | + // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date. |
|
| 1305 | + if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) { |
|
| 1306 | + $TKT->set('TKT_end_date', $TKT->get('TKT_start_date')); |
|
| 1307 | + $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days'); |
|
| 1308 | + $TKT->save(); |
|
| 1309 | + } |
|
| 1310 | + // initially let's add the ticket to the dtt |
|
| 1311 | + $saved_dtt->_add_relation_to($TKT, 'Ticket'); |
|
| 1312 | + $saved_tickets[ $TKT->ID() ] = $TKT; |
|
| 1313 | + // add prices to ticket |
|
| 1314 | + $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices); |
|
| 1315 | + } |
|
| 1316 | + // however now we need to handle permanently deleting tickets via the ui. Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold. However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db. |
|
| 1317 | + $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets; |
|
| 1318 | + $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets)); |
|
| 1319 | + foreach ($tickets_removed as $id) { |
|
| 1320 | + $id = absint($id); |
|
| 1321 | + // get the ticket for this id |
|
| 1322 | + $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id); |
|
| 1323 | + // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold) |
|
| 1324 | + $dtts = $tkt_to_remove->get_many_related('Datetime'); |
|
| 1325 | + foreach ($dtts as $dtt) { |
|
| 1326 | + $tkt_to_remove->_remove_relation_to($dtt, 'Datetime'); |
|
| 1327 | + } |
|
| 1328 | + // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived)) |
|
| 1329 | + $tkt_to_remove->delete_related_permanently('Price'); |
|
| 1330 | + // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships) |
|
| 1331 | + $tkt_to_remove->delete_permanently(); |
|
| 1332 | + } |
|
| 1333 | + return array($saved_dtt, $saved_tickets); |
|
| 1334 | + } |
|
| 1335 | + |
|
| 1336 | + |
|
| 1337 | + /** |
|
| 1338 | + * This attaches a list of given prices to a ticket. |
|
| 1339 | + * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change |
|
| 1340 | + * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old |
|
| 1341 | + * price info and prices are automatically "archived" via the ticket. |
|
| 1342 | + * |
|
| 1343 | + * @access private |
|
| 1344 | + * @param array $prices Array of prices from the form. |
|
| 1345 | + * @param EE_Ticket $ticket EE_Ticket object that prices are being attached to. |
|
| 1346 | + * @param bool $new_prices Whether attach existing incoming prices or create new ones. |
|
| 1347 | + * @return void |
|
| 1348 | + */ |
|
| 1349 | + private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false) |
|
| 1350 | + { |
|
| 1351 | + foreach ($prices as $row => $prc) { |
|
| 1352 | + $PRC_values = array( |
|
| 1353 | + 'PRC_ID' => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null, |
|
| 1354 | + 'PRT_ID' => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null, |
|
| 1355 | + 'PRC_amount' => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0, |
|
| 1356 | + 'PRC_name' => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '', |
|
| 1357 | + 'PRC_desc' => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '', |
|
| 1358 | + 'PRC_is_default' => 0, // make sure prices are NOT set as default from this context |
|
| 1359 | + 'PRC_order' => $row, |
|
| 1360 | + ); |
|
| 1361 | + if ($new_prices || empty($PRC_values['PRC_ID'])) { |
|
| 1362 | + $PRC_values['PRC_ID'] = 0; |
|
| 1363 | + $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false); |
|
| 1364 | + } else { |
|
| 1365 | + $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']); |
|
| 1366 | + // update this price with new values |
|
| 1367 | + foreach ($PRC_values as $field => $newprc) { |
|
| 1368 | + $PRC->set($field, $newprc); |
|
| 1369 | + } |
|
| 1370 | + $PRC->save(); |
|
| 1371 | + } |
|
| 1372 | + $ticket->_add_relation_to($PRC, 'Price'); |
|
| 1373 | + } |
|
| 1374 | + } |
|
| 1375 | + |
|
| 1376 | + |
|
| 1377 | + /** |
|
| 1378 | + * Add in our autosave ajax handlers |
|
| 1379 | + * |
|
| 1380 | + */ |
|
| 1381 | + protected function _ee_autosave_create_new() |
|
| 1382 | + { |
|
| 1383 | + } |
|
| 1384 | + |
|
| 1385 | + |
|
| 1386 | + /** |
|
| 1387 | + * More autosave handlers. |
|
| 1388 | + */ |
|
| 1389 | + protected function _ee_autosave_edit() |
|
| 1390 | + { |
|
| 1391 | + return; // TEMPORARILY EXITING CAUSE THIS IS A TODO |
|
| 1392 | + } |
|
| 1393 | + |
|
| 1394 | + |
|
| 1395 | + /** |
|
| 1396 | + * _generate_publish_box_extra_content |
|
| 1397 | + */ |
|
| 1398 | + private function _generate_publish_box_extra_content() |
|
| 1399 | + { |
|
| 1400 | + // load formatter helper |
|
| 1401 | + // args for getting related registrations |
|
| 1402 | + $approved_query_args = array( |
|
| 1403 | + array( |
|
| 1404 | + 'REG_deleted' => 0, |
|
| 1405 | + 'STS_ID' => EEM_Registration::status_id_approved, |
|
| 1406 | + ), |
|
| 1407 | + ); |
|
| 1408 | + $not_approved_query_args = array( |
|
| 1409 | + array( |
|
| 1410 | + 'REG_deleted' => 0, |
|
| 1411 | + 'STS_ID' => EEM_Registration::status_id_not_approved, |
|
| 1412 | + ), |
|
| 1413 | + ); |
|
| 1414 | + $pending_payment_query_args = array( |
|
| 1415 | + array( |
|
| 1416 | + 'REG_deleted' => 0, |
|
| 1417 | + 'STS_ID' => EEM_Registration::status_id_pending_payment, |
|
| 1418 | + ), |
|
| 1419 | + ); |
|
| 1420 | + // publish box |
|
| 1421 | + $publish_box_extra_args = array( |
|
| 1422 | + 'view_approved_reg_url' => add_query_arg( |
|
| 1423 | + array( |
|
| 1424 | + 'action' => 'default', |
|
| 1425 | + 'event_id' => $this->_cpt_model_obj->ID(), |
|
| 1426 | + '_reg_status' => EEM_Registration::status_id_approved, |
|
| 1427 | + ), |
|
| 1428 | + REG_ADMIN_URL |
|
| 1429 | + ), |
|
| 1430 | + 'view_not_approved_reg_url' => add_query_arg( |
|
| 1431 | + array( |
|
| 1432 | + 'action' => 'default', |
|
| 1433 | + 'event_id' => $this->_cpt_model_obj->ID(), |
|
| 1434 | + '_reg_status' => EEM_Registration::status_id_not_approved, |
|
| 1435 | + ), |
|
| 1436 | + REG_ADMIN_URL |
|
| 1437 | + ), |
|
| 1438 | + 'view_pending_payment_reg_url' => add_query_arg( |
|
| 1439 | + array( |
|
| 1440 | + 'action' => 'default', |
|
| 1441 | + 'event_id' => $this->_cpt_model_obj->ID(), |
|
| 1442 | + '_reg_status' => EEM_Registration::status_id_pending_payment, |
|
| 1443 | + ), |
|
| 1444 | + REG_ADMIN_URL |
|
| 1445 | + ), |
|
| 1446 | + 'approved_regs' => $this->_cpt_model_obj->count_related( |
|
| 1447 | + 'Registration', |
|
| 1448 | + $approved_query_args |
|
| 1449 | + ), |
|
| 1450 | + 'not_approved_regs' => $this->_cpt_model_obj->count_related( |
|
| 1451 | + 'Registration', |
|
| 1452 | + $not_approved_query_args |
|
| 1453 | + ), |
|
| 1454 | + 'pending_payment_regs' => $this->_cpt_model_obj->count_related( |
|
| 1455 | + 'Registration', |
|
| 1456 | + $pending_payment_query_args |
|
| 1457 | + ), |
|
| 1458 | + 'misc_pub_section_class' => apply_filters( |
|
| 1459 | + 'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class', |
|
| 1460 | + 'misc-pub-section' |
|
| 1461 | + ), |
|
| 1462 | + ); |
|
| 1463 | + ob_start(); |
|
| 1464 | + do_action( |
|
| 1465 | + 'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add', |
|
| 1466 | + $this->_cpt_model_obj |
|
| 1467 | + ); |
|
| 1468 | + $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean(); |
|
| 1469 | + // load template |
|
| 1470 | + EEH_Template::display_template( |
|
| 1471 | + EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php', |
|
| 1472 | + $publish_box_extra_args |
|
| 1473 | + ); |
|
| 1474 | + } |
|
| 1475 | + |
|
| 1476 | + |
|
| 1477 | + /** |
|
| 1478 | + * @return EE_Event |
|
| 1479 | + */ |
|
| 1480 | + public function get_event_object() |
|
| 1481 | + { |
|
| 1482 | + return $this->_cpt_model_obj; |
|
| 1483 | + } |
|
| 1484 | + |
|
| 1485 | + |
|
| 1486 | + |
|
| 1487 | + |
|
| 1488 | + /** METABOXES * */ |
|
| 1489 | + /** |
|
| 1490 | + * _register_event_editor_meta_boxes |
|
| 1491 | + * add all metaboxes related to the event_editor |
|
| 1492 | + * |
|
| 1493 | + * @return void |
|
| 1494 | + */ |
|
| 1495 | + protected function _register_event_editor_meta_boxes() |
|
| 1496 | + { |
|
| 1497 | + $this->verify_cpt_object(); |
|
| 1498 | + add_meta_box( |
|
| 1499 | + 'espresso_event_editor_tickets', |
|
| 1500 | + esc_html__('Event Datetime & Ticket', 'event_espresso'), |
|
| 1501 | + array($this, 'ticket_metabox'), |
|
| 1502 | + $this->page_slug, |
|
| 1503 | + 'normal', |
|
| 1504 | + 'high' |
|
| 1505 | + ); |
|
| 1506 | + add_meta_box( |
|
| 1507 | + 'espresso_event_editor_event_options', |
|
| 1508 | + esc_html__('Event Registration Options', 'event_espresso'), |
|
| 1509 | + array($this, 'registration_options_meta_box'), |
|
| 1510 | + $this->page_slug, |
|
| 1511 | + 'side', |
|
| 1512 | + 'default' |
|
| 1513 | + ); |
|
| 1514 | + // NOTE: if you're looking for other metaboxes in here, |
|
| 1515 | + // where a metabox has a related management page in the admin |
|
| 1516 | + // you will find it setup in the related management page's "_Hooks" file. |
|
| 1517 | + // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php". |
|
| 1518 | + } |
|
| 1519 | + |
|
| 1520 | + |
|
| 1521 | + /** |
|
| 1522 | + * @throws DomainException |
|
| 1523 | + * @throws EE_Error |
|
| 1524 | + */ |
|
| 1525 | + public function ticket_metabox() |
|
| 1526 | + { |
|
| 1527 | + $existing_datetime_ids = $existing_ticket_ids = array(); |
|
| 1528 | + // defaults for template args |
|
| 1529 | + $template_args = array( |
|
| 1530 | + 'existing_datetime_ids' => '', |
|
| 1531 | + 'event_datetime_help_link' => '', |
|
| 1532 | + 'ticket_options_help_link' => '', |
|
| 1533 | + 'time' => null, |
|
| 1534 | + 'ticket_rows' => '', |
|
| 1535 | + 'existing_ticket_ids' => '', |
|
| 1536 | + 'total_ticket_rows' => 1, |
|
| 1537 | + 'ticket_js_structure' => '', |
|
| 1538 | + 'trash_icon' => 'ee-lock-icon', |
|
| 1539 | + 'disabled' => '', |
|
| 1540 | + ); |
|
| 1541 | + $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null; |
|
| 1542 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 1543 | + /** |
|
| 1544 | + * 1. Start with retrieving Datetimes |
|
| 1545 | + * 2. Fore each datetime get related tickets |
|
| 1546 | + * 3. For each ticket get related prices |
|
| 1547 | + */ |
|
| 1548 | + $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id); |
|
| 1549 | + /** @type EE_Datetime $first_datetime */ |
|
| 1550 | + $first_datetime = reset($times); |
|
| 1551 | + // do we get related tickets? |
|
| 1552 | + if ($first_datetime instanceof EE_Datetime |
|
| 1553 | + && $first_datetime->ID() !== 0 |
|
| 1554 | + ) { |
|
| 1555 | + $existing_datetime_ids[] = $first_datetime->get('DTT_ID'); |
|
| 1556 | + $template_args['time'] = $first_datetime; |
|
| 1557 | + $related_tickets = $first_datetime->tickets( |
|
| 1558 | + array( |
|
| 1559 | + array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)), |
|
| 1560 | + 'default_where_conditions' => 'none', |
|
| 1561 | + ) |
|
| 1562 | + ); |
|
| 1563 | + if (! empty($related_tickets)) { |
|
| 1564 | + $template_args['total_ticket_rows'] = count($related_tickets); |
|
| 1565 | + $row = 0; |
|
| 1566 | + foreach ($related_tickets as $ticket) { |
|
| 1567 | + $existing_ticket_ids[] = $ticket->get('TKT_ID'); |
|
| 1568 | + $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row); |
|
| 1569 | + $row++; |
|
| 1570 | + } |
|
| 1571 | + } else { |
|
| 1572 | + $template_args['total_ticket_rows'] = 1; |
|
| 1573 | + /** @type EE_Ticket $ticket */ |
|
| 1574 | + $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object(); |
|
| 1575 | + $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket); |
|
| 1576 | + } |
|
| 1577 | + } else { |
|
| 1578 | + $template_args['time'] = $times[0]; |
|
| 1579 | + /** @type EE_Ticket $ticket */ |
|
| 1580 | + $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets(); |
|
| 1581 | + $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]); |
|
| 1582 | + // NOTE: we're just sending the first default row |
|
| 1583 | + // (decaf can't manage default tickets so this should be sufficient); |
|
| 1584 | + } |
|
| 1585 | + $template_args['event_datetime_help_link'] = $this->_get_help_tab_link( |
|
| 1586 | + 'event_editor_event_datetimes_help_tab' |
|
| 1587 | + ); |
|
| 1588 | + $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info'); |
|
| 1589 | + $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids); |
|
| 1590 | + $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids); |
|
| 1591 | + $template_args['ticket_js_structure'] = $this->_get_ticket_row( |
|
| 1592 | + EE_Registry::instance()->load_model('Ticket')->create_default_object(), |
|
| 1593 | + true |
|
| 1594 | + ); |
|
| 1595 | + $template = apply_filters( |
|
| 1596 | + 'FHEE__Events_Admin_Page__ticket_metabox__template', |
|
| 1597 | + EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php' |
|
| 1598 | + ); |
|
| 1599 | + EEH_Template::display_template($template, $template_args); |
|
| 1600 | + } |
|
| 1601 | + |
|
| 1602 | + |
|
| 1603 | + /** |
|
| 1604 | + * Setup an individual ticket form for the decaf event editor page |
|
| 1605 | + * |
|
| 1606 | + * @access private |
|
| 1607 | + * @param EE_Ticket $ticket the ticket object |
|
| 1608 | + * @param boolean $skeleton whether we're generating a skeleton for js manipulation |
|
| 1609 | + * @param int $row |
|
| 1610 | + * @return string generated html for the ticket row. |
|
| 1611 | + */ |
|
| 1612 | + private function _get_ticket_row($ticket, $skeleton = false, $row = 0) |
|
| 1613 | + { |
|
| 1614 | + $template_args = array( |
|
| 1615 | + 'tkt_status_class' => ' tkt-status-' . $ticket->ticket_status(), |
|
| 1616 | + 'tkt_archive_class' => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived' |
|
| 1617 | + : '', |
|
| 1618 | + 'ticketrow' => $skeleton ? 'TICKETNUM' : $row, |
|
| 1619 | + 'TKT_ID' => $ticket->get('TKT_ID'), |
|
| 1620 | + 'TKT_name' => $ticket->get('TKT_name'), |
|
| 1621 | + 'TKT_start_date' => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'), |
|
| 1622 | + 'TKT_end_date' => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'), |
|
| 1623 | + 'TKT_is_default' => $ticket->get('TKT_is_default'), |
|
| 1624 | + 'TKT_qty' => $ticket->get_pretty('TKT_qty', 'input'), |
|
| 1625 | + 'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets', |
|
| 1626 | + 'TKT_sold' => $skeleton ? 0 : $ticket->get('TKT_sold'), |
|
| 1627 | + 'trash_icon' => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted'))) |
|
| 1628 | + && (! empty($ticket) && $ticket->get('TKT_sold') === 0) |
|
| 1629 | + ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon', |
|
| 1630 | + 'disabled' => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? '' |
|
| 1631 | + : ' disabled=disabled', |
|
| 1632 | + ); |
|
| 1633 | + $price = $ticket->ID() !== 0 |
|
| 1634 | + ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none')) |
|
| 1635 | + : EE_Registry::instance()->load_model('Price')->create_default_object(); |
|
| 1636 | + $price_args = array( |
|
| 1637 | + 'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign, |
|
| 1638 | + 'PRC_amount' => $price->get('PRC_amount'), |
|
| 1639 | + 'PRT_ID' => $price->get('PRT_ID'), |
|
| 1640 | + 'PRC_ID' => $price->get('PRC_ID'), |
|
| 1641 | + 'PRC_is_default' => $price->get('PRC_is_default'), |
|
| 1642 | + ); |
|
| 1643 | + // make sure we have default start and end dates if skeleton |
|
| 1644 | + // handle rows that should NOT be empty |
|
| 1645 | + if (empty($template_args['TKT_start_date'])) { |
|
| 1646 | + // if empty then the start date will be now. |
|
| 1647 | + $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp')); |
|
| 1648 | + } |
|
| 1649 | + if (empty($template_args['TKT_end_date'])) { |
|
| 1650 | + // get the earliest datetime (if present); |
|
| 1651 | + $earliest_dtt = $this->_cpt_model_obj->ID() > 0 |
|
| 1652 | + ? $this->_cpt_model_obj->get_first_related( |
|
| 1653 | + 'Datetime', |
|
| 1654 | + array('order_by' => array('DTT_EVT_start' => 'ASC')) |
|
| 1655 | + ) |
|
| 1656 | + : null; |
|
| 1657 | + if (! empty($earliest_dtt)) { |
|
| 1658 | + $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a'); |
|
| 1659 | + } else { |
|
| 1660 | + $template_args['TKT_end_date'] = date( |
|
| 1661 | + 'Y-m-d h:i a', |
|
| 1662 | + mktime(0, 0, 0, date("m"), date("d") + 7, date("Y")) |
|
| 1663 | + ); |
|
| 1664 | + } |
|
| 1665 | + } |
|
| 1666 | + $template_args = array_merge($template_args, $price_args); |
|
| 1667 | + $template = apply_filters( |
|
| 1668 | + 'FHEE__Events_Admin_Page__get_ticket_row__template', |
|
| 1669 | + EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php', |
|
| 1670 | + $ticket |
|
| 1671 | + ); |
|
| 1672 | + return EEH_Template::display_template($template, $template_args, true); |
|
| 1673 | + } |
|
| 1674 | + |
|
| 1675 | + |
|
| 1676 | + /** |
|
| 1677 | + * @throws DomainException |
|
| 1678 | + */ |
|
| 1679 | + public function registration_options_meta_box() |
|
| 1680 | + { |
|
| 1681 | + $yes_no_values = array( |
|
| 1682 | + array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')), |
|
| 1683 | + array('id' => false, 'text' => esc_html__('No', 'event_espresso')), |
|
| 1684 | + ); |
|
| 1685 | + $default_reg_status_values = EEM_Registration::reg_status_array( |
|
| 1686 | + array( |
|
| 1687 | + EEM_Registration::status_id_cancelled, |
|
| 1688 | + EEM_Registration::status_id_declined, |
|
| 1689 | + EEM_Registration::status_id_incomplete, |
|
| 1690 | + ), |
|
| 1691 | + true |
|
| 1692 | + ); |
|
| 1693 | + // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active()); |
|
| 1694 | + $template_args['_event'] = $this->_cpt_model_obj; |
|
| 1695 | + $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false); |
|
| 1696 | + $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit(); |
|
| 1697 | + $template_args['default_registration_status'] = EEH_Form_Fields::select_input( |
|
| 1698 | + 'default_reg_status', |
|
| 1699 | + $default_reg_status_values, |
|
| 1700 | + $this->_cpt_model_obj->default_registration_status() |
|
| 1701 | + ); |
|
| 1702 | + $template_args['display_description'] = EEH_Form_Fields::select_input( |
|
| 1703 | + 'display_desc', |
|
| 1704 | + $yes_no_values, |
|
| 1705 | + $this->_cpt_model_obj->display_description() |
|
| 1706 | + ); |
|
| 1707 | + $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input( |
|
| 1708 | + 'display_ticket_selector', |
|
| 1709 | + $yes_no_values, |
|
| 1710 | + $this->_cpt_model_obj->display_ticket_selector(), |
|
| 1711 | + '', |
|
| 1712 | + '', |
|
| 1713 | + false |
|
| 1714 | + ); |
|
| 1715 | + $template_args['additional_registration_options'] = apply_filters( |
|
| 1716 | + 'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options', |
|
| 1717 | + '', |
|
| 1718 | + $template_args, |
|
| 1719 | + $yes_no_values, |
|
| 1720 | + $default_reg_status_values |
|
| 1721 | + ); |
|
| 1722 | + EEH_Template::display_template( |
|
| 1723 | + EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php', |
|
| 1724 | + $template_args |
|
| 1725 | + ); |
|
| 1726 | + } |
|
| 1727 | + |
|
| 1728 | + |
|
| 1729 | + /** |
|
| 1730 | + * _get_events() |
|
| 1731 | + * This method simply returns all the events (for the given _view and paging) |
|
| 1732 | + * |
|
| 1733 | + * @access public |
|
| 1734 | + * @param int $per_page count of items per page (20 default); |
|
| 1735 | + * @param int $current_page what is the current page being viewed. |
|
| 1736 | + * @param bool $count if TRUE then we just return a count of ALL events matching the given _view. |
|
| 1737 | + * If FALSE then we return an array of event objects |
|
| 1738 | + * that match the given _view and paging parameters. |
|
| 1739 | + * @return array an array of event objects. |
|
| 1740 | + */ |
|
| 1741 | + public function get_events($per_page = 10, $current_page = 1, $count = false) |
|
| 1742 | + { |
|
| 1743 | + $EEME = $this->_event_model(); |
|
| 1744 | + $offset = ($current_page - 1) * $per_page; |
|
| 1745 | + $limit = $count ? null : $offset . ',' . $per_page; |
|
| 1746 | + $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID'; |
|
| 1747 | + $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC"; |
|
| 1748 | + if (isset($this->_req_data['month_range'])) { |
|
| 1749 | + $pieces = explode(' ', $this->_req_data['month_range'], 3); |
|
| 1750 | + // simulate the FIRST day of the month, that fixes issues for months like February |
|
| 1751 | + // where PHP doesn't know what to assume for date. |
|
| 1752 | + // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437 |
|
| 1753 | + $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : ''; |
|
| 1754 | + $year_r = ! empty($pieces[1]) ? $pieces[1] : ''; |
|
| 1755 | + } |
|
| 1756 | + $where = array(); |
|
| 1757 | + $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null; |
|
| 1758 | + // determine what post_status our condition will have for the query. |
|
| 1759 | + switch ($status) { |
|
| 1760 | + case 'month': |
|
| 1761 | + case 'today': |
|
| 1762 | + case null: |
|
| 1763 | + case 'all': |
|
| 1764 | + break; |
|
| 1765 | + case 'draft': |
|
| 1766 | + $where['status'] = array('IN', array('draft', 'auto-draft')); |
|
| 1767 | + break; |
|
| 1768 | + default: |
|
| 1769 | + $where['status'] = $status; |
|
| 1770 | + } |
|
| 1771 | + // categories? |
|
| 1772 | + $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0 |
|
| 1773 | + ? $this->_req_data['EVT_CAT'] : null; |
|
| 1774 | + if (! empty($category)) { |
|
| 1775 | + $where['Term_Taxonomy.taxonomy'] = 'espresso_event_categories'; |
|
| 1776 | + $where['Term_Taxonomy.term_id'] = $category; |
|
| 1777 | + } |
|
| 1778 | + // date where conditions |
|
| 1779 | + $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start'); |
|
| 1780 | + if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') { |
|
| 1781 | + $DateTime = new DateTime( |
|
| 1782 | + $year_r . '-' . $month_r . '-01 00:00:00', |
|
| 1783 | + new DateTimeZone(EEM_Datetime::instance()->get_timezone()) |
|
| 1784 | + ); |
|
| 1785 | + $start = $DateTime->format(implode(' ', $start_formats)); |
|
| 1786 | + $end = $DateTime->setDate( |
|
| 1787 | + $year_r, |
|
| 1788 | + $month_r, |
|
| 1789 | + $DateTime |
|
| 1790 | + ->format('t') |
|
| 1791 | + )->setTime(23, 59, 59) |
|
| 1792 | + ->format(implode(' ', $start_formats)); |
|
| 1793 | + $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end)); |
|
| 1794 | + } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') { |
|
| 1795 | + $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone())); |
|
| 1796 | + $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats)); |
|
| 1797 | + $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats)); |
|
| 1798 | + $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end)); |
|
| 1799 | + } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') { |
|
| 1800 | + $now = date('Y-m-01'); |
|
| 1801 | + $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone())); |
|
| 1802 | + $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats)); |
|
| 1803 | + $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t')) |
|
| 1804 | + ->setTime(23, 59, 59) |
|
| 1805 | + ->format(implode(' ', $start_formats)); |
|
| 1806 | + $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end)); |
|
| 1807 | + } |
|
| 1808 | + if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) { |
|
| 1809 | + $where['EVT_wp_user'] = get_current_user_id(); |
|
| 1810 | + } else { |
|
| 1811 | + if (! isset($where['status'])) { |
|
| 1812 | + if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) { |
|
| 1813 | + $where['OR'] = array( |
|
| 1814 | + 'status*restrict_private' => array('!=', 'private'), |
|
| 1815 | + 'AND' => array( |
|
| 1816 | + 'status*inclusive' => array('=', 'private'), |
|
| 1817 | + 'EVT_wp_user' => get_current_user_id(), |
|
| 1818 | + ), |
|
| 1819 | + ); |
|
| 1820 | + } |
|
| 1821 | + } |
|
| 1822 | + } |
|
| 1823 | + if (isset($this->_req_data['EVT_wp_user'])) { |
|
| 1824 | + if ($this->_req_data['EVT_wp_user'] != get_current_user_id() |
|
| 1825 | + && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events') |
|
| 1826 | + ) { |
|
| 1827 | + $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user']; |
|
| 1828 | + } |
|
| 1829 | + } |
|
| 1830 | + // search query handling |
|
| 1831 | + if (isset($this->_req_data['s'])) { |
|
| 1832 | + $search_string = '%' . $this->_req_data['s'] . '%'; |
|
| 1833 | + $where['OR'] = array( |
|
| 1834 | + 'EVT_name' => array('LIKE', $search_string), |
|
| 1835 | + 'EVT_desc' => array('LIKE', $search_string), |
|
| 1836 | + 'EVT_short_desc' => array('LIKE', $search_string), |
|
| 1837 | + ); |
|
| 1838 | + } |
|
| 1839 | + $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data); |
|
| 1840 | + $query_params = apply_filters( |
|
| 1841 | + 'FHEE__Events_Admin_Page__get_events__query_params', |
|
| 1842 | + array( |
|
| 1843 | + $where, |
|
| 1844 | + 'limit' => $limit, |
|
| 1845 | + 'order_by' => $orderby, |
|
| 1846 | + 'order' => $order, |
|
| 1847 | + 'group_by' => 'EVT_ID', |
|
| 1848 | + ), |
|
| 1849 | + $this->_req_data |
|
| 1850 | + ); |
|
| 1851 | + // let's first check if we have special requests coming in. |
|
| 1852 | + if (isset($this->_req_data['active_status'])) { |
|
| 1853 | + switch ($this->_req_data['active_status']) { |
|
| 1854 | + case 'upcoming': |
|
| 1855 | + return $EEME->get_upcoming_events($query_params, $count); |
|
| 1856 | + break; |
|
| 1857 | + case 'expired': |
|
| 1858 | + return $EEME->get_expired_events($query_params, $count); |
|
| 1859 | + break; |
|
| 1860 | + case 'active': |
|
| 1861 | + return $EEME->get_active_events($query_params, $count); |
|
| 1862 | + break; |
|
| 1863 | + case 'inactive': |
|
| 1864 | + return $EEME->get_inactive_events($query_params, $count); |
|
| 1865 | + break; |
|
| 1866 | + } |
|
| 1867 | + } |
|
| 1868 | + $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params); |
|
| 1869 | + return $events; |
|
| 1870 | + } |
|
| 1871 | + |
|
| 1872 | + |
|
| 1873 | + /** |
|
| 1874 | + * handling for WordPress CPT actions (trash, restore, delete) |
|
| 1875 | + * |
|
| 1876 | + * @param string $post_id |
|
| 1877 | + */ |
|
| 1878 | + public function trash_cpt_item($post_id) |
|
| 1879 | + { |
|
| 1880 | + $this->_req_data['EVT_ID'] = $post_id; |
|
| 1881 | + $this->_trash_or_restore_event('trash', false); |
|
| 1882 | + } |
|
| 1883 | + |
|
| 1884 | + |
|
| 1885 | + /** |
|
| 1886 | + * @param string $post_id |
|
| 1887 | + */ |
|
| 1888 | + public function restore_cpt_item($post_id) |
|
| 1889 | + { |
|
| 1890 | + $this->_req_data['EVT_ID'] = $post_id; |
|
| 1891 | + $this->_trash_or_restore_event('draft', false); |
|
| 1892 | + } |
|
| 1893 | + |
|
| 1894 | + |
|
| 1895 | + /** |
|
| 1896 | + * @param string $post_id |
|
| 1897 | + */ |
|
| 1898 | + public function delete_cpt_item($post_id) |
|
| 1899 | + { |
|
| 1900 | + $this->_req_data['EVT_ID'] = $post_id; |
|
| 1901 | + $this->_delete_event(false); |
|
| 1902 | + } |
|
| 1903 | + |
|
| 1904 | + |
|
| 1905 | + /** |
|
| 1906 | + * _trash_or_restore_event |
|
| 1907 | + * |
|
| 1908 | + * @access protected |
|
| 1909 | + * @param string $event_status |
|
| 1910 | + * @param bool $redirect_after |
|
| 1911 | + */ |
|
| 1912 | + protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true) |
|
| 1913 | + { |
|
| 1914 | + // determine the event id and set to array. |
|
| 1915 | + $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false; |
|
| 1916 | + // loop thru events |
|
| 1917 | + if ($EVT_ID) { |
|
| 1918 | + // clean status |
|
| 1919 | + $event_status = sanitize_key($event_status); |
|
| 1920 | + // grab status |
|
| 1921 | + if (! empty($event_status)) { |
|
| 1922 | + $success = $this->_change_event_status($EVT_ID, $event_status); |
|
| 1923 | + } else { |
|
| 1924 | + $success = false; |
|
| 1925 | + $msg = esc_html__( |
|
| 1926 | + 'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.', |
|
| 1927 | + 'event_espresso' |
|
| 1928 | + ); |
|
| 1929 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1930 | + } |
|
| 1931 | + } else { |
|
| 1932 | + $success = false; |
|
| 1933 | + $msg = esc_html__( |
|
| 1934 | + 'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.', |
|
| 1935 | + 'event_espresso' |
|
| 1936 | + ); |
|
| 1937 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1938 | + } |
|
| 1939 | + $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash'; |
|
| 1940 | + if ($redirect_after) { |
|
| 1941 | + $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default')); |
|
| 1942 | + } |
|
| 1943 | + } |
|
| 1944 | + |
|
| 1945 | + |
|
| 1946 | + /** |
|
| 1947 | + * _trash_or_restore_events |
|
| 1948 | + * |
|
| 1949 | + * @access protected |
|
| 1950 | + * @param string $event_status |
|
| 1951 | + * @return void |
|
| 1952 | + */ |
|
| 1953 | + protected function _trash_or_restore_events($event_status = 'trash') |
|
| 1954 | + { |
|
| 1955 | + // clean status |
|
| 1956 | + $event_status = sanitize_key($event_status); |
|
| 1957 | + // grab status |
|
| 1958 | + if (! empty($event_status)) { |
|
| 1959 | + $success = true; |
|
| 1960 | + // determine the event id and set to array. |
|
| 1961 | + $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array(); |
|
| 1962 | + // loop thru events |
|
| 1963 | + foreach ($EVT_IDs as $EVT_ID) { |
|
| 1964 | + if ($EVT_ID = absint($EVT_ID)) { |
|
| 1965 | + $results = $this->_change_event_status($EVT_ID, $event_status); |
|
| 1966 | + $success = $results !== false ? $success : false; |
|
| 1967 | + } else { |
|
| 1968 | + $msg = sprintf( |
|
| 1969 | + esc_html__( |
|
| 1970 | + 'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.', |
|
| 1971 | + 'event_espresso' |
|
| 1972 | + ), |
|
| 1973 | + $EVT_ID |
|
| 1974 | + ); |
|
| 1975 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1976 | + $success = false; |
|
| 1977 | + } |
|
| 1978 | + } |
|
| 1979 | + } else { |
|
| 1980 | + $success = false; |
|
| 1981 | + $msg = esc_html__( |
|
| 1982 | + 'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.', |
|
| 1983 | + 'event_espresso' |
|
| 1984 | + ); |
|
| 1985 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 1986 | + } |
|
| 1987 | + // in order to force a pluralized result message we need to send back a success status greater than 1 |
|
| 1988 | + $success = $success ? 2 : false; |
|
| 1989 | + $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash'; |
|
| 1990 | + $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default')); |
|
| 1991 | + } |
|
| 1992 | + |
|
| 1993 | + |
|
| 1994 | + /** |
|
| 1995 | + * _trash_or_restore_events |
|
| 1996 | + * |
|
| 1997 | + * @access private |
|
| 1998 | + * @param int $EVT_ID |
|
| 1999 | + * @param string $event_status |
|
| 2000 | + * @return bool |
|
| 2001 | + */ |
|
| 2002 | + private function _change_event_status($EVT_ID = 0, $event_status = '') |
|
| 2003 | + { |
|
| 2004 | + // grab event id |
|
| 2005 | + if (! $EVT_ID) { |
|
| 2006 | + $msg = esc_html__( |
|
| 2007 | + 'An error occurred. No Event ID or an invalid Event ID was received.', |
|
| 2008 | + 'event_espresso' |
|
| 2009 | + ); |
|
| 2010 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2011 | + return false; |
|
| 2012 | + } |
|
| 2013 | + $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID); |
|
| 2014 | + // clean status |
|
| 2015 | + $event_status = sanitize_key($event_status); |
|
| 2016 | + // grab status |
|
| 2017 | + if (empty($event_status)) { |
|
| 2018 | + $msg = esc_html__( |
|
| 2019 | + 'An error occurred. No Event Status or an invalid Event Status was received.', |
|
| 2020 | + 'event_espresso' |
|
| 2021 | + ); |
|
| 2022 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2023 | + return false; |
|
| 2024 | + } |
|
| 2025 | + // was event trashed or restored ? |
|
| 2026 | + switch ($event_status) { |
|
| 2027 | + case 'draft': |
|
| 2028 | + $action = 'restored from the trash'; |
|
| 2029 | + $hook = 'AHEE_event_restored_from_trash'; |
|
| 2030 | + break; |
|
| 2031 | + case 'trash': |
|
| 2032 | + $action = 'moved to the trash'; |
|
| 2033 | + $hook = 'AHEE_event_moved_to_trash'; |
|
| 2034 | + break; |
|
| 2035 | + default: |
|
| 2036 | + $action = 'updated'; |
|
| 2037 | + $hook = false; |
|
| 2038 | + } |
|
| 2039 | + // use class to change status |
|
| 2040 | + $this->_cpt_model_obj->set_status($event_status); |
|
| 2041 | + $success = $this->_cpt_model_obj->save(); |
|
| 2042 | + if ($success === false) { |
|
| 2043 | + $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action); |
|
| 2044 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2045 | + return false; |
|
| 2046 | + } |
|
| 2047 | + if ($hook) { |
|
| 2048 | + do_action($hook); |
|
| 2049 | + } |
|
| 2050 | + return true; |
|
| 2051 | + } |
|
| 2052 | + |
|
| 2053 | + |
|
| 2054 | + /** |
|
| 2055 | + * _delete_event |
|
| 2056 | + * |
|
| 2057 | + * @access protected |
|
| 2058 | + * @param bool $redirect_after |
|
| 2059 | + */ |
|
| 2060 | + protected function _delete_event($redirect_after = true) |
|
| 2061 | + { |
|
| 2062 | + // determine the event id and set to array. |
|
| 2063 | + $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null; |
|
| 2064 | + $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID; |
|
| 2065 | + // loop thru events |
|
| 2066 | + if ($EVT_ID) { |
|
| 2067 | + $success = $this->_permanently_delete_event($EVT_ID); |
|
| 2068 | + // get list of events with no prices |
|
| 2069 | + $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array()); |
|
| 2070 | + // remove this event from the list of events with no prices |
|
| 2071 | + if (isset($espresso_no_ticket_prices[ $EVT_ID ])) { |
|
| 2072 | + unset($espresso_no_ticket_prices[ $EVT_ID ]); |
|
| 2073 | + } |
|
| 2074 | + update_option('ee_no_ticket_prices', $espresso_no_ticket_prices); |
|
| 2075 | + } else { |
|
| 2076 | + $success = false; |
|
| 2077 | + $msg = esc_html__( |
|
| 2078 | + 'An error occurred. An event could not be deleted because a valid event ID was not not supplied.', |
|
| 2079 | + 'event_espresso' |
|
| 2080 | + ); |
|
| 2081 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2082 | + } |
|
| 2083 | + if ($redirect_after) { |
|
| 2084 | + $this->_redirect_after_action( |
|
| 2085 | + $success, |
|
| 2086 | + 'Event', |
|
| 2087 | + 'deleted', |
|
| 2088 | + array('action' => 'default', 'status' => 'trash') |
|
| 2089 | + ); |
|
| 2090 | + } |
|
| 2091 | + } |
|
| 2092 | + |
|
| 2093 | + |
|
| 2094 | + /** |
|
| 2095 | + * _delete_events |
|
| 2096 | + * |
|
| 2097 | + * @access protected |
|
| 2098 | + * @return void |
|
| 2099 | + */ |
|
| 2100 | + protected function _delete_events() |
|
| 2101 | + { |
|
| 2102 | + $success = true; |
|
| 2103 | + // get list of events with no prices |
|
| 2104 | + $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array()); |
|
| 2105 | + // determine the event id and set to array. |
|
| 2106 | + $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array(); |
|
| 2107 | + // loop thru events |
|
| 2108 | + foreach ($EVT_IDs as $EVT_ID) { |
|
| 2109 | + $EVT_ID = absint($EVT_ID); |
|
| 2110 | + if ($EVT_ID) { |
|
| 2111 | + $results = $this->_permanently_delete_event($EVT_ID); |
|
| 2112 | + $success = $results !== false ? $success : false; |
|
| 2113 | + // remove this event from the list of events with no prices |
|
| 2114 | + unset($espresso_no_ticket_prices[ $EVT_ID ]); |
|
| 2115 | + } else { |
|
| 2116 | + $success = false; |
|
| 2117 | + $msg = esc_html__( |
|
| 2118 | + 'An error occurred. An event could not be deleted because a valid event ID was not not supplied.', |
|
| 2119 | + 'event_espresso' |
|
| 2120 | + ); |
|
| 2121 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2122 | + } |
|
| 2123 | + } |
|
| 2124 | + update_option('ee_no_ticket_prices', $espresso_no_ticket_prices); |
|
| 2125 | + // in order to force a pluralized result message we need to send back a success status greater than 1 |
|
| 2126 | + $success = $success ? 2 : false; |
|
| 2127 | + $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default')); |
|
| 2128 | + } |
|
| 2129 | + |
|
| 2130 | + |
|
| 2131 | + /** |
|
| 2132 | + * _permanently_delete_event |
|
| 2133 | + * |
|
| 2134 | + * @access private |
|
| 2135 | + * @param int $EVT_ID |
|
| 2136 | + * @return bool |
|
| 2137 | + */ |
|
| 2138 | + private function _permanently_delete_event($EVT_ID = 0) |
|
| 2139 | + { |
|
| 2140 | + // grab event id |
|
| 2141 | + if (! $EVT_ID) { |
|
| 2142 | + $msg = esc_html__( |
|
| 2143 | + 'An error occurred. No Event ID or an invalid Event ID was received.', |
|
| 2144 | + 'event_espresso' |
|
| 2145 | + ); |
|
| 2146 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2147 | + return false; |
|
| 2148 | + } |
|
| 2149 | + if (! $this->_cpt_model_obj instanceof EE_Event |
|
| 2150 | + || $this->_cpt_model_obj->ID() !== $EVT_ID |
|
| 2151 | + ) { |
|
| 2152 | + $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID); |
|
| 2153 | + } |
|
| 2154 | + if (! $this->_cpt_model_obj instanceof EE_Event) { |
|
| 2155 | + return false; |
|
| 2156 | + } |
|
| 2157 | + // need to delete related tickets and prices first. |
|
| 2158 | + $datetimes = $this->_cpt_model_obj->get_many_related('Datetime'); |
|
| 2159 | + foreach ($datetimes as $datetime) { |
|
| 2160 | + $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime'); |
|
| 2161 | + $tickets = $datetime->get_many_related('Ticket'); |
|
| 2162 | + foreach ($tickets as $ticket) { |
|
| 2163 | + $ticket->_remove_relation_to($datetime, 'Datetime'); |
|
| 2164 | + $ticket->delete_related_permanently('Price'); |
|
| 2165 | + $ticket->delete_permanently(); |
|
| 2166 | + } |
|
| 2167 | + $datetime->delete(); |
|
| 2168 | + } |
|
| 2169 | + // what about related venues or terms? |
|
| 2170 | + $venues = $this->_cpt_model_obj->get_many_related('Venue'); |
|
| 2171 | + foreach ($venues as $venue) { |
|
| 2172 | + $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue'); |
|
| 2173 | + } |
|
| 2174 | + // any attached question groups? |
|
| 2175 | + $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group'); |
|
| 2176 | + if (! empty($question_groups)) { |
|
| 2177 | + foreach ($question_groups as $question_group) { |
|
| 2178 | + $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group'); |
|
| 2179 | + } |
|
| 2180 | + } |
|
| 2181 | + // Message Template Groups |
|
| 2182 | + $this->_cpt_model_obj->_remove_relations('Message_Template_Group'); |
|
| 2183 | + /** @type EE_Term_Taxonomy[] $term_taxonomies */ |
|
| 2184 | + $term_taxonomies = $this->_cpt_model_obj->term_taxonomies(); |
|
| 2185 | + foreach ($term_taxonomies as $term_taxonomy) { |
|
| 2186 | + $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy); |
|
| 2187 | + } |
|
| 2188 | + $success = $this->_cpt_model_obj->delete_permanently(); |
|
| 2189 | + // did it all go as planned ? |
|
| 2190 | + if ($success) { |
|
| 2191 | + $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID); |
|
| 2192 | + EE_Error::add_success($msg); |
|
| 2193 | + } else { |
|
| 2194 | + $msg = sprintf( |
|
| 2195 | + esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'), |
|
| 2196 | + $EVT_ID |
|
| 2197 | + ); |
|
| 2198 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2199 | + return false; |
|
| 2200 | + } |
|
| 2201 | + do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID); |
|
| 2202 | + return true; |
|
| 2203 | + } |
|
| 2204 | + |
|
| 2205 | + |
|
| 2206 | + /** |
|
| 2207 | + * get total number of events |
|
| 2208 | + * |
|
| 2209 | + * @access public |
|
| 2210 | + * @return int |
|
| 2211 | + */ |
|
| 2212 | + public function total_events() |
|
| 2213 | + { |
|
| 2214 | + $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true); |
|
| 2215 | + return $count; |
|
| 2216 | + } |
|
| 2217 | + |
|
| 2218 | + |
|
| 2219 | + /** |
|
| 2220 | + * get total number of draft events |
|
| 2221 | + * |
|
| 2222 | + * @access public |
|
| 2223 | + * @return int |
|
| 2224 | + */ |
|
| 2225 | + public function total_events_draft() |
|
| 2226 | + { |
|
| 2227 | + $where = array( |
|
| 2228 | + 'status' => array('IN', array('draft', 'auto-draft')), |
|
| 2229 | + ); |
|
| 2230 | + $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true); |
|
| 2231 | + return $count; |
|
| 2232 | + } |
|
| 2233 | + |
|
| 2234 | + |
|
| 2235 | + /** |
|
| 2236 | + * get total number of trashed events |
|
| 2237 | + * |
|
| 2238 | + * @access public |
|
| 2239 | + * @return int |
|
| 2240 | + */ |
|
| 2241 | + public function total_trashed_events() |
|
| 2242 | + { |
|
| 2243 | + $where = array( |
|
| 2244 | + 'status' => 'trash', |
|
| 2245 | + ); |
|
| 2246 | + $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true); |
|
| 2247 | + return $count; |
|
| 2248 | + } |
|
| 2249 | + |
|
| 2250 | + |
|
| 2251 | + /** |
|
| 2252 | + * _default_event_settings |
|
| 2253 | + * This generates the Default Settings Tab |
|
| 2254 | + * |
|
| 2255 | + * @return void |
|
| 2256 | + * @throws EE_Error |
|
| 2257 | + */ |
|
| 2258 | + protected function _default_event_settings() |
|
| 2259 | + { |
|
| 2260 | + $this->_set_add_edit_form_tags('update_default_event_settings'); |
|
| 2261 | + $this->_set_publish_post_box_vars(null, false, false, null, false); |
|
| 2262 | + $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html(); |
|
| 2263 | + $this->display_admin_page_with_sidebar(); |
|
| 2264 | + } |
|
| 2265 | + |
|
| 2266 | + |
|
| 2267 | + /** |
|
| 2268 | + * Return the form for event settings. |
|
| 2269 | + * |
|
| 2270 | + * @return EE_Form_Section_Proper |
|
| 2271 | + * @throws EE_Error |
|
| 2272 | + */ |
|
| 2273 | + protected function _default_event_settings_form() |
|
| 2274 | + { |
|
| 2275 | + $registration_config = EE_Registry::instance()->CFG->registration; |
|
| 2276 | + $registration_stati_for_selection = EEM_Registration::reg_status_array( |
|
| 2277 | + // exclude |
|
| 2278 | + array( |
|
| 2279 | + EEM_Registration::status_id_cancelled, |
|
| 2280 | + EEM_Registration::status_id_declined, |
|
| 2281 | + EEM_Registration::status_id_incomplete, |
|
| 2282 | + EEM_Registration::status_id_wait_list, |
|
| 2283 | + ), |
|
| 2284 | + true |
|
| 2285 | + ); |
|
| 2286 | + return new EE_Form_Section_Proper( |
|
| 2287 | + array( |
|
| 2288 | + 'name' => 'update_default_event_settings', |
|
| 2289 | + 'html_id' => 'update_default_event_settings', |
|
| 2290 | + 'html_class' => 'form-table', |
|
| 2291 | + 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
| 2292 | + 'subsections' => apply_filters( |
|
| 2293 | + 'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections', |
|
| 2294 | + array( |
|
| 2295 | + 'default_reg_status' => new EE_Select_Input( |
|
| 2296 | + $registration_stati_for_selection, |
|
| 2297 | + array( |
|
| 2298 | + 'default' => isset($registration_config->default_STS_ID) |
|
| 2299 | + && array_key_exists( |
|
| 2300 | + $registration_config->default_STS_ID, |
|
| 2301 | + $registration_stati_for_selection |
|
| 2302 | + ) |
|
| 2303 | + ? sanitize_text_field($registration_config->default_STS_ID) |
|
| 2304 | + : EEM_Registration::status_id_pending_payment, |
|
| 2305 | + 'html_label_text' => esc_html__('Default Registration Status', 'event_espresso') |
|
| 2306 | + . EEH_Template::get_help_tab_link( |
|
| 2307 | + 'default_settings_status_help_tab' |
|
| 2308 | + ), |
|
| 2309 | + 'html_help_text' => esc_html__( |
|
| 2310 | + 'This setting allows you to preselect what the default registration status setting is when creating an event. Note that changing this setting does NOT retroactively apply it to existing events.', |
|
| 2311 | + 'event_espresso' |
|
| 2312 | + ), |
|
| 2313 | + ) |
|
| 2314 | + ), |
|
| 2315 | + 'default_max_tickets' => new EE_Integer_Input( |
|
| 2316 | + array( |
|
| 2317 | + 'default' => isset($registration_config->default_maximum_number_of_tickets) |
|
| 2318 | + ? $registration_config->default_maximum_number_of_tickets |
|
| 2319 | + : EEM_Event::get_default_additional_limit(), |
|
| 2320 | + 'html_label_text' => esc_html__( |
|
| 2321 | + 'Default Maximum Tickets Allowed Per Order:', |
|
| 2322 | + 'event_espresso' |
|
| 2323 | + ) |
|
| 2324 | + . EEH_Template::get_help_tab_link( |
|
| 2325 | + 'default_maximum_tickets_help_tab"' |
|
| 2326 | + ), |
|
| 2327 | + 'html_help_text' => esc_html__( |
|
| 2328 | + 'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.', |
|
| 2329 | + 'event_espresso' |
|
| 2330 | + ), |
|
| 2331 | + ) |
|
| 2332 | + ), |
|
| 2333 | + ) |
|
| 2334 | + ), |
|
| 2335 | + ) |
|
| 2336 | + ); |
|
| 2337 | + } |
|
| 2338 | + |
|
| 2339 | + |
|
| 2340 | + /** |
|
| 2341 | + * _update_default_event_settings |
|
| 2342 | + * |
|
| 2343 | + * @access protected |
|
| 2344 | + * @return void |
|
| 2345 | + * @throws EE_Error |
|
| 2346 | + */ |
|
| 2347 | + protected function _update_default_event_settings() |
|
| 2348 | + { |
|
| 2349 | + $registration_config = EE_Registry::instance()->CFG->registration; |
|
| 2350 | + $form = $this->_default_event_settings_form(); |
|
| 2351 | + if ($form->was_submitted()) { |
|
| 2352 | + $form->receive_form_submission(); |
|
| 2353 | + if ($form->is_valid()) { |
|
| 2354 | + $valid_data = $form->valid_data(); |
|
| 2355 | + if (isset($valid_data['default_reg_status'])) { |
|
| 2356 | + $registration_config->default_STS_ID = $valid_data['default_reg_status']; |
|
| 2357 | + } |
|
| 2358 | + if (isset($valid_data['default_max_tickets'])) { |
|
| 2359 | + $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets']; |
|
| 2360 | + } |
|
| 2361 | + // update because data was valid! |
|
| 2362 | + EE_Registry::instance()->CFG->update_espresso_config(); |
|
| 2363 | + EE_Error::overwrite_success(); |
|
| 2364 | + EE_Error::add_success( |
|
| 2365 | + __('Default Event Settings were updated', 'event_espresso') |
|
| 2366 | + ); |
|
| 2367 | + } |
|
| 2368 | + } |
|
| 2369 | + $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true); |
|
| 2370 | + } |
|
| 2371 | + |
|
| 2372 | + |
|
| 2373 | + /************* Templates *************/ |
|
| 2374 | + protected function _template_settings() |
|
| 2375 | + { |
|
| 2376 | + $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso'); |
|
| 2377 | + $this->_template_args['preview_img'] = '<img src="' |
|
| 2378 | + . EVENTS_ASSETS_URL |
|
| 2379 | + . DS |
|
| 2380 | + . 'images' |
|
| 2381 | + . DS |
|
| 2382 | + . 'caffeinated_template_features.jpg" alt="' |
|
| 2383 | + . esc_attr__('Template Settings Preview screenshot', 'event_espresso') |
|
| 2384 | + . '" />'; |
|
| 2385 | + $this->_template_args['preview_text'] = '<strong>' |
|
| 2386 | + . esc_html__( |
|
| 2387 | + 'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.', |
|
| 2388 | + 'event_espresso' |
|
| 2389 | + ) . '</strong>'; |
|
| 2390 | + $this->display_admin_caf_preview_page('template_settings_tab'); |
|
| 2391 | + } |
|
| 2392 | + |
|
| 2393 | + |
|
| 2394 | + /** Event Category Stuff **/ |
|
| 2395 | + /** |
|
| 2396 | + * set the _category property with the category object for the loaded page. |
|
| 2397 | + * |
|
| 2398 | + * @access private |
|
| 2399 | + * @return void |
|
| 2400 | + */ |
|
| 2401 | + private function _set_category_object() |
|
| 2402 | + { |
|
| 2403 | + if (isset($this->_category->id) && ! empty($this->_category->id)) { |
|
| 2404 | + return; |
|
| 2405 | + } //already have the category object so get out. |
|
| 2406 | + // set default category object |
|
| 2407 | + $this->_set_empty_category_object(); |
|
| 2408 | + // only set if we've got an id |
|
| 2409 | + if (! isset($this->_req_data['EVT_CAT_ID'])) { |
|
| 2410 | + return; |
|
| 2411 | + } |
|
| 2412 | + $category_id = absint($this->_req_data['EVT_CAT_ID']); |
|
| 2413 | + $term = get_term($category_id, 'espresso_event_categories'); |
|
| 2414 | + if (! empty($term)) { |
|
| 2415 | + $this->_category->category_name = $term->name; |
|
| 2416 | + $this->_category->category_identifier = $term->slug; |
|
| 2417 | + $this->_category->category_desc = $term->description; |
|
| 2418 | + $this->_category->id = $term->term_id; |
|
| 2419 | + $this->_category->parent = $term->parent; |
|
| 2420 | + } |
|
| 2421 | + } |
|
| 2422 | + |
|
| 2423 | + |
|
| 2424 | + /** |
|
| 2425 | + * Clears out category properties. |
|
| 2426 | + */ |
|
| 2427 | + private function _set_empty_category_object() |
|
| 2428 | + { |
|
| 2429 | + $this->_category = new stdClass(); |
|
| 2430 | + $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = ''; |
|
| 2431 | + $this->_category->id = $this->_category->parent = 0; |
|
| 2432 | + } |
|
| 2433 | + |
|
| 2434 | + |
|
| 2435 | + /** |
|
| 2436 | + * @throws EE_Error |
|
| 2437 | + */ |
|
| 2438 | + protected function _category_list_table() |
|
| 2439 | + { |
|
| 2440 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
| 2441 | + $this->_search_btn_label = esc_html__('Categories', 'event_espresso'); |
|
| 2442 | + $this->_admin_page_title .= ' ' . $this->get_action_link_or_button( |
|
| 2443 | + 'add_category', |
|
| 2444 | + 'add_category', |
|
| 2445 | + array(), |
|
| 2446 | + 'add-new-h2' |
|
| 2447 | + ); |
|
| 2448 | + $this->display_admin_list_table_page_with_sidebar(); |
|
| 2449 | + } |
|
| 2450 | + |
|
| 2451 | + |
|
| 2452 | + /** |
|
| 2453 | + * Output category details view. |
|
| 2454 | + */ |
|
| 2455 | + protected function _category_details($view) |
|
| 2456 | + { |
|
| 2457 | + // load formatter helper |
|
| 2458 | + // load field generator helper |
|
| 2459 | + $route = $view == 'edit' ? 'update_category' : 'insert_category'; |
|
| 2460 | + $this->_set_add_edit_form_tags($route); |
|
| 2461 | + $this->_set_category_object(); |
|
| 2462 | + $id = ! empty($this->_category->id) ? $this->_category->id : ''; |
|
| 2463 | + $delete_action = 'delete_category'; |
|
| 2464 | + // custom redirect |
|
| 2465 | + $redirect = EE_Admin_Page::add_query_args_and_nonce( |
|
| 2466 | + array('action' => 'category_list'), |
|
| 2467 | + $this->_admin_base_url |
|
| 2468 | + ); |
|
| 2469 | + $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect); |
|
| 2470 | + // take care of contents |
|
| 2471 | + $this->_template_args['admin_page_content'] = $this->_category_details_content(); |
|
| 2472 | + $this->display_admin_page_with_sidebar(); |
|
| 2473 | + } |
|
| 2474 | + |
|
| 2475 | + |
|
| 2476 | + /** |
|
| 2477 | + * Output category details content. |
|
| 2478 | + */ |
|
| 2479 | + protected function _category_details_content() |
|
| 2480 | + { |
|
| 2481 | + $editor_args['category_desc'] = array( |
|
| 2482 | + 'type' => 'wp_editor', |
|
| 2483 | + 'value' => EEH_Formatter::admin_format_content($this->_category->category_desc), |
|
| 2484 | + 'class' => 'my_editor_custom', |
|
| 2485 | + 'wpeditor_args' => array('media_buttons' => false), |
|
| 2486 | + ); |
|
| 2487 | + $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array'); |
|
| 2488 | + $all_terms = get_terms( |
|
| 2489 | + array('espresso_event_categories'), |
|
| 2490 | + array('hide_empty' => 0, 'exclude' => array($this->_category->id)) |
|
| 2491 | + ); |
|
| 2492 | + // setup category select for term parents. |
|
| 2493 | + $category_select_values[] = array( |
|
| 2494 | + 'text' => esc_html__('No Parent', 'event_espresso'), |
|
| 2495 | + 'id' => 0, |
|
| 2496 | + ); |
|
| 2497 | + foreach ($all_terms as $term) { |
|
| 2498 | + $category_select_values[] = array( |
|
| 2499 | + 'text' => $term->name, |
|
| 2500 | + 'id' => $term->term_id, |
|
| 2501 | + ); |
|
| 2502 | + } |
|
| 2503 | + $category_select = EEH_Form_Fields::select_input( |
|
| 2504 | + 'category_parent', |
|
| 2505 | + $category_select_values, |
|
| 2506 | + $this->_category->parent |
|
| 2507 | + ); |
|
| 2508 | + $template_args = array( |
|
| 2509 | + 'category' => $this->_category, |
|
| 2510 | + 'category_select' => $category_select, |
|
| 2511 | + 'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'), |
|
| 2512 | + 'category_desc_editor' => $_wp_editor['category_desc']['field'], |
|
| 2513 | + 'disable' => '', |
|
| 2514 | + 'disabled_message' => false, |
|
| 2515 | + ); |
|
| 2516 | + $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php'; |
|
| 2517 | + return EEH_Template::display_template($template, $template_args, true); |
|
| 2518 | + } |
|
| 2519 | + |
|
| 2520 | + |
|
| 2521 | + /** |
|
| 2522 | + * Handles deleting categories. |
|
| 2523 | + */ |
|
| 2524 | + protected function _delete_categories() |
|
| 2525 | + { |
|
| 2526 | + $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID'] |
|
| 2527 | + : (array) $this->_req_data['category_id']; |
|
| 2528 | + foreach ($cat_ids as $cat_id) { |
|
| 2529 | + $this->_delete_category($cat_id); |
|
| 2530 | + } |
|
| 2531 | + // doesn't matter what page we're coming from... we're going to the same place after delete. |
|
| 2532 | + $query_args = array( |
|
| 2533 | + 'action' => 'category_list', |
|
| 2534 | + ); |
|
| 2535 | + $this->_redirect_after_action(0, '', '', $query_args); |
|
| 2536 | + } |
|
| 2537 | + |
|
| 2538 | + |
|
| 2539 | + /** |
|
| 2540 | + * Handles deleting specific category. |
|
| 2541 | + * |
|
| 2542 | + * @param int $cat_id |
|
| 2543 | + */ |
|
| 2544 | + protected function _delete_category($cat_id) |
|
| 2545 | + { |
|
| 2546 | + $cat_id = absint($cat_id); |
|
| 2547 | + wp_delete_term($cat_id, 'espresso_event_categories'); |
|
| 2548 | + } |
|
| 2549 | + |
|
| 2550 | + |
|
| 2551 | + /** |
|
| 2552 | + * Handles triggering the update or insertion of a new category. |
|
| 2553 | + * |
|
| 2554 | + * @param bool $new_category true means we're triggering the insert of a new category. |
|
| 2555 | + */ |
|
| 2556 | + protected function _insert_or_update_category($new_category) |
|
| 2557 | + { |
|
| 2558 | + $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true); |
|
| 2559 | + $success = 0; // we already have a success message so lets not send another. |
|
| 2560 | + if ($cat_id) { |
|
| 2561 | + $query_args = array( |
|
| 2562 | + 'action' => 'edit_category', |
|
| 2563 | + 'EVT_CAT_ID' => $cat_id, |
|
| 2564 | + ); |
|
| 2565 | + } else { |
|
| 2566 | + $query_args = array('action' => 'add_category'); |
|
| 2567 | + } |
|
| 2568 | + $this->_redirect_after_action($success, '', '', $query_args, true); |
|
| 2569 | + } |
|
| 2570 | + |
|
| 2571 | + |
|
| 2572 | + /** |
|
| 2573 | + * Inserts or updates category |
|
| 2574 | + * |
|
| 2575 | + * @param bool $update (true indicates we're updating a category). |
|
| 2576 | + * @return bool|mixed|string |
|
| 2577 | + */ |
|
| 2578 | + private function _insert_category($update = false) |
|
| 2579 | + { |
|
| 2580 | + $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : ''; |
|
| 2581 | + $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : ''; |
|
| 2582 | + $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : ''; |
|
| 2583 | + $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0; |
|
| 2584 | + if (empty($category_name)) { |
|
| 2585 | + $msg = esc_html__('You must add a name for the category.', 'event_espresso'); |
|
| 2586 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2587 | + return false; |
|
| 2588 | + } |
|
| 2589 | + $term_args = array( |
|
| 2590 | + 'name' => $category_name, |
|
| 2591 | + 'description' => $category_desc, |
|
| 2592 | + 'parent' => $category_parent, |
|
| 2593 | + ); |
|
| 2594 | + // was the category_identifier input disabled? |
|
| 2595 | + if (isset($this->_req_data['category_identifier'])) { |
|
| 2596 | + $term_args['slug'] = $this->_req_data['category_identifier']; |
|
| 2597 | + } |
|
| 2598 | + $insert_ids = $update |
|
| 2599 | + ? wp_update_term($cat_id, 'espresso_event_categories', $term_args) |
|
| 2600 | + : wp_insert_term($category_name, 'espresso_event_categories', $term_args); |
|
| 2601 | + if (! is_array($insert_ids)) { |
|
| 2602 | + $msg = esc_html__( |
|
| 2603 | + 'An error occurred and the category has not been saved to the database.', |
|
| 2604 | + 'event_espresso' |
|
| 2605 | + ); |
|
| 2606 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 2607 | + } else { |
|
| 2608 | + $cat_id = $insert_ids['term_id']; |
|
| 2609 | + $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name); |
|
| 2610 | + EE_Error::add_success($msg); |
|
| 2611 | + } |
|
| 2612 | + return $cat_id; |
|
| 2613 | + } |
|
| 2614 | + |
|
| 2615 | + |
|
| 2616 | + /** |
|
| 2617 | + * Gets categories or count of categories matching the arguments in the request. |
|
| 2618 | + * |
|
| 2619 | + * @param int $per_page |
|
| 2620 | + * @param int $current_page |
|
| 2621 | + * @param bool $count |
|
| 2622 | + * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int |
|
| 2623 | + */ |
|
| 2624 | + public function get_categories($per_page = 10, $current_page = 1, $count = false) |
|
| 2625 | + { |
|
| 2626 | + // testing term stuff |
|
| 2627 | + $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id'; |
|
| 2628 | + $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC'; |
|
| 2629 | + $limit = ($current_page - 1) * $per_page; |
|
| 2630 | + $where = array('taxonomy' => 'espresso_event_categories'); |
|
| 2631 | + if (isset($this->_req_data['s'])) { |
|
| 2632 | + $sstr = '%' . $this->_req_data['s'] . '%'; |
|
| 2633 | + $where['OR'] = array( |
|
| 2634 | + 'Term.name' => array('LIKE', $sstr), |
|
| 2635 | + 'description' => array('LIKE', $sstr), |
|
| 2636 | + ); |
|
| 2637 | + } |
|
| 2638 | + $query_params = array( |
|
| 2639 | + $where, |
|
| 2640 | + 'order_by' => array($orderby => $order), |
|
| 2641 | + 'limit' => $limit . ',' . $per_page, |
|
| 2642 | + 'force_join' => array('Term'), |
|
| 2643 | + ); |
|
| 2644 | + $categories = $count |
|
| 2645 | + ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id') |
|
| 2646 | + : EEM_Term_Taxonomy::instance()->get_all($query_params); |
|
| 2647 | + return $categories; |
|
| 2648 | + } |
|
| 2649 | + |
|
| 2650 | + /* end category stuff */ |
|
| 2651 | + /**************/ |
|
| 2652 | + |
|
| 2653 | + |
|
| 2654 | + /** |
|
| 2655 | + * Callback for the `ee_save_timezone_setting` ajax action. |
|
| 2656 | + * |
|
| 2657 | + * @throws EE_Error |
|
| 2658 | + */ |
|
| 2659 | + public function save_timezonestring_setting() |
|
| 2660 | + { |
|
| 2661 | + $timezone_string = isset($this->_req_data['timezone_selected']) |
|
| 2662 | + ? $this->_req_data['timezone_selected'] |
|
| 2663 | + : ''; |
|
| 2664 | + if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) { |
|
| 2665 | + EE_Error::add_error( |
|
| 2666 | + esc_html('An invalid timezone string submitted.', 'event_espresso'), |
|
| 2667 | + __FILE__, |
|
| 2668 | + __FUNCTION__, |
|
| 2669 | + __LINE__ |
|
| 2670 | + ); |
|
| 2671 | + $this->_template_args['error'] = true; |
|
| 2672 | + $this->_return_json(); |
|
| 2673 | + } |
|
| 2674 | + |
|
| 2675 | + update_option('timezone_string', $timezone_string); |
|
| 2676 | + EE_Error::add_success( |
|
| 2677 | + esc_html__('Your timezone string was updated.', 'event_espresso') |
|
| 2678 | + ); |
|
| 2679 | + $this->_template_args['success'] = true; |
|
| 2680 | + $this->_return_json(true, array('action' => 'create_new')); |
|
| 2681 | + } |
|
| 2682 | 2682 | } |