@@ -16,781 +16,781 @@ |
||
| 16 | 16 | class EE_Export |
| 17 | 17 | { |
| 18 | 18 | |
| 19 | - const option_prefix = 'ee_report_job_'; |
|
| 20 | - |
|
| 21 | - |
|
| 22 | - // instance of the EE_Export object |
|
| 23 | - private static $_instance; |
|
| 24 | - |
|
| 25 | - // instance of the EE_CSV object |
|
| 26 | - /** |
|
| 27 | - * |
|
| 28 | - * @var EE_CSV |
|
| 29 | - */ |
|
| 30 | - public $EE_CSV = null; |
|
| 31 | - |
|
| 32 | - |
|
| 33 | - private $_req_data = array(); |
|
| 34 | - |
|
| 35 | - |
|
| 36 | - /** |
|
| 37 | - * private constructor to prevent direct creation |
|
| 38 | - * |
|
| 39 | - * @Constructor |
|
| 40 | - * @access private |
|
| 41 | - * @param array $request_data |
|
| 42 | - */ |
|
| 43 | - private function __construct($request_data = array()) |
|
| 44 | - { |
|
| 45 | - $this->_req_data = $request_data; |
|
| 46 | - $this->today = date("Y-m-d", time()); |
|
| 47 | - require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
| 48 | - $this->EE_CSV = EE_CSV::instance(); |
|
| 49 | - } |
|
| 50 | - |
|
| 51 | - |
|
| 52 | - /** |
|
| 53 | - * @ singleton method used to instantiate class object |
|
| 54 | - * @ access public |
|
| 55 | - * |
|
| 56 | - * @param array $request_data |
|
| 57 | - * @return \EE_Export |
|
| 58 | - */ |
|
| 59 | - public static function instance($request_data = array()) |
|
| 60 | - { |
|
| 61 | - // check if class object is instantiated |
|
| 62 | - if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Export)) { |
|
| 63 | - self::$_instance = new self($request_data); |
|
| 64 | - } |
|
| 65 | - return self::$_instance; |
|
| 66 | - } |
|
| 67 | - |
|
| 68 | - |
|
| 69 | - /** |
|
| 70 | - * @Export Event Espresso data - routes export requests |
|
| 71 | - * @access public |
|
| 72 | - * @return void | bool |
|
| 73 | - */ |
|
| 74 | - public function export() |
|
| 75 | - { |
|
| 76 | - // in case of bulk exports, the "actual" action will be in action2, but first check regular action for "export" keyword |
|
| 77 | - if (isset($this->_req_data['action']) && strpos($this->_req_data['action'], 'export') === false) { |
|
| 78 | - // check if action2 has export action |
|
| 79 | - if (isset($this->_req_data['action2']) && strpos($this->_req_data['action2'], 'export') !== false) { |
|
| 80 | - // whoop! there it is! |
|
| 81 | - $this->_req_data['action'] = $this->_req_data['action2']; |
|
| 82 | - } |
|
| 83 | - } |
|
| 84 | - |
|
| 85 | - $this->_req_data['export'] = isset($this->_req_data['export']) ? $this->_req_data['export'] : ''; |
|
| 86 | - |
|
| 87 | - switch ($this->_req_data['export']) { |
|
| 88 | - case 'report': |
|
| 89 | - switch ($this->_req_data['action']) { |
|
| 90 | - case "event": |
|
| 91 | - case "export_events": |
|
| 92 | - case 'all_event_data': |
|
| 93 | - $this->export_all_event_data(); |
|
| 94 | - break; |
|
| 95 | - |
|
| 96 | - case 'registrations_report_for_event': |
|
| 97 | - $this->report_registrations_for_event($this->_req_data['EVT_ID']); |
|
| 98 | - break; |
|
| 99 | - |
|
| 100 | - case 'attendees': |
|
| 101 | - $this->export_attendees(); |
|
| 102 | - break; |
|
| 103 | - |
|
| 104 | - case 'categories': |
|
| 105 | - $this->export_categories(); |
|
| 106 | - break; |
|
| 107 | - |
|
| 108 | - default: |
|
| 109 | - EE_Error::add_error( |
|
| 110 | - __('An error occurred! The requested export report could not be found.', 'event_espresso'), |
|
| 111 | - __FILE__, |
|
| 112 | - __FUNCTION__, |
|
| 113 | - __LINE__ |
|
| 114 | - ); |
|
| 115 | - return false; |
|
| 116 | - break; |
|
| 117 | - } |
|
| 118 | - break; // end of switch export : report |
|
| 119 | - default: |
|
| 120 | - break; |
|
| 121 | - } // end of switch export |
|
| 122 | - |
|
| 123 | - exit; |
|
| 124 | - } |
|
| 125 | - |
|
| 126 | - /** |
|
| 127 | - * Downloads a CSV file with all the columns, but no data. This should be used for importing |
|
| 128 | - * |
|
| 129 | - * @return null kills execution |
|
| 130 | - */ |
|
| 131 | - public function export_sample() |
|
| 132 | - { |
|
| 133 | - $event = EEM_Event::instance()->get_one(); |
|
| 134 | - $this->_req_data['EVT_ID'] = $event->ID(); |
|
| 135 | - $this->export_all_event_data(); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - |
|
| 139 | - /** |
|
| 140 | - * @Export data for ALL events |
|
| 141 | - * @access public |
|
| 142 | - * @return void |
|
| 143 | - */ |
|
| 144 | - public function export_all_event_data() |
|
| 145 | - { |
|
| 146 | - // are any Event IDs set? |
|
| 147 | - $event_query_params = array(); |
|
| 148 | - $related_models_query_params = array(); |
|
| 149 | - $related_through_reg_query_params = array(); |
|
| 150 | - $datetime_ticket_query_params = array(); |
|
| 151 | - $price_query_params = array(); |
|
| 152 | - $price_type_query_params = array(); |
|
| 153 | - $term_query_params = array(); |
|
| 154 | - $state_country_query_params = array(); |
|
| 155 | - $question_group_query_params = array(); |
|
| 156 | - $question_query_params = array(); |
|
| 157 | - if (isset($this->_req_data['EVT_ID'])) { |
|
| 158 | - // do we have an array of IDs ? |
|
| 159 | - |
|
| 160 | - if (is_array($this->_req_data['EVT_ID'])) { |
|
| 161 | - $EVT_IDs = array_map('sanitize_text_field', $this->_req_data['EVT_ID']); |
|
| 162 | - $value_to_equal = array('IN', $EVT_IDs); |
|
| 163 | - $filename = 'events'; |
|
| 164 | - } else { |
|
| 165 | - // generate regular where = clause |
|
| 166 | - $EVT_ID = absint($this->_req_data['EVT_ID']); |
|
| 167 | - $value_to_equal = $EVT_ID; |
|
| 168 | - $event = EE_Registry::instance()->load_model('Event')->get_one_by_ID($EVT_ID); |
|
| 169 | - |
|
| 170 | - $filename = 'event-' . ($event instanceof EE_Event ? $event->slug() : __('unknown', 'event_espresso')); |
|
| 171 | - } |
|
| 172 | - $event_query_params[0]['EVT_ID'] = $value_to_equal; |
|
| 173 | - $related_models_query_params[0]['Event.EVT_ID'] = $value_to_equal; |
|
| 174 | - $related_through_reg_query_params[0]['Registration.EVT_ID'] = $value_to_equal; |
|
| 175 | - $datetime_ticket_query_params[0]['Datetime.EVT_ID'] = $value_to_equal; |
|
| 176 | - $price_query_params[0]['Ticket.Datetime.EVT_ID'] = $value_to_equal; |
|
| 177 | - $price_type_query_params[0]['Price.Ticket.Datetime.EVT_ID'] = $value_to_equal; |
|
| 178 | - $term_query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $value_to_equal; |
|
| 179 | - $state_country_query_params[0]['Venue.Event.EVT_ID'] = $value_to_equal; |
|
| 180 | - $question_group_query_params[0]['Event.EVT_ID'] = $value_to_equal; |
|
| 181 | - $question_query_params[0]['Question_Group.Event.EVT_ID'] = $value_to_equal; |
|
| 182 | - } else { |
|
| 183 | - $filename = 'all-events'; |
|
| 184 | - } |
|
| 185 | - |
|
| 186 | - |
|
| 187 | - // array in the format: table name => query where clause |
|
| 188 | - $models_to_export = array( |
|
| 189 | - 'Event' => $event_query_params, |
|
| 190 | - 'Datetime' => $related_models_query_params, |
|
| 191 | - 'Ticket_Template' => $price_query_params, |
|
| 192 | - 'Ticket' => $datetime_ticket_query_params, |
|
| 193 | - 'Datetime_Ticket' => $datetime_ticket_query_params, |
|
| 194 | - 'Price_Type' => $price_type_query_params, |
|
| 195 | - 'Price' => $price_query_params, |
|
| 196 | - 'Ticket_Price' => $price_query_params, |
|
| 197 | - 'Term' => $term_query_params, |
|
| 198 | - 'Term_Taxonomy' => $related_models_query_params, |
|
| 199 | - 'Term_Relationship' => $related_models_query_params, // model has NO primary key... |
|
| 200 | - 'Country' => $state_country_query_params, |
|
| 201 | - 'State' => $state_country_query_params, |
|
| 202 | - 'Venue' => $related_models_query_params, |
|
| 203 | - 'Event_Venue' => $related_models_query_params, |
|
| 204 | - 'Question_Group' => $question_group_query_params, |
|
| 205 | - 'Event_Question_Group' => $question_group_query_params, |
|
| 206 | - 'Question' => $question_query_params, |
|
| 207 | - 'Question_Group_Question' => $question_query_params, |
|
| 208 | - // 'Transaction'=>$related_through_reg_query_params, |
|
| 209 | - // 'Registration'=>$related_models_query_params, |
|
| 210 | - // 'Attendee'=>$related_through_reg_query_params, |
|
| 211 | - // 'Line_Item'=> |
|
| 212 | - |
|
| 213 | - ); |
|
| 214 | - |
|
| 215 | - $model_data = $this->_get_export_data_for_models($models_to_export); |
|
| 216 | - |
|
| 217 | - $filename = $this->generate_filename($filename); |
|
| 218 | - |
|
| 219 | - if (! $this->EE_CSV->export_multiple_model_data_to_csv($filename, $model_data)) { |
|
| 220 | - EE_Error::add_error( |
|
| 221 | - __( |
|
| 222 | - "'An error occurred and the Event details could not be exported from the database.'", |
|
| 223 | - "event_espresso" |
|
| 224 | - ), |
|
| 225 | - __FILE__, |
|
| 226 | - __FUNCTION__, |
|
| 227 | - __LINE__ |
|
| 228 | - ); |
|
| 229 | - } |
|
| 230 | - } |
|
| 231 | - |
|
| 232 | - public function report_attendees() |
|
| 233 | - { |
|
| 234 | - $attendee_rows = EEM_Attendee::instance()->get_all_wpdb_results( |
|
| 235 | - array( |
|
| 236 | - 'force_join' => array('State', 'Country'), |
|
| 237 | - 'caps' => EEM_Base::caps_read_admin, |
|
| 238 | - ) |
|
| 239 | - ); |
|
| 240 | - $csv_data = array(); |
|
| 241 | - foreach ($attendee_rows as $attendee_row) { |
|
| 242 | - $csv_row = array(); |
|
| 243 | - foreach (EEM_Attendee::instance()->field_settings() as $field_name => $field_obj) { |
|
| 244 | - if ($field_name == 'STA_ID') { |
|
| 245 | - $state_name_field = EEM_State::instance()->field_settings_for('STA_name'); |
|
| 246 | - $csv_row[ __('State', 'event_espresso') ] = $attendee_row[ $state_name_field->get_qualified_column( |
|
| 247 | - ) ]; |
|
| 248 | - } elseif ($field_name == 'CNT_ISO') { |
|
| 249 | - $country_name_field = EEM_Country::instance()->field_settings_for('CNT_name'); |
|
| 250 | - $csv_row[ __( |
|
| 251 | - 'Country', |
|
| 252 | - 'event_espresso' |
|
| 253 | - ) ] = $attendee_row[ $country_name_field->get_qualified_column() ]; |
|
| 254 | - } else { |
|
| 255 | - $csv_row[ $field_obj->get_nicename() ] = $attendee_row[ $field_obj->get_qualified_column() ]; |
|
| 256 | - } |
|
| 257 | - } |
|
| 258 | - $csv_data[] = $csv_row; |
|
| 259 | - } |
|
| 260 | - |
|
| 261 | - $filename = $this->generate_filename('contact-list-report'); |
|
| 262 | - |
|
| 263 | - $handle = $this->EE_CSV->begin_sending_csv($filename); |
|
| 264 | - $this->EE_CSV->write_data_array_to_csv($handle, $csv_data); |
|
| 265 | - $this->EE_CSV->end_sending_csv($handle); |
|
| 266 | - } |
|
| 267 | - |
|
| 268 | - |
|
| 269 | - /** |
|
| 270 | - * @Export data for ALL attendees |
|
| 271 | - * @access public |
|
| 272 | - * @return void |
|
| 273 | - */ |
|
| 274 | - public function export_attendees() |
|
| 275 | - { |
|
| 276 | - |
|
| 277 | - $states_that_have_an_attendee = EEM_State::instance()->get_all( |
|
| 278 | - array(0 => array('Attendee.ATT_ID' => array('IS NOT NULL'))) |
|
| 279 | - ); |
|
| 280 | - $countries_that_have_an_attendee = EEM_Country::instance()->get_all( |
|
| 281 | - array(0 => array('Attendee.ATT_ID' => array('IS NOT NULL'))) |
|
| 282 | - ); |
|
| 283 | - // $states_to_export_query_params |
|
| 284 | - $models_to_export = array( |
|
| 285 | - 'Country' => array(array('CNT_ISO' => array('IN', array_keys($countries_that_have_an_attendee)))), |
|
| 286 | - 'State' => array(array('STA_ID' => array('IN', array_keys($states_that_have_an_attendee)))), |
|
| 287 | - 'Attendee' => array(), |
|
| 288 | - ); |
|
| 289 | - |
|
| 290 | - |
|
| 291 | - $model_data = $this->_get_export_data_for_models($models_to_export); |
|
| 292 | - $filename = $this->generate_filename('all-attendees'); |
|
| 293 | - |
|
| 294 | - if (! $this->EE_CSV->export_multiple_model_data_to_csv($filename, $model_data)) { |
|
| 295 | - EE_Error::add_error( |
|
| 296 | - __( |
|
| 297 | - 'An error occurred and the Attendee data could not be exported from the database.', |
|
| 298 | - 'event_espresso' |
|
| 299 | - ), |
|
| 300 | - __FILE__, |
|
| 301 | - __FUNCTION__, |
|
| 302 | - __LINE__ |
|
| 303 | - ); |
|
| 304 | - } |
|
| 305 | - } |
|
| 306 | - |
|
| 307 | - /** |
|
| 308 | - * Shortcut for preparing a database result for display |
|
| 309 | - * |
|
| 310 | - * @param EEM_Base $model |
|
| 311 | - * @param string $field_name |
|
| 312 | - * @param string $raw_db_value |
|
| 313 | - * @param boolean|string $pretty_schema true to display pretty, a string to use a specific "Schema", or false to |
|
| 314 | - * NOT display pretty |
|
| 315 | - * @return string |
|
| 316 | - */ |
|
| 317 | - protected function _prepare_value_from_db_for_display($model, $field_name, $raw_db_value, $pretty_schema = true) |
|
| 318 | - { |
|
| 319 | - $field_obj = $model->field_settings_for($field_name); |
|
| 320 | - $value_on_model_obj = $field_obj->prepare_for_set_from_db($raw_db_value); |
|
| 321 | - if ($field_obj instanceof EE_Datetime_Field) { |
|
| 322 | - $field_obj->set_date_format( |
|
| 323 | - EE_CSV::instance()->get_date_format_for_csv($field_obj->get_date_format($pretty_schema)), |
|
| 324 | - $pretty_schema |
|
| 325 | - ); |
|
| 326 | - $field_obj->set_time_format( |
|
| 327 | - EE_CSV::instance()->get_time_format_for_csv($field_obj->get_time_format($pretty_schema)), |
|
| 328 | - $pretty_schema |
|
| 329 | - ); |
|
| 330 | - } |
|
| 331 | - if ($pretty_schema === true) { |
|
| 332 | - return $field_obj->prepare_for_pretty_echoing($value_on_model_obj); |
|
| 333 | - } elseif (is_string($pretty_schema)) { |
|
| 334 | - return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema); |
|
| 335 | - } else { |
|
| 336 | - return $field_obj->prepare_for_get($value_on_model_obj); |
|
| 337 | - } |
|
| 338 | - } |
|
| 339 | - |
|
| 340 | - /** |
|
| 341 | - * Export a custom CSV of registration info including: A bunch of the reg fields, the time of the event, the price |
|
| 342 | - * name, and the questions associated with the registrations |
|
| 343 | - * |
|
| 344 | - * @param int $event_id |
|
| 345 | - */ |
|
| 346 | - public function report_registrations_for_event($event_id = null) |
|
| 347 | - { |
|
| 348 | - $reg_fields_to_include = array( |
|
| 349 | - 'TXN_ID', |
|
| 350 | - 'ATT_ID', |
|
| 351 | - 'REG_ID', |
|
| 352 | - 'REG_date', |
|
| 353 | - 'REG_code', |
|
| 354 | - 'REG_count', |
|
| 355 | - 'REG_final_price', |
|
| 356 | - |
|
| 357 | - ); |
|
| 358 | - $att_fields_to_include = array( |
|
| 359 | - 'ATT_fname', |
|
| 360 | - 'ATT_lname', |
|
| 361 | - 'ATT_email', |
|
| 362 | - 'ATT_address', |
|
| 363 | - 'ATT_address2', |
|
| 364 | - 'ATT_city', |
|
| 365 | - 'STA_ID', |
|
| 366 | - 'CNT_ISO', |
|
| 367 | - 'ATT_zip', |
|
| 368 | - 'ATT_phone', |
|
| 369 | - ); |
|
| 370 | - |
|
| 371 | - $registrations_csv_ready_array = array(); |
|
| 372 | - $reg_model = EE_Registry::instance()->load_model('Registration'); |
|
| 373 | - $query_params = apply_filters( |
|
| 374 | - 'FHEE__EE_Export__report_registration_for_event', |
|
| 375 | - array( |
|
| 376 | - array( |
|
| 377 | - 'OR' => array( |
|
| 378 | - // don't include registrations from failed or abandoned transactions... |
|
| 379 | - 'Transaction.STS_ID' => array( |
|
| 380 | - 'NOT IN', |
|
| 381 | - array(EEM_Transaction::failed_status_code, EEM_Transaction::abandoned_status_code), |
|
| 382 | - ), |
|
| 383 | - // unless the registration is approved, in which case include it regardless of transaction status |
|
| 384 | - 'STS_ID' => EEM_Registration::status_id_approved, |
|
| 385 | - ), |
|
| 386 | - 'Ticket.TKT_deleted' => array('IN', array(true, false)), |
|
| 387 | - ), |
|
| 388 | - 'order_by' => array('Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'), |
|
| 389 | - 'force_join' => array('Transaction', 'Ticket', 'Attendee'), |
|
| 390 | - 'caps' => EEM_Base::caps_read_admin, |
|
| 391 | - ), |
|
| 392 | - $event_id |
|
| 393 | - ); |
|
| 394 | - if ($event_id) { |
|
| 395 | - $query_params[0]['EVT_ID'] = $event_id; |
|
| 396 | - } else { |
|
| 397 | - $query_params['force_join'][] = 'Event'; |
|
| 398 | - } |
|
| 399 | - $registration_rows = $reg_model->get_all_wpdb_results($query_params); |
|
| 400 | - // get all questions which relate to someone in this group |
|
| 401 | - $registration_ids = array(); |
|
| 402 | - foreach ($registration_rows as $reg_row) { |
|
| 403 | - $registration_ids[] = intval($reg_row['Registration.REG_ID']); |
|
| 404 | - } |
|
| 405 | - // EEM_Question::instance()->show_next_x_db_queries(); |
|
| 406 | - $questions_for_these_regs_rows = EEM_Question::instance()->get_all_wpdb_results( |
|
| 407 | - array(array('Answer.REG_ID' => array('IN', $registration_ids))) |
|
| 408 | - ); |
|
| 409 | - foreach ($registration_rows as $reg_row) { |
|
| 410 | - if (is_array($reg_row)) { |
|
| 411 | - $reg_csv_array = array(); |
|
| 412 | - if (! $event_id) { |
|
| 413 | - // get the event's name and Id |
|
| 414 | - $reg_csv_array[ __('Event', 'event_espresso') ] = sprintf( |
|
| 415 | - __('%1$s (%2$s)', 'event_espresso'), |
|
| 416 | - $this->_prepare_value_from_db_for_display( |
|
| 417 | - EEM_Event::instance(), |
|
| 418 | - 'EVT_name', |
|
| 419 | - $reg_row['Event_CPT.post_title'] |
|
| 420 | - ), |
|
| 421 | - $reg_row['Event_CPT.ID'] |
|
| 422 | - ); |
|
| 423 | - } |
|
| 424 | - $is_primary_reg = $reg_row['Registration.REG_count'] == '1' ? true : false; |
|
| 425 | - /*@var $reg_row EE_Registration */ |
|
| 426 | - foreach ($reg_fields_to_include as $field_name) { |
|
| 427 | - $field = $reg_model->field_settings_for($field_name); |
|
| 428 | - if ($field_name == 'REG_final_price') { |
|
| 429 | - $value = $this->_prepare_value_from_db_for_display( |
|
| 430 | - $reg_model, |
|
| 431 | - $field_name, |
|
| 432 | - $reg_row['Registration.REG_final_price'], |
|
| 433 | - 'localized_float' |
|
| 434 | - ); |
|
| 435 | - } elseif ($field_name == 'REG_count') { |
|
| 436 | - $value = sprintf( |
|
| 437 | - __('%s of %s', 'event_espresso'), |
|
| 438 | - $this->_prepare_value_from_db_for_display( |
|
| 439 | - $reg_model, |
|
| 440 | - 'REG_count', |
|
| 441 | - $reg_row['Registration.REG_count'] |
|
| 442 | - ), |
|
| 443 | - $this->_prepare_value_from_db_for_display( |
|
| 444 | - $reg_model, |
|
| 445 | - 'REG_group_size', |
|
| 446 | - $reg_row['Registration.REG_group_size'] |
|
| 447 | - ) |
|
| 448 | - ); |
|
| 449 | - } elseif ($field_name == 'REG_date') { |
|
| 450 | - $value = $this->_prepare_value_from_db_for_display( |
|
| 451 | - $reg_model, |
|
| 452 | - $field_name, |
|
| 453 | - $reg_row['Registration.REG_date'], |
|
| 454 | - 'no_html' |
|
| 455 | - ); |
|
| 456 | - } else { |
|
| 457 | - $value = $this->_prepare_value_from_db_for_display( |
|
| 458 | - $reg_model, |
|
| 459 | - $field_name, |
|
| 460 | - $reg_row[ $field->get_qualified_column() ] |
|
| 461 | - ); |
|
| 462 | - } |
|
| 463 | - $reg_csv_array[ $this->_get_column_name_for_field($field) ] = $value; |
|
| 464 | - if ($field_name == 'REG_final_price') { |
|
| 465 | - // add a column named Currency after the final price |
|
| 466 | - $reg_csv_array[ __("Currency", "event_espresso") ] = EE_Config::instance()->currency->code; |
|
| 467 | - } |
|
| 468 | - } |
|
| 469 | - // get pretty status |
|
| 470 | - $stati = EEM_Status::instance()->localized_status( |
|
| 471 | - array( |
|
| 472 | - $reg_row['Registration.STS_ID'] => __('unknown', 'event_espresso'), |
|
| 473 | - $reg_row['TransactionTable.STS_ID'] => __('unknown', 'event_espresso'), |
|
| 474 | - ), |
|
| 475 | - false, |
|
| 476 | - 'sentence' |
|
| 477 | - ); |
|
| 478 | - $reg_csv_array[ __( |
|
| 479 | - "Registration Status", |
|
| 480 | - 'event_espresso' |
|
| 481 | - ) ] = $stati[ $reg_row['Registration.STS_ID'] ]; |
|
| 482 | - // get pretty trnasaction status |
|
| 483 | - $reg_csv_array[ __( |
|
| 484 | - "Transaction Status", |
|
| 485 | - 'event_espresso' |
|
| 486 | - ) ] = $stati[ $reg_row['TransactionTable.STS_ID'] ]; |
|
| 487 | - $reg_csv_array[ __('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg |
|
| 488 | - ? $this->_prepare_value_from_db_for_display( |
|
| 489 | - EEM_Transaction::instance(), |
|
| 490 | - 'TXN_total', |
|
| 491 | - $reg_row['TransactionTable.TXN_total'], |
|
| 492 | - 'localized_float' |
|
| 493 | - ) : '0.00'; |
|
| 494 | - $reg_csv_array[ __('Amount Paid', 'event_espresso') ] = $is_primary_reg |
|
| 495 | - ? $this->_prepare_value_from_db_for_display( |
|
| 496 | - EEM_Transaction::instance(), |
|
| 497 | - 'TXN_paid', |
|
| 498 | - $reg_row['TransactionTable.TXN_paid'], |
|
| 499 | - 'localized_float' |
|
| 500 | - ) : '0.00'; |
|
| 501 | - $payment_methods = array(); |
|
| 502 | - $gateway_txn_ids_etc = array(); |
|
| 503 | - $payment_times = array(); |
|
| 504 | - if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) { |
|
| 505 | - $payments_info = EEM_Payment::instance()->get_all_wpdb_results( |
|
| 506 | - array( |
|
| 507 | - array( |
|
| 508 | - 'TXN_ID' => $reg_row['TransactionTable.TXN_ID'], |
|
| 509 | - 'STS_ID' => EEM_Payment::status_id_approved, |
|
| 510 | - ), |
|
| 511 | - 'force_join' => array('Payment_Method'), |
|
| 512 | - ), |
|
| 513 | - ARRAY_A, |
|
| 514 | - 'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time' |
|
| 515 | - ); |
|
| 516 | - |
|
| 517 | - foreach ($payments_info as $payment_method_and_gateway_txn_id) { |
|
| 518 | - $payment_methods[] = isset($payment_method_and_gateway_txn_id['name']) |
|
| 519 | - ? $payment_method_and_gateway_txn_id['name'] : __('Unknown', 'event_espresso'); |
|
| 520 | - $gateway_txn_ids_etc[] = isset($payment_method_and_gateway_txn_id['gateway_txn_id']) |
|
| 521 | - ? $payment_method_and_gateway_txn_id['gateway_txn_id'] : ''; |
|
| 522 | - $payment_times[] = isset($payment_method_and_gateway_txn_id['payment_time']) |
|
| 523 | - ? $payment_method_and_gateway_txn_id['payment_time'] : ''; |
|
| 524 | - } |
|
| 525 | - } |
|
| 526 | - $reg_csv_array[ __('Payment Date(s)', 'event_espresso') ] = implode(',', $payment_times); |
|
| 527 | - $reg_csv_array[ __('Payment Method(s)', 'event_espresso') ] = implode(",", $payment_methods); |
|
| 528 | - $reg_csv_array[ __('Gateway Transaction ID(s)', 'event_espresso') ] = implode( |
|
| 529 | - ',', |
|
| 530 | - $gateway_txn_ids_etc |
|
| 531 | - ); |
|
| 532 | - |
|
| 533 | - // get whether or not the user has checked in |
|
| 534 | - $reg_csv_array[ __("Check-Ins", "event_espresso") ] = $reg_model->count_related( |
|
| 535 | - $reg_row['Registration.REG_ID'], |
|
| 536 | - 'Checkin' |
|
| 537 | - ); |
|
| 538 | - // get ticket of registration and its price |
|
| 539 | - $ticket_model = EE_Registry::instance()->load_model('Ticket'); |
|
| 540 | - if ($reg_row['Ticket.TKT_ID']) { |
|
| 541 | - $ticket_name = $this->_prepare_value_from_db_for_display( |
|
| 542 | - $ticket_model, |
|
| 543 | - 'TKT_name', |
|
| 544 | - $reg_row['Ticket.TKT_name'] |
|
| 545 | - ); |
|
| 546 | - $datetimes_strings = array(); |
|
| 547 | - foreach ( |
|
| 548 | - EEM_Datetime::instance()->get_all_wpdb_results( |
|
| 549 | - array( |
|
| 550 | - array('Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']), |
|
| 551 | - 'order_by' => array('DTT_EVT_start' => 'ASC'), |
|
| 552 | - 'default_where_conditions' => 'none', |
|
| 553 | - ) |
|
| 554 | - ) as $datetime |
|
| 555 | - ) { |
|
| 556 | - $datetimes_strings[] = $this->_prepare_value_from_db_for_display( |
|
| 557 | - EEM_Datetime::instance(), |
|
| 558 | - 'DTT_EVT_start', |
|
| 559 | - $datetime['Datetime.DTT_EVT_start'] |
|
| 560 | - ); |
|
| 561 | - } |
|
| 562 | - } else { |
|
| 563 | - $ticket_name = __('Unknown', 'event_espresso'); |
|
| 564 | - $datetimes_strings = array(__('Unknown', 'event_espresso')); |
|
| 565 | - } |
|
| 566 | - $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name; |
|
| 567 | - $reg_csv_array[ __("Datetimes of Ticket", "event_espresso") ] = implode(", ", $datetimes_strings); |
|
| 568 | - // get datetime(s) of registration |
|
| 569 | - |
|
| 570 | - // add attendee columns |
|
| 571 | - foreach ($att_fields_to_include as $att_field_name) { |
|
| 572 | - $field_obj = EEM_Attendee::instance()->field_settings_for($att_field_name); |
|
| 573 | - if ($reg_row['Attendee_CPT.ID']) { |
|
| 574 | - if ($att_field_name == 'STA_ID') { |
|
| 575 | - $value = EEM_State::instance()->get_var( |
|
| 576 | - array(array('STA_ID' => $reg_row['Attendee_Meta.STA_ID'])), |
|
| 577 | - 'STA_name' |
|
| 578 | - ); |
|
| 579 | - } elseif ($att_field_name == 'CNT_ISO') { |
|
| 580 | - $value = EEM_Country::instance()->get_var( |
|
| 581 | - array(array('CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO'])), |
|
| 582 | - 'CNT_name' |
|
| 583 | - ); |
|
| 584 | - } else { |
|
| 585 | - $value = $this->_prepare_value_from_db_for_display( |
|
| 586 | - EEM_Attendee::instance(), |
|
| 587 | - $att_field_name, |
|
| 588 | - $reg_row[ $field_obj->get_qualified_column() ] |
|
| 589 | - ); |
|
| 590 | - } |
|
| 591 | - } else { |
|
| 592 | - $value = ''; |
|
| 593 | - } |
|
| 594 | - |
|
| 595 | - $reg_csv_array[ $this->_get_column_name_for_field($field_obj) ] = $value; |
|
| 596 | - } |
|
| 597 | - |
|
| 598 | - // make sure each registration has the same questions in the same order |
|
| 599 | - foreach ($questions_for_these_regs_rows as $question_row) { |
|
| 600 | - if (! isset($reg_csv_array[ $question_row['Question.QST_admin_label'] ])) { |
|
| 601 | - $reg_csv_array[ $question_row['Question.QST_admin_label'] ] = null; |
|
| 602 | - } |
|
| 603 | - } |
|
| 604 | - // now fill out the questions THEY answered |
|
| 605 | - foreach ( |
|
| 606 | - EEM_Answer::instance()->get_all_wpdb_results( |
|
| 607 | - array(array('REG_ID' => $reg_row['Registration.REG_ID']), 'force_join' => array('Question')) |
|
| 608 | - ) as $answer_row |
|
| 609 | - ) { |
|
| 610 | - /* @var $answer EE_Answer */ |
|
| 611 | - if ($answer_row['Question.QST_ID']) { |
|
| 612 | - $question_label = $this->_prepare_value_from_db_for_display( |
|
| 613 | - EEM_Question::instance(), |
|
| 614 | - 'QST_admin_label', |
|
| 615 | - $answer_row['Question.QST_admin_label'] |
|
| 616 | - ); |
|
| 617 | - } else { |
|
| 618 | - $question_label = sprintf(__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']); |
|
| 619 | - } |
|
| 620 | - if (isset($answer_row['Question.QST_type']) && $answer_row['Question.QST_type'] == EEM_Question::QST_type_state) { |
|
| 621 | - $reg_csv_array[ $question_label ] = EEM_State::instance()->get_state_name_by_ID( |
|
| 622 | - $answer_row['Answer.ANS_value'] |
|
| 623 | - ); |
|
| 624 | - } else { |
|
| 625 | - $reg_csv_array[ $question_label ] = $this->_prepare_value_from_db_for_display( |
|
| 626 | - EEM_Answer::instance(), |
|
| 627 | - 'ANS_value', |
|
| 628 | - $answer_row['Answer.ANS_value'] |
|
| 629 | - ); |
|
| 630 | - } |
|
| 631 | - } |
|
| 632 | - $registrations_csv_ready_array[] = apply_filters( |
|
| 633 | - 'FHEE__EE_Export__report_registrations__reg_csv_array', |
|
| 634 | - $reg_csv_array, |
|
| 635 | - $reg_row |
|
| 636 | - ); |
|
| 637 | - } |
|
| 638 | - } |
|
| 639 | - |
|
| 640 | - // if we couldn't export anything, we want to at least show the column headers |
|
| 641 | - if (empty($registrations_csv_ready_array)) { |
|
| 642 | - $reg_csv_array = array(); |
|
| 643 | - $model_and_fields_to_include = array( |
|
| 644 | - 'Registration' => $reg_fields_to_include, |
|
| 645 | - 'Attendee' => $att_fields_to_include, |
|
| 646 | - ); |
|
| 647 | - foreach ($model_and_fields_to_include as $model_name => $field_list) { |
|
| 648 | - $model = EE_Registry::instance()->load_model($model_name); |
|
| 649 | - foreach ($field_list as $field_name) { |
|
| 650 | - $field = $model->field_settings_for($field_name); |
|
| 651 | - $reg_csv_array[ $this->_get_column_name_for_field( |
|
| 652 | - $field |
|
| 653 | - ) ] = null;// $registration->get($field->get_name()); |
|
| 654 | - } |
|
| 655 | - } |
|
| 656 | - $registrations_csv_ready_array [] = $reg_csv_array; |
|
| 657 | - } |
|
| 658 | - if ($event_id) { |
|
| 659 | - $event_slug = EEM_Event::instance()->get_var(array(array('EVT_ID' => $event_id)), 'EVT_slug'); |
|
| 660 | - if (! $event_slug) { |
|
| 661 | - $event_slug = __('unknown', 'event_espresso'); |
|
| 662 | - } |
|
| 663 | - } else { |
|
| 664 | - $event_slug = __('all', 'event_espresso'); |
|
| 665 | - } |
|
| 666 | - $filename = sprintf("registrations-for-%s", $event_slug); |
|
| 667 | - |
|
| 668 | - $handle = $this->EE_CSV->begin_sending_csv($filename); |
|
| 669 | - $this->EE_CSV->write_data_array_to_csv($handle, $registrations_csv_ready_array); |
|
| 670 | - $this->EE_CSV->end_sending_csv($handle); |
|
| 671 | - } |
|
| 672 | - |
|
| 673 | - /** |
|
| 674 | - * Gets the 'normal' column named for fields |
|
| 675 | - * |
|
| 676 | - * @param EE_Model_Field_Base $field |
|
| 677 | - * @return string |
|
| 678 | - */ |
|
| 679 | - protected function _get_column_name_for_field(EE_Model_Field_Base $field) |
|
| 680 | - { |
|
| 681 | - return $field->get_nicename() . "[" . $field->get_name() . "]"; |
|
| 682 | - } |
|
| 683 | - |
|
| 684 | - |
|
| 685 | - /** |
|
| 686 | - * @Export data for ALL events |
|
| 687 | - * @access public |
|
| 688 | - * @return void |
|
| 689 | - */ |
|
| 690 | - public function export_categories() |
|
| 691 | - { |
|
| 692 | - // are any Event IDs set? |
|
| 693 | - $query_params = array(); |
|
| 694 | - if (isset($this->_req_data['EVT_CAT_ID'])) { |
|
| 695 | - // do we have an array of IDs ? |
|
| 696 | - if (is_array($this->_req_data['EVT_CAT_ID'])) { |
|
| 697 | - // generate an "IN (CSV)" where clause |
|
| 698 | - $EVT_CAT_IDs = array_map('sanitize_text_field', $this->_req_data['EVT_CAT_ID']); |
|
| 699 | - $filename = 'event-categories'; |
|
| 700 | - $query_params[0]['term_taxonomy_id'] = array('IN', $EVT_CAT_IDs); |
|
| 701 | - } else { |
|
| 702 | - // generate regular where = clause |
|
| 703 | - $EVT_CAT_ID = absint($this->_req_data['EVT_CAT_ID']); |
|
| 704 | - $filename = 'event-category#' . $EVT_CAT_ID; |
|
| 705 | - $query_params[0]['term_taxonomy_id'] = $EVT_CAT_ID; |
|
| 706 | - } |
|
| 707 | - } else { |
|
| 708 | - // no IDs means we will d/l the entire table |
|
| 709 | - $filename = 'all-categories'; |
|
| 710 | - } |
|
| 711 | - |
|
| 712 | - $tables_to_export = array( |
|
| 713 | - 'Term_Taxonomy' => $query_params, |
|
| 714 | - ); |
|
| 715 | - |
|
| 716 | - $table_data = $this->_get_export_data_for_models($tables_to_export); |
|
| 717 | - $filename = $this->generate_filename($filename); |
|
| 718 | - |
|
| 719 | - if (! $this->EE_CSV->export_multiple_model_data_to_csv($filename, $table_data)) { |
|
| 720 | - EE_Error::add_error( |
|
| 721 | - __( |
|
| 722 | - 'An error occurred and the Category details could not be exported from the database.', |
|
| 723 | - 'event_espresso' |
|
| 724 | - ), |
|
| 725 | - __FILE__, |
|
| 726 | - __FUNCTION__, |
|
| 727 | - __LINE__ |
|
| 728 | - ); |
|
| 729 | - } |
|
| 730 | - } |
|
| 731 | - |
|
| 732 | - |
|
| 733 | - /** |
|
| 734 | - * @process export name to create a suitable filename |
|
| 735 | - * @access private |
|
| 736 | - * @param string - export_name |
|
| 737 | - * @return string on success, FALSE on fail |
|
| 738 | - */ |
|
| 739 | - private function generate_filename($export_name = '') |
|
| 740 | - { |
|
| 741 | - if ($export_name != '') { |
|
| 742 | - $filename = get_bloginfo('name') . '-' . $export_name; |
|
| 743 | - $filename = sanitize_key($filename) . '-' . $this->today; |
|
| 744 | - return $filename; |
|
| 745 | - } else { |
|
| 746 | - EE_Error::add_error(__("No filename was provided", "event_espresso"), __FILE__, __FUNCTION__, __LINE__); |
|
| 747 | - } |
|
| 748 | - return false; |
|
| 749 | - } |
|
| 750 | - |
|
| 751 | - |
|
| 752 | - /** |
|
| 753 | - * @recursive function for exporting table data and merging the results with the next results |
|
| 754 | - * @access private |
|
| 755 | - * @param array $models_to_export keys are model names (eg 'Event', 'Attendee', etc.) and values are arrays of |
|
| 756 | - * query params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 757 | - * @return array on success, FALSE on fail |
|
| 758 | - */ |
|
| 759 | - private function _get_export_data_for_models($models_to_export = array()) |
|
| 760 | - { |
|
| 761 | - $table_data = false; |
|
| 762 | - if (is_array($models_to_export)) { |
|
| 763 | - foreach ($models_to_export as $model_name => $query_params) { |
|
| 764 | - // check for a numerically-indexed array. in that case, $model_name is the value!! |
|
| 765 | - if (is_int($model_name)) { |
|
| 766 | - $model_name = $query_params; |
|
| 767 | - $query_params = array(); |
|
| 768 | - } |
|
| 769 | - $model = EE_Registry::instance()->load_model($model_name); |
|
| 770 | - $model_objects = $model->get_all($query_params); |
|
| 771 | - |
|
| 772 | - $table_data[ $model_name ] = array(); |
|
| 773 | - foreach ($model_objects as $model_object) { |
|
| 774 | - $model_data_array = array(); |
|
| 775 | - $fields = $model->field_settings(); |
|
| 776 | - foreach ($fields as $field) { |
|
| 777 | - $column_name = $field->get_nicename() . "[" . $field->get_name() . "]"; |
|
| 778 | - if ($field instanceof EE_Datetime_Field) { |
|
| 779 | - // $field->set_date_format('Y-m-d'); |
|
| 780 | - // $field->set_time_format('H:i:s'); |
|
| 781 | - $model_data_array[ $column_name ] = $model_object->get_datetime( |
|
| 782 | - $field->get_name(), |
|
| 783 | - 'Y-m-d', |
|
| 784 | - 'H:i:s' |
|
| 785 | - ); |
|
| 786 | - } else { |
|
| 787 | - $model_data_array[ $column_name ] = $model_object->get($field->get_name()); |
|
| 788 | - } |
|
| 789 | - } |
|
| 790 | - $table_data[ $model_name ][] = $model_data_array; |
|
| 791 | - } |
|
| 792 | - } |
|
| 793 | - } |
|
| 794 | - return $table_data; |
|
| 795 | - } |
|
| 19 | + const option_prefix = 'ee_report_job_'; |
|
| 20 | + |
|
| 21 | + |
|
| 22 | + // instance of the EE_Export object |
|
| 23 | + private static $_instance; |
|
| 24 | + |
|
| 25 | + // instance of the EE_CSV object |
|
| 26 | + /** |
|
| 27 | + * |
|
| 28 | + * @var EE_CSV |
|
| 29 | + */ |
|
| 30 | + public $EE_CSV = null; |
|
| 31 | + |
|
| 32 | + |
|
| 33 | + private $_req_data = array(); |
|
| 34 | + |
|
| 35 | + |
|
| 36 | + /** |
|
| 37 | + * private constructor to prevent direct creation |
|
| 38 | + * |
|
| 39 | + * @Constructor |
|
| 40 | + * @access private |
|
| 41 | + * @param array $request_data |
|
| 42 | + */ |
|
| 43 | + private function __construct($request_data = array()) |
|
| 44 | + { |
|
| 45 | + $this->_req_data = $request_data; |
|
| 46 | + $this->today = date("Y-m-d", time()); |
|
| 47 | + require_once(EE_CLASSES . 'EE_CSV.class.php'); |
|
| 48 | + $this->EE_CSV = EE_CSV::instance(); |
|
| 49 | + } |
|
| 50 | + |
|
| 51 | + |
|
| 52 | + /** |
|
| 53 | + * @ singleton method used to instantiate class object |
|
| 54 | + * @ access public |
|
| 55 | + * |
|
| 56 | + * @param array $request_data |
|
| 57 | + * @return \EE_Export |
|
| 58 | + */ |
|
| 59 | + public static function instance($request_data = array()) |
|
| 60 | + { |
|
| 61 | + // check if class object is instantiated |
|
| 62 | + if (self::$_instance === null or ! is_object(self::$_instance) or ! (self::$_instance instanceof EE_Export)) { |
|
| 63 | + self::$_instance = new self($request_data); |
|
| 64 | + } |
|
| 65 | + return self::$_instance; |
|
| 66 | + } |
|
| 67 | + |
|
| 68 | + |
|
| 69 | + /** |
|
| 70 | + * @Export Event Espresso data - routes export requests |
|
| 71 | + * @access public |
|
| 72 | + * @return void | bool |
|
| 73 | + */ |
|
| 74 | + public function export() |
|
| 75 | + { |
|
| 76 | + // in case of bulk exports, the "actual" action will be in action2, but first check regular action for "export" keyword |
|
| 77 | + if (isset($this->_req_data['action']) && strpos($this->_req_data['action'], 'export') === false) { |
|
| 78 | + // check if action2 has export action |
|
| 79 | + if (isset($this->_req_data['action2']) && strpos($this->_req_data['action2'], 'export') !== false) { |
|
| 80 | + // whoop! there it is! |
|
| 81 | + $this->_req_data['action'] = $this->_req_data['action2']; |
|
| 82 | + } |
|
| 83 | + } |
|
| 84 | + |
|
| 85 | + $this->_req_data['export'] = isset($this->_req_data['export']) ? $this->_req_data['export'] : ''; |
|
| 86 | + |
|
| 87 | + switch ($this->_req_data['export']) { |
|
| 88 | + case 'report': |
|
| 89 | + switch ($this->_req_data['action']) { |
|
| 90 | + case "event": |
|
| 91 | + case "export_events": |
|
| 92 | + case 'all_event_data': |
|
| 93 | + $this->export_all_event_data(); |
|
| 94 | + break; |
|
| 95 | + |
|
| 96 | + case 'registrations_report_for_event': |
|
| 97 | + $this->report_registrations_for_event($this->_req_data['EVT_ID']); |
|
| 98 | + break; |
|
| 99 | + |
|
| 100 | + case 'attendees': |
|
| 101 | + $this->export_attendees(); |
|
| 102 | + break; |
|
| 103 | + |
|
| 104 | + case 'categories': |
|
| 105 | + $this->export_categories(); |
|
| 106 | + break; |
|
| 107 | + |
|
| 108 | + default: |
|
| 109 | + EE_Error::add_error( |
|
| 110 | + __('An error occurred! The requested export report could not be found.', 'event_espresso'), |
|
| 111 | + __FILE__, |
|
| 112 | + __FUNCTION__, |
|
| 113 | + __LINE__ |
|
| 114 | + ); |
|
| 115 | + return false; |
|
| 116 | + break; |
|
| 117 | + } |
|
| 118 | + break; // end of switch export : report |
|
| 119 | + default: |
|
| 120 | + break; |
|
| 121 | + } // end of switch export |
|
| 122 | + |
|
| 123 | + exit; |
|
| 124 | + } |
|
| 125 | + |
|
| 126 | + /** |
|
| 127 | + * Downloads a CSV file with all the columns, but no data. This should be used for importing |
|
| 128 | + * |
|
| 129 | + * @return null kills execution |
|
| 130 | + */ |
|
| 131 | + public function export_sample() |
|
| 132 | + { |
|
| 133 | + $event = EEM_Event::instance()->get_one(); |
|
| 134 | + $this->_req_data['EVT_ID'] = $event->ID(); |
|
| 135 | + $this->export_all_event_data(); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + |
|
| 139 | + /** |
|
| 140 | + * @Export data for ALL events |
|
| 141 | + * @access public |
|
| 142 | + * @return void |
|
| 143 | + */ |
|
| 144 | + public function export_all_event_data() |
|
| 145 | + { |
|
| 146 | + // are any Event IDs set? |
|
| 147 | + $event_query_params = array(); |
|
| 148 | + $related_models_query_params = array(); |
|
| 149 | + $related_through_reg_query_params = array(); |
|
| 150 | + $datetime_ticket_query_params = array(); |
|
| 151 | + $price_query_params = array(); |
|
| 152 | + $price_type_query_params = array(); |
|
| 153 | + $term_query_params = array(); |
|
| 154 | + $state_country_query_params = array(); |
|
| 155 | + $question_group_query_params = array(); |
|
| 156 | + $question_query_params = array(); |
|
| 157 | + if (isset($this->_req_data['EVT_ID'])) { |
|
| 158 | + // do we have an array of IDs ? |
|
| 159 | + |
|
| 160 | + if (is_array($this->_req_data['EVT_ID'])) { |
|
| 161 | + $EVT_IDs = array_map('sanitize_text_field', $this->_req_data['EVT_ID']); |
|
| 162 | + $value_to_equal = array('IN', $EVT_IDs); |
|
| 163 | + $filename = 'events'; |
|
| 164 | + } else { |
|
| 165 | + // generate regular where = clause |
|
| 166 | + $EVT_ID = absint($this->_req_data['EVT_ID']); |
|
| 167 | + $value_to_equal = $EVT_ID; |
|
| 168 | + $event = EE_Registry::instance()->load_model('Event')->get_one_by_ID($EVT_ID); |
|
| 169 | + |
|
| 170 | + $filename = 'event-' . ($event instanceof EE_Event ? $event->slug() : __('unknown', 'event_espresso')); |
|
| 171 | + } |
|
| 172 | + $event_query_params[0]['EVT_ID'] = $value_to_equal; |
|
| 173 | + $related_models_query_params[0]['Event.EVT_ID'] = $value_to_equal; |
|
| 174 | + $related_through_reg_query_params[0]['Registration.EVT_ID'] = $value_to_equal; |
|
| 175 | + $datetime_ticket_query_params[0]['Datetime.EVT_ID'] = $value_to_equal; |
|
| 176 | + $price_query_params[0]['Ticket.Datetime.EVT_ID'] = $value_to_equal; |
|
| 177 | + $price_type_query_params[0]['Price.Ticket.Datetime.EVT_ID'] = $value_to_equal; |
|
| 178 | + $term_query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $value_to_equal; |
|
| 179 | + $state_country_query_params[0]['Venue.Event.EVT_ID'] = $value_to_equal; |
|
| 180 | + $question_group_query_params[0]['Event.EVT_ID'] = $value_to_equal; |
|
| 181 | + $question_query_params[0]['Question_Group.Event.EVT_ID'] = $value_to_equal; |
|
| 182 | + } else { |
|
| 183 | + $filename = 'all-events'; |
|
| 184 | + } |
|
| 185 | + |
|
| 186 | + |
|
| 187 | + // array in the format: table name => query where clause |
|
| 188 | + $models_to_export = array( |
|
| 189 | + 'Event' => $event_query_params, |
|
| 190 | + 'Datetime' => $related_models_query_params, |
|
| 191 | + 'Ticket_Template' => $price_query_params, |
|
| 192 | + 'Ticket' => $datetime_ticket_query_params, |
|
| 193 | + 'Datetime_Ticket' => $datetime_ticket_query_params, |
|
| 194 | + 'Price_Type' => $price_type_query_params, |
|
| 195 | + 'Price' => $price_query_params, |
|
| 196 | + 'Ticket_Price' => $price_query_params, |
|
| 197 | + 'Term' => $term_query_params, |
|
| 198 | + 'Term_Taxonomy' => $related_models_query_params, |
|
| 199 | + 'Term_Relationship' => $related_models_query_params, // model has NO primary key... |
|
| 200 | + 'Country' => $state_country_query_params, |
|
| 201 | + 'State' => $state_country_query_params, |
|
| 202 | + 'Venue' => $related_models_query_params, |
|
| 203 | + 'Event_Venue' => $related_models_query_params, |
|
| 204 | + 'Question_Group' => $question_group_query_params, |
|
| 205 | + 'Event_Question_Group' => $question_group_query_params, |
|
| 206 | + 'Question' => $question_query_params, |
|
| 207 | + 'Question_Group_Question' => $question_query_params, |
|
| 208 | + // 'Transaction'=>$related_through_reg_query_params, |
|
| 209 | + // 'Registration'=>$related_models_query_params, |
|
| 210 | + // 'Attendee'=>$related_through_reg_query_params, |
|
| 211 | + // 'Line_Item'=> |
|
| 212 | + |
|
| 213 | + ); |
|
| 214 | + |
|
| 215 | + $model_data = $this->_get_export_data_for_models($models_to_export); |
|
| 216 | + |
|
| 217 | + $filename = $this->generate_filename($filename); |
|
| 218 | + |
|
| 219 | + if (! $this->EE_CSV->export_multiple_model_data_to_csv($filename, $model_data)) { |
|
| 220 | + EE_Error::add_error( |
|
| 221 | + __( |
|
| 222 | + "'An error occurred and the Event details could not be exported from the database.'", |
|
| 223 | + "event_espresso" |
|
| 224 | + ), |
|
| 225 | + __FILE__, |
|
| 226 | + __FUNCTION__, |
|
| 227 | + __LINE__ |
|
| 228 | + ); |
|
| 229 | + } |
|
| 230 | + } |
|
| 231 | + |
|
| 232 | + public function report_attendees() |
|
| 233 | + { |
|
| 234 | + $attendee_rows = EEM_Attendee::instance()->get_all_wpdb_results( |
|
| 235 | + array( |
|
| 236 | + 'force_join' => array('State', 'Country'), |
|
| 237 | + 'caps' => EEM_Base::caps_read_admin, |
|
| 238 | + ) |
|
| 239 | + ); |
|
| 240 | + $csv_data = array(); |
|
| 241 | + foreach ($attendee_rows as $attendee_row) { |
|
| 242 | + $csv_row = array(); |
|
| 243 | + foreach (EEM_Attendee::instance()->field_settings() as $field_name => $field_obj) { |
|
| 244 | + if ($field_name == 'STA_ID') { |
|
| 245 | + $state_name_field = EEM_State::instance()->field_settings_for('STA_name'); |
|
| 246 | + $csv_row[ __('State', 'event_espresso') ] = $attendee_row[ $state_name_field->get_qualified_column( |
|
| 247 | + ) ]; |
|
| 248 | + } elseif ($field_name == 'CNT_ISO') { |
|
| 249 | + $country_name_field = EEM_Country::instance()->field_settings_for('CNT_name'); |
|
| 250 | + $csv_row[ __( |
|
| 251 | + 'Country', |
|
| 252 | + 'event_espresso' |
|
| 253 | + ) ] = $attendee_row[ $country_name_field->get_qualified_column() ]; |
|
| 254 | + } else { |
|
| 255 | + $csv_row[ $field_obj->get_nicename() ] = $attendee_row[ $field_obj->get_qualified_column() ]; |
|
| 256 | + } |
|
| 257 | + } |
|
| 258 | + $csv_data[] = $csv_row; |
|
| 259 | + } |
|
| 260 | + |
|
| 261 | + $filename = $this->generate_filename('contact-list-report'); |
|
| 262 | + |
|
| 263 | + $handle = $this->EE_CSV->begin_sending_csv($filename); |
|
| 264 | + $this->EE_CSV->write_data_array_to_csv($handle, $csv_data); |
|
| 265 | + $this->EE_CSV->end_sending_csv($handle); |
|
| 266 | + } |
|
| 267 | + |
|
| 268 | + |
|
| 269 | + /** |
|
| 270 | + * @Export data for ALL attendees |
|
| 271 | + * @access public |
|
| 272 | + * @return void |
|
| 273 | + */ |
|
| 274 | + public function export_attendees() |
|
| 275 | + { |
|
| 276 | + |
|
| 277 | + $states_that_have_an_attendee = EEM_State::instance()->get_all( |
|
| 278 | + array(0 => array('Attendee.ATT_ID' => array('IS NOT NULL'))) |
|
| 279 | + ); |
|
| 280 | + $countries_that_have_an_attendee = EEM_Country::instance()->get_all( |
|
| 281 | + array(0 => array('Attendee.ATT_ID' => array('IS NOT NULL'))) |
|
| 282 | + ); |
|
| 283 | + // $states_to_export_query_params |
|
| 284 | + $models_to_export = array( |
|
| 285 | + 'Country' => array(array('CNT_ISO' => array('IN', array_keys($countries_that_have_an_attendee)))), |
|
| 286 | + 'State' => array(array('STA_ID' => array('IN', array_keys($states_that_have_an_attendee)))), |
|
| 287 | + 'Attendee' => array(), |
|
| 288 | + ); |
|
| 289 | + |
|
| 290 | + |
|
| 291 | + $model_data = $this->_get_export_data_for_models($models_to_export); |
|
| 292 | + $filename = $this->generate_filename('all-attendees'); |
|
| 293 | + |
|
| 294 | + if (! $this->EE_CSV->export_multiple_model_data_to_csv($filename, $model_data)) { |
|
| 295 | + EE_Error::add_error( |
|
| 296 | + __( |
|
| 297 | + 'An error occurred and the Attendee data could not be exported from the database.', |
|
| 298 | + 'event_espresso' |
|
| 299 | + ), |
|
| 300 | + __FILE__, |
|
| 301 | + __FUNCTION__, |
|
| 302 | + __LINE__ |
|
| 303 | + ); |
|
| 304 | + } |
|
| 305 | + } |
|
| 306 | + |
|
| 307 | + /** |
|
| 308 | + * Shortcut for preparing a database result for display |
|
| 309 | + * |
|
| 310 | + * @param EEM_Base $model |
|
| 311 | + * @param string $field_name |
|
| 312 | + * @param string $raw_db_value |
|
| 313 | + * @param boolean|string $pretty_schema true to display pretty, a string to use a specific "Schema", or false to |
|
| 314 | + * NOT display pretty |
|
| 315 | + * @return string |
|
| 316 | + */ |
|
| 317 | + protected function _prepare_value_from_db_for_display($model, $field_name, $raw_db_value, $pretty_schema = true) |
|
| 318 | + { |
|
| 319 | + $field_obj = $model->field_settings_for($field_name); |
|
| 320 | + $value_on_model_obj = $field_obj->prepare_for_set_from_db($raw_db_value); |
|
| 321 | + if ($field_obj instanceof EE_Datetime_Field) { |
|
| 322 | + $field_obj->set_date_format( |
|
| 323 | + EE_CSV::instance()->get_date_format_for_csv($field_obj->get_date_format($pretty_schema)), |
|
| 324 | + $pretty_schema |
|
| 325 | + ); |
|
| 326 | + $field_obj->set_time_format( |
|
| 327 | + EE_CSV::instance()->get_time_format_for_csv($field_obj->get_time_format($pretty_schema)), |
|
| 328 | + $pretty_schema |
|
| 329 | + ); |
|
| 330 | + } |
|
| 331 | + if ($pretty_schema === true) { |
|
| 332 | + return $field_obj->prepare_for_pretty_echoing($value_on_model_obj); |
|
| 333 | + } elseif (is_string($pretty_schema)) { |
|
| 334 | + return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema); |
|
| 335 | + } else { |
|
| 336 | + return $field_obj->prepare_for_get($value_on_model_obj); |
|
| 337 | + } |
|
| 338 | + } |
|
| 339 | + |
|
| 340 | + /** |
|
| 341 | + * Export a custom CSV of registration info including: A bunch of the reg fields, the time of the event, the price |
|
| 342 | + * name, and the questions associated with the registrations |
|
| 343 | + * |
|
| 344 | + * @param int $event_id |
|
| 345 | + */ |
|
| 346 | + public function report_registrations_for_event($event_id = null) |
|
| 347 | + { |
|
| 348 | + $reg_fields_to_include = array( |
|
| 349 | + 'TXN_ID', |
|
| 350 | + 'ATT_ID', |
|
| 351 | + 'REG_ID', |
|
| 352 | + 'REG_date', |
|
| 353 | + 'REG_code', |
|
| 354 | + 'REG_count', |
|
| 355 | + 'REG_final_price', |
|
| 356 | + |
|
| 357 | + ); |
|
| 358 | + $att_fields_to_include = array( |
|
| 359 | + 'ATT_fname', |
|
| 360 | + 'ATT_lname', |
|
| 361 | + 'ATT_email', |
|
| 362 | + 'ATT_address', |
|
| 363 | + 'ATT_address2', |
|
| 364 | + 'ATT_city', |
|
| 365 | + 'STA_ID', |
|
| 366 | + 'CNT_ISO', |
|
| 367 | + 'ATT_zip', |
|
| 368 | + 'ATT_phone', |
|
| 369 | + ); |
|
| 370 | + |
|
| 371 | + $registrations_csv_ready_array = array(); |
|
| 372 | + $reg_model = EE_Registry::instance()->load_model('Registration'); |
|
| 373 | + $query_params = apply_filters( |
|
| 374 | + 'FHEE__EE_Export__report_registration_for_event', |
|
| 375 | + array( |
|
| 376 | + array( |
|
| 377 | + 'OR' => array( |
|
| 378 | + // don't include registrations from failed or abandoned transactions... |
|
| 379 | + 'Transaction.STS_ID' => array( |
|
| 380 | + 'NOT IN', |
|
| 381 | + array(EEM_Transaction::failed_status_code, EEM_Transaction::abandoned_status_code), |
|
| 382 | + ), |
|
| 383 | + // unless the registration is approved, in which case include it regardless of transaction status |
|
| 384 | + 'STS_ID' => EEM_Registration::status_id_approved, |
|
| 385 | + ), |
|
| 386 | + 'Ticket.TKT_deleted' => array('IN', array(true, false)), |
|
| 387 | + ), |
|
| 388 | + 'order_by' => array('Transaction.TXN_ID' => 'asc', 'REG_count' => 'asc'), |
|
| 389 | + 'force_join' => array('Transaction', 'Ticket', 'Attendee'), |
|
| 390 | + 'caps' => EEM_Base::caps_read_admin, |
|
| 391 | + ), |
|
| 392 | + $event_id |
|
| 393 | + ); |
|
| 394 | + if ($event_id) { |
|
| 395 | + $query_params[0]['EVT_ID'] = $event_id; |
|
| 396 | + } else { |
|
| 397 | + $query_params['force_join'][] = 'Event'; |
|
| 398 | + } |
|
| 399 | + $registration_rows = $reg_model->get_all_wpdb_results($query_params); |
|
| 400 | + // get all questions which relate to someone in this group |
|
| 401 | + $registration_ids = array(); |
|
| 402 | + foreach ($registration_rows as $reg_row) { |
|
| 403 | + $registration_ids[] = intval($reg_row['Registration.REG_ID']); |
|
| 404 | + } |
|
| 405 | + // EEM_Question::instance()->show_next_x_db_queries(); |
|
| 406 | + $questions_for_these_regs_rows = EEM_Question::instance()->get_all_wpdb_results( |
|
| 407 | + array(array('Answer.REG_ID' => array('IN', $registration_ids))) |
|
| 408 | + ); |
|
| 409 | + foreach ($registration_rows as $reg_row) { |
|
| 410 | + if (is_array($reg_row)) { |
|
| 411 | + $reg_csv_array = array(); |
|
| 412 | + if (! $event_id) { |
|
| 413 | + // get the event's name and Id |
|
| 414 | + $reg_csv_array[ __('Event', 'event_espresso') ] = sprintf( |
|
| 415 | + __('%1$s (%2$s)', 'event_espresso'), |
|
| 416 | + $this->_prepare_value_from_db_for_display( |
|
| 417 | + EEM_Event::instance(), |
|
| 418 | + 'EVT_name', |
|
| 419 | + $reg_row['Event_CPT.post_title'] |
|
| 420 | + ), |
|
| 421 | + $reg_row['Event_CPT.ID'] |
|
| 422 | + ); |
|
| 423 | + } |
|
| 424 | + $is_primary_reg = $reg_row['Registration.REG_count'] == '1' ? true : false; |
|
| 425 | + /*@var $reg_row EE_Registration */ |
|
| 426 | + foreach ($reg_fields_to_include as $field_name) { |
|
| 427 | + $field = $reg_model->field_settings_for($field_name); |
|
| 428 | + if ($field_name == 'REG_final_price') { |
|
| 429 | + $value = $this->_prepare_value_from_db_for_display( |
|
| 430 | + $reg_model, |
|
| 431 | + $field_name, |
|
| 432 | + $reg_row['Registration.REG_final_price'], |
|
| 433 | + 'localized_float' |
|
| 434 | + ); |
|
| 435 | + } elseif ($field_name == 'REG_count') { |
|
| 436 | + $value = sprintf( |
|
| 437 | + __('%s of %s', 'event_espresso'), |
|
| 438 | + $this->_prepare_value_from_db_for_display( |
|
| 439 | + $reg_model, |
|
| 440 | + 'REG_count', |
|
| 441 | + $reg_row['Registration.REG_count'] |
|
| 442 | + ), |
|
| 443 | + $this->_prepare_value_from_db_for_display( |
|
| 444 | + $reg_model, |
|
| 445 | + 'REG_group_size', |
|
| 446 | + $reg_row['Registration.REG_group_size'] |
|
| 447 | + ) |
|
| 448 | + ); |
|
| 449 | + } elseif ($field_name == 'REG_date') { |
|
| 450 | + $value = $this->_prepare_value_from_db_for_display( |
|
| 451 | + $reg_model, |
|
| 452 | + $field_name, |
|
| 453 | + $reg_row['Registration.REG_date'], |
|
| 454 | + 'no_html' |
|
| 455 | + ); |
|
| 456 | + } else { |
|
| 457 | + $value = $this->_prepare_value_from_db_for_display( |
|
| 458 | + $reg_model, |
|
| 459 | + $field_name, |
|
| 460 | + $reg_row[ $field->get_qualified_column() ] |
|
| 461 | + ); |
|
| 462 | + } |
|
| 463 | + $reg_csv_array[ $this->_get_column_name_for_field($field) ] = $value; |
|
| 464 | + if ($field_name == 'REG_final_price') { |
|
| 465 | + // add a column named Currency after the final price |
|
| 466 | + $reg_csv_array[ __("Currency", "event_espresso") ] = EE_Config::instance()->currency->code; |
|
| 467 | + } |
|
| 468 | + } |
|
| 469 | + // get pretty status |
|
| 470 | + $stati = EEM_Status::instance()->localized_status( |
|
| 471 | + array( |
|
| 472 | + $reg_row['Registration.STS_ID'] => __('unknown', 'event_espresso'), |
|
| 473 | + $reg_row['TransactionTable.STS_ID'] => __('unknown', 'event_espresso'), |
|
| 474 | + ), |
|
| 475 | + false, |
|
| 476 | + 'sentence' |
|
| 477 | + ); |
|
| 478 | + $reg_csv_array[ __( |
|
| 479 | + "Registration Status", |
|
| 480 | + 'event_espresso' |
|
| 481 | + ) ] = $stati[ $reg_row['Registration.STS_ID'] ]; |
|
| 482 | + // get pretty trnasaction status |
|
| 483 | + $reg_csv_array[ __( |
|
| 484 | + "Transaction Status", |
|
| 485 | + 'event_espresso' |
|
| 486 | + ) ] = $stati[ $reg_row['TransactionTable.STS_ID'] ]; |
|
| 487 | + $reg_csv_array[ __('Transaction Amount Due', 'event_espresso') ] = $is_primary_reg |
|
| 488 | + ? $this->_prepare_value_from_db_for_display( |
|
| 489 | + EEM_Transaction::instance(), |
|
| 490 | + 'TXN_total', |
|
| 491 | + $reg_row['TransactionTable.TXN_total'], |
|
| 492 | + 'localized_float' |
|
| 493 | + ) : '0.00'; |
|
| 494 | + $reg_csv_array[ __('Amount Paid', 'event_espresso') ] = $is_primary_reg |
|
| 495 | + ? $this->_prepare_value_from_db_for_display( |
|
| 496 | + EEM_Transaction::instance(), |
|
| 497 | + 'TXN_paid', |
|
| 498 | + $reg_row['TransactionTable.TXN_paid'], |
|
| 499 | + 'localized_float' |
|
| 500 | + ) : '0.00'; |
|
| 501 | + $payment_methods = array(); |
|
| 502 | + $gateway_txn_ids_etc = array(); |
|
| 503 | + $payment_times = array(); |
|
| 504 | + if ($is_primary_reg && $reg_row['TransactionTable.TXN_ID']) { |
|
| 505 | + $payments_info = EEM_Payment::instance()->get_all_wpdb_results( |
|
| 506 | + array( |
|
| 507 | + array( |
|
| 508 | + 'TXN_ID' => $reg_row['TransactionTable.TXN_ID'], |
|
| 509 | + 'STS_ID' => EEM_Payment::status_id_approved, |
|
| 510 | + ), |
|
| 511 | + 'force_join' => array('Payment_Method'), |
|
| 512 | + ), |
|
| 513 | + ARRAY_A, |
|
| 514 | + 'Payment_Method.PMD_admin_name as name, Payment.PAY_txn_id_chq_nmbr as gateway_txn_id, Payment.PAY_timestamp as payment_time' |
|
| 515 | + ); |
|
| 516 | + |
|
| 517 | + foreach ($payments_info as $payment_method_and_gateway_txn_id) { |
|
| 518 | + $payment_methods[] = isset($payment_method_and_gateway_txn_id['name']) |
|
| 519 | + ? $payment_method_and_gateway_txn_id['name'] : __('Unknown', 'event_espresso'); |
|
| 520 | + $gateway_txn_ids_etc[] = isset($payment_method_and_gateway_txn_id['gateway_txn_id']) |
|
| 521 | + ? $payment_method_and_gateway_txn_id['gateway_txn_id'] : ''; |
|
| 522 | + $payment_times[] = isset($payment_method_and_gateway_txn_id['payment_time']) |
|
| 523 | + ? $payment_method_and_gateway_txn_id['payment_time'] : ''; |
|
| 524 | + } |
|
| 525 | + } |
|
| 526 | + $reg_csv_array[ __('Payment Date(s)', 'event_espresso') ] = implode(',', $payment_times); |
|
| 527 | + $reg_csv_array[ __('Payment Method(s)', 'event_espresso') ] = implode(",", $payment_methods); |
|
| 528 | + $reg_csv_array[ __('Gateway Transaction ID(s)', 'event_espresso') ] = implode( |
|
| 529 | + ',', |
|
| 530 | + $gateway_txn_ids_etc |
|
| 531 | + ); |
|
| 532 | + |
|
| 533 | + // get whether or not the user has checked in |
|
| 534 | + $reg_csv_array[ __("Check-Ins", "event_espresso") ] = $reg_model->count_related( |
|
| 535 | + $reg_row['Registration.REG_ID'], |
|
| 536 | + 'Checkin' |
|
| 537 | + ); |
|
| 538 | + // get ticket of registration and its price |
|
| 539 | + $ticket_model = EE_Registry::instance()->load_model('Ticket'); |
|
| 540 | + if ($reg_row['Ticket.TKT_ID']) { |
|
| 541 | + $ticket_name = $this->_prepare_value_from_db_for_display( |
|
| 542 | + $ticket_model, |
|
| 543 | + 'TKT_name', |
|
| 544 | + $reg_row['Ticket.TKT_name'] |
|
| 545 | + ); |
|
| 546 | + $datetimes_strings = array(); |
|
| 547 | + foreach ( |
|
| 548 | + EEM_Datetime::instance()->get_all_wpdb_results( |
|
| 549 | + array( |
|
| 550 | + array('Ticket.TKT_ID' => $reg_row['Ticket.TKT_ID']), |
|
| 551 | + 'order_by' => array('DTT_EVT_start' => 'ASC'), |
|
| 552 | + 'default_where_conditions' => 'none', |
|
| 553 | + ) |
|
| 554 | + ) as $datetime |
|
| 555 | + ) { |
|
| 556 | + $datetimes_strings[] = $this->_prepare_value_from_db_for_display( |
|
| 557 | + EEM_Datetime::instance(), |
|
| 558 | + 'DTT_EVT_start', |
|
| 559 | + $datetime['Datetime.DTT_EVT_start'] |
|
| 560 | + ); |
|
| 561 | + } |
|
| 562 | + } else { |
|
| 563 | + $ticket_name = __('Unknown', 'event_espresso'); |
|
| 564 | + $datetimes_strings = array(__('Unknown', 'event_espresso')); |
|
| 565 | + } |
|
| 566 | + $reg_csv_array[ $ticket_model->field_settings_for('TKT_name')->get_nicename() ] = $ticket_name; |
|
| 567 | + $reg_csv_array[ __("Datetimes of Ticket", "event_espresso") ] = implode(", ", $datetimes_strings); |
|
| 568 | + // get datetime(s) of registration |
|
| 569 | + |
|
| 570 | + // add attendee columns |
|
| 571 | + foreach ($att_fields_to_include as $att_field_name) { |
|
| 572 | + $field_obj = EEM_Attendee::instance()->field_settings_for($att_field_name); |
|
| 573 | + if ($reg_row['Attendee_CPT.ID']) { |
|
| 574 | + if ($att_field_name == 'STA_ID') { |
|
| 575 | + $value = EEM_State::instance()->get_var( |
|
| 576 | + array(array('STA_ID' => $reg_row['Attendee_Meta.STA_ID'])), |
|
| 577 | + 'STA_name' |
|
| 578 | + ); |
|
| 579 | + } elseif ($att_field_name == 'CNT_ISO') { |
|
| 580 | + $value = EEM_Country::instance()->get_var( |
|
| 581 | + array(array('CNT_ISO' => $reg_row['Attendee_Meta.CNT_ISO'])), |
|
| 582 | + 'CNT_name' |
|
| 583 | + ); |
|
| 584 | + } else { |
|
| 585 | + $value = $this->_prepare_value_from_db_for_display( |
|
| 586 | + EEM_Attendee::instance(), |
|
| 587 | + $att_field_name, |
|
| 588 | + $reg_row[ $field_obj->get_qualified_column() ] |
|
| 589 | + ); |
|
| 590 | + } |
|
| 591 | + } else { |
|
| 592 | + $value = ''; |
|
| 593 | + } |
|
| 594 | + |
|
| 595 | + $reg_csv_array[ $this->_get_column_name_for_field($field_obj) ] = $value; |
|
| 596 | + } |
|
| 597 | + |
|
| 598 | + // make sure each registration has the same questions in the same order |
|
| 599 | + foreach ($questions_for_these_regs_rows as $question_row) { |
|
| 600 | + if (! isset($reg_csv_array[ $question_row['Question.QST_admin_label'] ])) { |
|
| 601 | + $reg_csv_array[ $question_row['Question.QST_admin_label'] ] = null; |
|
| 602 | + } |
|
| 603 | + } |
|
| 604 | + // now fill out the questions THEY answered |
|
| 605 | + foreach ( |
|
| 606 | + EEM_Answer::instance()->get_all_wpdb_results( |
|
| 607 | + array(array('REG_ID' => $reg_row['Registration.REG_ID']), 'force_join' => array('Question')) |
|
| 608 | + ) as $answer_row |
|
| 609 | + ) { |
|
| 610 | + /* @var $answer EE_Answer */ |
|
| 611 | + if ($answer_row['Question.QST_ID']) { |
|
| 612 | + $question_label = $this->_prepare_value_from_db_for_display( |
|
| 613 | + EEM_Question::instance(), |
|
| 614 | + 'QST_admin_label', |
|
| 615 | + $answer_row['Question.QST_admin_label'] |
|
| 616 | + ); |
|
| 617 | + } else { |
|
| 618 | + $question_label = sprintf(__('Question $s', 'event_espresso'), $answer_row['Answer.QST_ID']); |
|
| 619 | + } |
|
| 620 | + if (isset($answer_row['Question.QST_type']) && $answer_row['Question.QST_type'] == EEM_Question::QST_type_state) { |
|
| 621 | + $reg_csv_array[ $question_label ] = EEM_State::instance()->get_state_name_by_ID( |
|
| 622 | + $answer_row['Answer.ANS_value'] |
|
| 623 | + ); |
|
| 624 | + } else { |
|
| 625 | + $reg_csv_array[ $question_label ] = $this->_prepare_value_from_db_for_display( |
|
| 626 | + EEM_Answer::instance(), |
|
| 627 | + 'ANS_value', |
|
| 628 | + $answer_row['Answer.ANS_value'] |
|
| 629 | + ); |
|
| 630 | + } |
|
| 631 | + } |
|
| 632 | + $registrations_csv_ready_array[] = apply_filters( |
|
| 633 | + 'FHEE__EE_Export__report_registrations__reg_csv_array', |
|
| 634 | + $reg_csv_array, |
|
| 635 | + $reg_row |
|
| 636 | + ); |
|
| 637 | + } |
|
| 638 | + } |
|
| 639 | + |
|
| 640 | + // if we couldn't export anything, we want to at least show the column headers |
|
| 641 | + if (empty($registrations_csv_ready_array)) { |
|
| 642 | + $reg_csv_array = array(); |
|
| 643 | + $model_and_fields_to_include = array( |
|
| 644 | + 'Registration' => $reg_fields_to_include, |
|
| 645 | + 'Attendee' => $att_fields_to_include, |
|
| 646 | + ); |
|
| 647 | + foreach ($model_and_fields_to_include as $model_name => $field_list) { |
|
| 648 | + $model = EE_Registry::instance()->load_model($model_name); |
|
| 649 | + foreach ($field_list as $field_name) { |
|
| 650 | + $field = $model->field_settings_for($field_name); |
|
| 651 | + $reg_csv_array[ $this->_get_column_name_for_field( |
|
| 652 | + $field |
|
| 653 | + ) ] = null;// $registration->get($field->get_name()); |
|
| 654 | + } |
|
| 655 | + } |
|
| 656 | + $registrations_csv_ready_array [] = $reg_csv_array; |
|
| 657 | + } |
|
| 658 | + if ($event_id) { |
|
| 659 | + $event_slug = EEM_Event::instance()->get_var(array(array('EVT_ID' => $event_id)), 'EVT_slug'); |
|
| 660 | + if (! $event_slug) { |
|
| 661 | + $event_slug = __('unknown', 'event_espresso'); |
|
| 662 | + } |
|
| 663 | + } else { |
|
| 664 | + $event_slug = __('all', 'event_espresso'); |
|
| 665 | + } |
|
| 666 | + $filename = sprintf("registrations-for-%s", $event_slug); |
|
| 667 | + |
|
| 668 | + $handle = $this->EE_CSV->begin_sending_csv($filename); |
|
| 669 | + $this->EE_CSV->write_data_array_to_csv($handle, $registrations_csv_ready_array); |
|
| 670 | + $this->EE_CSV->end_sending_csv($handle); |
|
| 671 | + } |
|
| 672 | + |
|
| 673 | + /** |
|
| 674 | + * Gets the 'normal' column named for fields |
|
| 675 | + * |
|
| 676 | + * @param EE_Model_Field_Base $field |
|
| 677 | + * @return string |
|
| 678 | + */ |
|
| 679 | + protected function _get_column_name_for_field(EE_Model_Field_Base $field) |
|
| 680 | + { |
|
| 681 | + return $field->get_nicename() . "[" . $field->get_name() . "]"; |
|
| 682 | + } |
|
| 683 | + |
|
| 684 | + |
|
| 685 | + /** |
|
| 686 | + * @Export data for ALL events |
|
| 687 | + * @access public |
|
| 688 | + * @return void |
|
| 689 | + */ |
|
| 690 | + public function export_categories() |
|
| 691 | + { |
|
| 692 | + // are any Event IDs set? |
|
| 693 | + $query_params = array(); |
|
| 694 | + if (isset($this->_req_data['EVT_CAT_ID'])) { |
|
| 695 | + // do we have an array of IDs ? |
|
| 696 | + if (is_array($this->_req_data['EVT_CAT_ID'])) { |
|
| 697 | + // generate an "IN (CSV)" where clause |
|
| 698 | + $EVT_CAT_IDs = array_map('sanitize_text_field', $this->_req_data['EVT_CAT_ID']); |
|
| 699 | + $filename = 'event-categories'; |
|
| 700 | + $query_params[0]['term_taxonomy_id'] = array('IN', $EVT_CAT_IDs); |
|
| 701 | + } else { |
|
| 702 | + // generate regular where = clause |
|
| 703 | + $EVT_CAT_ID = absint($this->_req_data['EVT_CAT_ID']); |
|
| 704 | + $filename = 'event-category#' . $EVT_CAT_ID; |
|
| 705 | + $query_params[0]['term_taxonomy_id'] = $EVT_CAT_ID; |
|
| 706 | + } |
|
| 707 | + } else { |
|
| 708 | + // no IDs means we will d/l the entire table |
|
| 709 | + $filename = 'all-categories'; |
|
| 710 | + } |
|
| 711 | + |
|
| 712 | + $tables_to_export = array( |
|
| 713 | + 'Term_Taxonomy' => $query_params, |
|
| 714 | + ); |
|
| 715 | + |
|
| 716 | + $table_data = $this->_get_export_data_for_models($tables_to_export); |
|
| 717 | + $filename = $this->generate_filename($filename); |
|
| 718 | + |
|
| 719 | + if (! $this->EE_CSV->export_multiple_model_data_to_csv($filename, $table_data)) { |
|
| 720 | + EE_Error::add_error( |
|
| 721 | + __( |
|
| 722 | + 'An error occurred and the Category details could not be exported from the database.', |
|
| 723 | + 'event_espresso' |
|
| 724 | + ), |
|
| 725 | + __FILE__, |
|
| 726 | + __FUNCTION__, |
|
| 727 | + __LINE__ |
|
| 728 | + ); |
|
| 729 | + } |
|
| 730 | + } |
|
| 731 | + |
|
| 732 | + |
|
| 733 | + /** |
|
| 734 | + * @process export name to create a suitable filename |
|
| 735 | + * @access private |
|
| 736 | + * @param string - export_name |
|
| 737 | + * @return string on success, FALSE on fail |
|
| 738 | + */ |
|
| 739 | + private function generate_filename($export_name = '') |
|
| 740 | + { |
|
| 741 | + if ($export_name != '') { |
|
| 742 | + $filename = get_bloginfo('name') . '-' . $export_name; |
|
| 743 | + $filename = sanitize_key($filename) . '-' . $this->today; |
|
| 744 | + return $filename; |
|
| 745 | + } else { |
|
| 746 | + EE_Error::add_error(__("No filename was provided", "event_espresso"), __FILE__, __FUNCTION__, __LINE__); |
|
| 747 | + } |
|
| 748 | + return false; |
|
| 749 | + } |
|
| 750 | + |
|
| 751 | + |
|
| 752 | + /** |
|
| 753 | + * @recursive function for exporting table data and merging the results with the next results |
|
| 754 | + * @access private |
|
| 755 | + * @param array $models_to_export keys are model names (eg 'Event', 'Attendee', etc.) and values are arrays of |
|
| 756 | + * query params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 757 | + * @return array on success, FALSE on fail |
|
| 758 | + */ |
|
| 759 | + private function _get_export_data_for_models($models_to_export = array()) |
|
| 760 | + { |
|
| 761 | + $table_data = false; |
|
| 762 | + if (is_array($models_to_export)) { |
|
| 763 | + foreach ($models_to_export as $model_name => $query_params) { |
|
| 764 | + // check for a numerically-indexed array. in that case, $model_name is the value!! |
|
| 765 | + if (is_int($model_name)) { |
|
| 766 | + $model_name = $query_params; |
|
| 767 | + $query_params = array(); |
|
| 768 | + } |
|
| 769 | + $model = EE_Registry::instance()->load_model($model_name); |
|
| 770 | + $model_objects = $model->get_all($query_params); |
|
| 771 | + |
|
| 772 | + $table_data[ $model_name ] = array(); |
|
| 773 | + foreach ($model_objects as $model_object) { |
|
| 774 | + $model_data_array = array(); |
|
| 775 | + $fields = $model->field_settings(); |
|
| 776 | + foreach ($fields as $field) { |
|
| 777 | + $column_name = $field->get_nicename() . "[" . $field->get_name() . "]"; |
|
| 778 | + if ($field instanceof EE_Datetime_Field) { |
|
| 779 | + // $field->set_date_format('Y-m-d'); |
|
| 780 | + // $field->set_time_format('H:i:s'); |
|
| 781 | + $model_data_array[ $column_name ] = $model_object->get_datetime( |
|
| 782 | + $field->get_name(), |
|
| 783 | + 'Y-m-d', |
|
| 784 | + 'H:i:s' |
|
| 785 | + ); |
|
| 786 | + } else { |
|
| 787 | + $model_data_array[ $column_name ] = $model_object->get($field->get_name()); |
|
| 788 | + } |
|
| 789 | + } |
|
| 790 | + $table_data[ $model_name ][] = $model_data_array; |
|
| 791 | + } |
|
| 792 | + } |
|
| 793 | + } |
|
| 794 | + return $table_data; |
|
| 795 | + } |
|
| 796 | 796 | } |
@@ -10,875 +10,875 @@ |
||
| 10 | 10 | class EE_Message extends EE_Base_Class implements EEI_Admin_Links |
| 11 | 11 | { |
| 12 | 12 | |
| 13 | - /** |
|
| 14 | - * @deprecated 4.9.0 Added for backward compat with add-on's |
|
| 15 | - * @type null |
|
| 16 | - */ |
|
| 17 | - public $template_pack; |
|
| 18 | - |
|
| 19 | - /** |
|
| 20 | - * @deprecated 4.9.0 Added for backward compat with add-on's |
|
| 21 | - * @type null |
|
| 22 | - */ |
|
| 23 | - public $template_variation; |
|
| 24 | - |
|
| 25 | - /** |
|
| 26 | - * @deprecated 4.9.0 Added for backward compat with add-on's |
|
| 27 | - * @type string |
|
| 28 | - */ |
|
| 29 | - public $content = ''; |
|
| 30 | - |
|
| 31 | - |
|
| 32 | - /** |
|
| 33 | - * @type EE_messenger $_messenger |
|
| 34 | - */ |
|
| 35 | - protected $_messenger = null; |
|
| 36 | - |
|
| 37 | - /** |
|
| 38 | - * @type EE_message_type $_message_type |
|
| 39 | - */ |
|
| 40 | - protected $_message_type = null; |
|
| 41 | - |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * @param array $props_n_values |
|
| 45 | - * @param string $timezone |
|
| 46 | - * @param array $date_formats incoming date formats in an array. First value is the date_format, second is time |
|
| 47 | - * format. |
|
| 48 | - * @return EE_Message |
|
| 49 | - */ |
|
| 50 | - public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array()) |
|
| 51 | - { |
|
| 52 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__); |
|
| 53 | - // if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db. |
|
| 54 | - if (! $has_object) { |
|
| 55 | - EE_Registry::instance()->load_helper('URL'); |
|
| 56 | - $props_n_values['MSG_token'] = EEH_URL::generate_unique_token(); |
|
| 57 | - } |
|
| 58 | - return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
| 59 | - } |
|
| 60 | - |
|
| 61 | - |
|
| 62 | - /** |
|
| 63 | - * @param array $props_n_values |
|
| 64 | - * @param string $timezone |
|
| 65 | - * @return EE_Message |
|
| 66 | - */ |
|
| 67 | - public static function new_instance_from_db($props_n_values = array(), $timezone = '') |
|
| 68 | - { |
|
| 69 | - return new self($props_n_values, true, $timezone); |
|
| 70 | - } |
|
| 71 | - |
|
| 72 | - |
|
| 73 | - /** |
|
| 74 | - * Gets MSG_token |
|
| 75 | - * |
|
| 76 | - * @return int |
|
| 77 | - */ |
|
| 78 | - public function MSG_token() |
|
| 79 | - { |
|
| 80 | - return $this->get('MSG_token'); |
|
| 81 | - } |
|
| 82 | - |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * Sets MSG_token |
|
| 86 | - * |
|
| 87 | - * @param int $MSG_token |
|
| 88 | - */ |
|
| 89 | - public function set_MSG_token($MSG_token) |
|
| 90 | - { |
|
| 91 | - $this->set('MSG_token', $MSG_token); |
|
| 92 | - } |
|
| 93 | - |
|
| 94 | - |
|
| 95 | - /** |
|
| 96 | - * Gets GRP_ID |
|
| 97 | - * |
|
| 98 | - * @return int |
|
| 99 | - */ |
|
| 100 | - public function GRP_ID() |
|
| 101 | - { |
|
| 102 | - return $this->get('GRP_ID'); |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - |
|
| 106 | - /** |
|
| 107 | - * Sets GRP_ID |
|
| 108 | - * |
|
| 109 | - * @param int $GRP_ID |
|
| 110 | - */ |
|
| 111 | - public function set_GRP_ID($GRP_ID) |
|
| 112 | - { |
|
| 113 | - $this->set('GRP_ID', $GRP_ID); |
|
| 114 | - } |
|
| 115 | - |
|
| 116 | - |
|
| 117 | - /** |
|
| 118 | - * Gets TXN_ID |
|
| 119 | - * |
|
| 120 | - * @return int |
|
| 121 | - */ |
|
| 122 | - public function TXN_ID() |
|
| 123 | - { |
|
| 124 | - return $this->get('TXN_ID'); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - |
|
| 128 | - /** |
|
| 129 | - * Sets TXN_ID |
|
| 130 | - * |
|
| 131 | - * @param int $TXN_ID |
|
| 132 | - */ |
|
| 133 | - public function set_TXN_ID($TXN_ID) |
|
| 134 | - { |
|
| 135 | - $this->set('TXN_ID', $TXN_ID); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - |
|
| 139 | - /** |
|
| 140 | - * Gets messenger |
|
| 141 | - * |
|
| 142 | - * @return string |
|
| 143 | - */ |
|
| 144 | - public function messenger() |
|
| 145 | - { |
|
| 146 | - return $this->get('MSG_messenger'); |
|
| 147 | - } |
|
| 148 | - |
|
| 149 | - |
|
| 150 | - /** |
|
| 151 | - * Sets messenger |
|
| 152 | - * |
|
| 153 | - * @param string $messenger |
|
| 154 | - */ |
|
| 155 | - public function set_messenger($messenger) |
|
| 156 | - { |
|
| 157 | - $this->set('MSG_messenger', $messenger); |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - |
|
| 161 | - /** |
|
| 162 | - * Returns corresponding messenger object for the set messenger on this message |
|
| 163 | - * |
|
| 164 | - * @return EE_messenger | null |
|
| 165 | - */ |
|
| 166 | - public function messenger_object() |
|
| 167 | - { |
|
| 168 | - return $this->_messenger; |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * Sets messenger |
|
| 174 | - * |
|
| 175 | - * @param EE_messenger $messenger |
|
| 176 | - */ |
|
| 177 | - public function set_messenger_object(EE_messenger $messenger) |
|
| 178 | - { |
|
| 179 | - $this->_messenger = $messenger; |
|
| 180 | - } |
|
| 181 | - |
|
| 182 | - |
|
| 183 | - /** |
|
| 184 | - * validates messenger |
|
| 185 | - * |
|
| 186 | - * @param bool $throw_exceptions |
|
| 187 | - * @return bool |
|
| 188 | - * @throws \EE_Error |
|
| 189 | - */ |
|
| 190 | - public function valid_messenger($throw_exceptions = false) |
|
| 191 | - { |
|
| 192 | - if ($this->_messenger instanceof EE_messenger) { |
|
| 193 | - return true; |
|
| 194 | - } |
|
| 195 | - if ($throw_exceptions) { |
|
| 196 | - throw new EE_Error( |
|
| 197 | - sprintf( |
|
| 198 | - __( |
|
| 199 | - 'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.', |
|
| 200 | - 'event_espresso' |
|
| 201 | - ), |
|
| 202 | - $this->messenger() |
|
| 203 | - ) |
|
| 204 | - ); |
|
| 205 | - } |
|
| 206 | - return false; |
|
| 207 | - } |
|
| 208 | - |
|
| 209 | - |
|
| 210 | - /** |
|
| 211 | - * This returns the set localized label for the messenger on this message. |
|
| 212 | - * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved |
|
| 213 | - * with this message. |
|
| 214 | - * |
|
| 215 | - * @param bool $plural whether to return the plural label or not. |
|
| 216 | - * @return string |
|
| 217 | - */ |
|
| 218 | - public function messenger_label($plural = false) |
|
| 219 | - { |
|
| 220 | - $label_type = $plural ? 'plural' : 'singular'; |
|
| 221 | - $messenger = $this->messenger_object(); |
|
| 222 | - return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger(); |
|
| 223 | - } |
|
| 224 | - |
|
| 225 | - |
|
| 226 | - /** |
|
| 227 | - * Gets message_type |
|
| 228 | - * |
|
| 229 | - * @return string |
|
| 230 | - */ |
|
| 231 | - public function message_type() |
|
| 232 | - { |
|
| 233 | - return $this->get('MSG_message_type'); |
|
| 234 | - } |
|
| 235 | - |
|
| 236 | - |
|
| 237 | - /** |
|
| 238 | - * Sets message_type |
|
| 239 | - * |
|
| 240 | - * @param string $message_type |
|
| 241 | - */ |
|
| 242 | - public function set_message_type($message_type) |
|
| 243 | - { |
|
| 244 | - $this->set('MSG_message_type', $message_type); |
|
| 245 | - } |
|
| 246 | - |
|
| 247 | - |
|
| 248 | - /** |
|
| 249 | - * Returns the message type object for the set message type on this message |
|
| 250 | - * |
|
| 251 | - * @return EE_message_type | null |
|
| 252 | - */ |
|
| 253 | - public function message_type_object() |
|
| 254 | - { |
|
| 255 | - return $this->_message_type; |
|
| 256 | - } |
|
| 257 | - |
|
| 258 | - |
|
| 259 | - /** |
|
| 260 | - * Sets message_type |
|
| 261 | - * |
|
| 262 | - * @param EE_message_type $message_type |
|
| 263 | - * @param bool $set_priority This indicates whether to set the priority to whatever the priority is on |
|
| 264 | - * the message type or not. |
|
| 265 | - */ |
|
| 266 | - public function set_message_type_object(EE_message_type $message_type, $set_priority = false) |
|
| 267 | - { |
|
| 268 | - $this->_message_type = $message_type; |
|
| 269 | - if ($set_priority) { |
|
| 270 | - $this->set_priority($this->_message_type->get_priority()); |
|
| 271 | - } |
|
| 272 | - } |
|
| 273 | - |
|
| 274 | - |
|
| 275 | - /** |
|
| 276 | - * validates message_type |
|
| 277 | - * |
|
| 278 | - * @param bool $throw_exceptions |
|
| 279 | - * @return bool |
|
| 280 | - * @throws \EE_Error |
|
| 281 | - */ |
|
| 282 | - public function valid_message_type($throw_exceptions = false) |
|
| 283 | - { |
|
| 284 | - if ($this->_message_type instanceof EE_message_type) { |
|
| 285 | - return true; |
|
| 286 | - } |
|
| 287 | - if ($throw_exceptions) { |
|
| 288 | - throw new EE_Error( |
|
| 289 | - sprintf( |
|
| 290 | - __( |
|
| 291 | - 'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.', |
|
| 292 | - 'event_espresso' |
|
| 293 | - ), |
|
| 294 | - $this->message_type() |
|
| 295 | - ) |
|
| 296 | - ); |
|
| 297 | - } |
|
| 298 | - return false; |
|
| 299 | - } |
|
| 300 | - |
|
| 301 | - |
|
| 302 | - /** |
|
| 303 | - * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects). |
|
| 304 | - * |
|
| 305 | - * @param bool $throw_exceptions |
|
| 306 | - * @return bool |
|
| 307 | - * @throws \EE_Error |
|
| 308 | - */ |
|
| 309 | - public function is_valid($throw_exceptions = false) |
|
| 310 | - { |
|
| 311 | - if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) { |
|
| 312 | - return true; |
|
| 313 | - } |
|
| 314 | - return false; |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - |
|
| 318 | - /** |
|
| 319 | - * This validates whether the internal messenger and message type objects are valid for sending. |
|
| 320 | - * Three checks are done: |
|
| 321 | - * 1. There is a valid messenger object. |
|
| 322 | - * 2. There is a valid message type object. |
|
| 323 | - * 3. The message type object is active for the messenger. |
|
| 324 | - * |
|
| 325 | - * @throws EE_Error But only if $throw_exceptions is set to true. |
|
| 326 | - * @param bool $throw_exceptions |
|
| 327 | - * @return bool |
|
| 328 | - */ |
|
| 329 | - public function is_valid_for_sending_or_generation($throw_exceptions = false) |
|
| 330 | - { |
|
| 331 | - $valid = false; |
|
| 332 | - if ($this->is_valid($throw_exceptions)) { |
|
| 333 | - /** @var EE_Message_Resource_Manager $message_resource_manager */ |
|
| 334 | - $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
| 335 | - $valid = $message_resource_manager->is_message_type_active_for_messenger( |
|
| 336 | - $this->messenger(), |
|
| 337 | - $this->message_type() |
|
| 338 | - ); |
|
| 339 | - if (! $valid && $throw_exceptions) { |
|
| 340 | - throw new EE_Error( |
|
| 341 | - sprintf( |
|
| 342 | - __( |
|
| 343 | - 'The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.', |
|
| 344 | - 'event_espresso' |
|
| 345 | - ), |
|
| 346 | - $this->message_type(), |
|
| 347 | - $this->messenger() |
|
| 348 | - ) |
|
| 349 | - ); |
|
| 350 | - } |
|
| 351 | - } |
|
| 352 | - return $valid; |
|
| 353 | - } |
|
| 354 | - |
|
| 355 | - |
|
| 356 | - /** |
|
| 357 | - * This returns the set localized label for the message type on this message. |
|
| 358 | - * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved |
|
| 359 | - * with this message. |
|
| 360 | - * |
|
| 361 | - * @param bool $plural whether to return the plural label or not. |
|
| 362 | - * @return string |
|
| 363 | - */ |
|
| 364 | - public function message_type_label($plural = false) |
|
| 365 | - { |
|
| 366 | - $label_type = $plural ? 'plural' : 'singular'; |
|
| 367 | - $message_type = $this->message_type_object(); |
|
| 368 | - return $message_type instanceof EE_message_type |
|
| 369 | - ? $message_type->label[ $label_type ] |
|
| 370 | - : str_replace( |
|
| 371 | - '_', |
|
| 372 | - ' ', |
|
| 373 | - $this->message_type() |
|
| 374 | - ); |
|
| 375 | - } |
|
| 376 | - |
|
| 377 | - |
|
| 378 | - /** |
|
| 379 | - * Gets context |
|
| 380 | - * |
|
| 381 | - * @return string |
|
| 382 | - */ |
|
| 383 | - public function context() |
|
| 384 | - { |
|
| 385 | - return $this->get('MSG_context'); |
|
| 386 | - } |
|
| 387 | - |
|
| 388 | - |
|
| 389 | - /** |
|
| 390 | - * This returns the corresponding localized label for the given context slug, if possible from installed message |
|
| 391 | - * types. Otherwise, this will just return the set context slug on this object. |
|
| 392 | - * |
|
| 393 | - * @return string |
|
| 394 | - */ |
|
| 395 | - public function context_label() |
|
| 396 | - { |
|
| 397 | - /** @type EE_Message_Resource_Manager $message_resource_manager */ |
|
| 398 | - $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
| 399 | - $contexts = $message_resource_manager->get_all_contexts(); |
|
| 400 | - return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context(); |
|
| 401 | - } |
|
| 402 | - |
|
| 403 | - |
|
| 404 | - /** |
|
| 405 | - * Sets context |
|
| 406 | - * |
|
| 407 | - * @param string $context |
|
| 408 | - */ |
|
| 409 | - public function set_context($context) |
|
| 410 | - { |
|
| 411 | - $this->set('MSG_context', $context); |
|
| 412 | - } |
|
| 413 | - |
|
| 414 | - |
|
| 415 | - /** |
|
| 416 | - * Gets recipient_ID |
|
| 417 | - * |
|
| 418 | - * @return int |
|
| 419 | - */ |
|
| 420 | - public function recipient_ID() |
|
| 421 | - { |
|
| 422 | - return $this->get('MSG_recipient_ID'); |
|
| 423 | - } |
|
| 424 | - |
|
| 425 | - |
|
| 426 | - /** |
|
| 427 | - * Sets recipient_ID |
|
| 428 | - * |
|
| 429 | - * @param string $recipient_ID |
|
| 430 | - */ |
|
| 431 | - public function set_recipient_ID($recipient_ID) |
|
| 432 | - { |
|
| 433 | - $this->set('MSG_recipient_ID', $recipient_ID); |
|
| 434 | - } |
|
| 435 | - |
|
| 436 | - |
|
| 437 | - /** |
|
| 438 | - * Gets recipient_type |
|
| 439 | - * |
|
| 440 | - * @return string |
|
| 441 | - */ |
|
| 442 | - public function recipient_type() |
|
| 443 | - { |
|
| 444 | - return $this->get('MSG_recipient_type'); |
|
| 445 | - } |
|
| 446 | - |
|
| 447 | - |
|
| 448 | - /** |
|
| 449 | - * Return the related object matching the recipient type and ID. |
|
| 450 | - * |
|
| 451 | - * @return EE_Base_Class | null |
|
| 452 | - */ |
|
| 453 | - public function recipient_object() |
|
| 454 | - { |
|
| 455 | - if (! $this->recipient_type() || ! $this->recipient_ID()) { |
|
| 456 | - return null; |
|
| 457 | - } |
|
| 458 | - |
|
| 459 | - return $this->get_first_related($this->recipient_type()); |
|
| 460 | - } |
|
| 461 | - |
|
| 462 | - |
|
| 463 | - /** |
|
| 464 | - * Sets recipient_type |
|
| 465 | - * |
|
| 466 | - * @param string $recipient_type |
|
| 467 | - */ |
|
| 468 | - public function set_recipient_type($recipient_type) |
|
| 469 | - { |
|
| 470 | - $this->set('MSG_recipient_type', $recipient_type); |
|
| 471 | - } |
|
| 472 | - |
|
| 473 | - |
|
| 474 | - /** |
|
| 475 | - * Gets content |
|
| 476 | - * |
|
| 477 | - * @return string |
|
| 478 | - */ |
|
| 479 | - public function content() |
|
| 480 | - { |
|
| 481 | - return $this->get('MSG_content'); |
|
| 482 | - } |
|
| 483 | - |
|
| 484 | - |
|
| 485 | - /** |
|
| 486 | - * Sets content |
|
| 487 | - * |
|
| 488 | - * @param string $content |
|
| 489 | - */ |
|
| 490 | - public function set_content($content) |
|
| 491 | - { |
|
| 492 | - $this->set('MSG_content', $content); |
|
| 493 | - } |
|
| 494 | - |
|
| 495 | - |
|
| 496 | - /** |
|
| 497 | - * Gets subject |
|
| 498 | - * |
|
| 499 | - * @return string |
|
| 500 | - */ |
|
| 501 | - public function subject() |
|
| 502 | - { |
|
| 503 | - return $this->get('MSG_subject'); |
|
| 504 | - } |
|
| 505 | - |
|
| 506 | - |
|
| 507 | - /** |
|
| 508 | - * Sets subject |
|
| 509 | - * |
|
| 510 | - * @param string $subject |
|
| 511 | - */ |
|
| 512 | - public function set_subject($subject) |
|
| 513 | - { |
|
| 514 | - $this->set('MSG_subject', $subject); |
|
| 515 | - } |
|
| 516 | - |
|
| 517 | - |
|
| 518 | - /** |
|
| 519 | - * Gets to |
|
| 520 | - * |
|
| 521 | - * @return string |
|
| 522 | - */ |
|
| 523 | - public function to() |
|
| 524 | - { |
|
| 525 | - $to = $this->get('MSG_to'); |
|
| 526 | - return empty($to) ? __('No recipient', 'event_espresso') : $to; |
|
| 527 | - } |
|
| 528 | - |
|
| 529 | - |
|
| 530 | - /** |
|
| 531 | - * Sets to |
|
| 532 | - * |
|
| 533 | - * @param string $to |
|
| 534 | - */ |
|
| 535 | - public function set_to($to) |
|
| 536 | - { |
|
| 537 | - $this->set('MSG_to', $to); |
|
| 538 | - } |
|
| 539 | - |
|
| 540 | - |
|
| 541 | - /** |
|
| 542 | - * Gets from |
|
| 543 | - * |
|
| 544 | - * @return string |
|
| 545 | - */ |
|
| 546 | - public function from() |
|
| 547 | - { |
|
| 548 | - return $this->get('MSG_from'); |
|
| 549 | - } |
|
| 550 | - |
|
| 551 | - |
|
| 552 | - /** |
|
| 553 | - * Sets from |
|
| 554 | - * |
|
| 555 | - * @param string $from |
|
| 556 | - */ |
|
| 557 | - public function set_from($from) |
|
| 558 | - { |
|
| 559 | - $this->set('MSG_from', $from); |
|
| 560 | - } |
|
| 561 | - |
|
| 562 | - |
|
| 563 | - /** |
|
| 564 | - * Gets priority |
|
| 565 | - * |
|
| 566 | - * @return int |
|
| 567 | - */ |
|
| 568 | - public function priority() |
|
| 569 | - { |
|
| 570 | - return $this->get('MSG_priority'); |
|
| 571 | - } |
|
| 572 | - |
|
| 573 | - |
|
| 574 | - /** |
|
| 575 | - * Sets priority |
|
| 576 | - * Note. Send Now Messengers always override any priority that may be set on a Message. So |
|
| 577 | - * this method calls the send_now method to verify that. |
|
| 578 | - * |
|
| 579 | - * @param int $priority |
|
| 580 | - */ |
|
| 581 | - public function set_priority($priority) |
|
| 582 | - { |
|
| 583 | - $priority = $this->send_now() ? EEM_Message::priority_high : $priority; |
|
| 584 | - parent::set('MSG_priority', $priority); |
|
| 585 | - } |
|
| 586 | - |
|
| 587 | - |
|
| 588 | - /** |
|
| 589 | - * Overrides parent::set method so we can capture any sets for priority. |
|
| 590 | - * |
|
| 591 | - * @param string $field_name |
|
| 592 | - * @param mixed $field_value |
|
| 593 | - * @param bool $use_default |
|
| 594 | - * @throws EE_Error |
|
| 595 | - * @see parent::set() for phpdocs |
|
| 596 | - */ |
|
| 597 | - public function set($field_name, $field_value, bool $use_default = false) |
|
| 598 | - { |
|
| 599 | - if ($field_name === 'MSG_priority') { |
|
| 600 | - $this->set_priority($field_value); |
|
| 601 | - } |
|
| 602 | - parent::set($field_name, $field_value, $use_default); |
|
| 603 | - } |
|
| 604 | - |
|
| 605 | - |
|
| 606 | - /** |
|
| 607 | - * @return bool |
|
| 608 | - * @throws \EE_Error |
|
| 609 | - */ |
|
| 610 | - public function send_now() |
|
| 611 | - { |
|
| 612 | - $send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high |
|
| 613 | - : $this->priority(); |
|
| 614 | - return $send_now === EEM_Message::priority_high ? true : false; |
|
| 615 | - } |
|
| 616 | - |
|
| 617 | - |
|
| 618 | - /** |
|
| 619 | - * Gets STS_ID |
|
| 620 | - * |
|
| 621 | - * @return string |
|
| 622 | - */ |
|
| 623 | - public function STS_ID() |
|
| 624 | - { |
|
| 625 | - return $this->get('STS_ID'); |
|
| 626 | - } |
|
| 627 | - |
|
| 628 | - |
|
| 629 | - /** |
|
| 630 | - * Sets STS_ID |
|
| 631 | - * |
|
| 632 | - * @param string $STS_ID |
|
| 633 | - */ |
|
| 634 | - public function set_STS_ID($STS_ID) |
|
| 635 | - { |
|
| 636 | - $this->set('STS_ID', $STS_ID); |
|
| 637 | - } |
|
| 638 | - |
|
| 639 | - |
|
| 640 | - /** |
|
| 641 | - * Gets created |
|
| 642 | - * |
|
| 643 | - * @return string |
|
| 644 | - */ |
|
| 645 | - public function created() |
|
| 646 | - { |
|
| 647 | - return $this->get('MSG_created'); |
|
| 648 | - } |
|
| 649 | - |
|
| 650 | - |
|
| 651 | - /** |
|
| 652 | - * Sets created |
|
| 653 | - * |
|
| 654 | - * @param string $created |
|
| 655 | - */ |
|
| 656 | - public function set_created($created) |
|
| 657 | - { |
|
| 658 | - $this->set('MSG_created', $created); |
|
| 659 | - } |
|
| 660 | - |
|
| 661 | - |
|
| 662 | - /** |
|
| 663 | - * Gets modified |
|
| 664 | - * |
|
| 665 | - * @return string |
|
| 666 | - */ |
|
| 667 | - public function modified() |
|
| 668 | - { |
|
| 669 | - return $this->get('MSG_modified'); |
|
| 670 | - } |
|
| 671 | - |
|
| 672 | - |
|
| 673 | - /** |
|
| 674 | - * Sets modified |
|
| 675 | - * |
|
| 676 | - * @param string $modified |
|
| 677 | - */ |
|
| 678 | - public function set_modified($modified) |
|
| 679 | - { |
|
| 680 | - $this->set('MSG_modified', $modified); |
|
| 681 | - } |
|
| 682 | - |
|
| 683 | - |
|
| 684 | - /** |
|
| 685 | - * Sets generation data for this message. |
|
| 686 | - * |
|
| 687 | - * @param mixed $data |
|
| 688 | - */ |
|
| 689 | - public function set_generation_data($data) |
|
| 690 | - { |
|
| 691 | - $this->set_field_or_extra_meta('MSG_generation_data', $data); |
|
| 692 | - } |
|
| 693 | - |
|
| 694 | - |
|
| 695 | - /** |
|
| 696 | - * Returns any set generation data for this message. |
|
| 697 | - * |
|
| 698 | - * @return mixed|null |
|
| 699 | - */ |
|
| 700 | - public function get_generation_data() |
|
| 701 | - { |
|
| 702 | - return $this->get_field_or_extra_meta('MSG_generation_data'); |
|
| 703 | - } |
|
| 704 | - |
|
| 705 | - |
|
| 706 | - /** |
|
| 707 | - * Gets any error message. |
|
| 708 | - * |
|
| 709 | - * @return mixed|null |
|
| 710 | - */ |
|
| 711 | - public function error_message() |
|
| 712 | - { |
|
| 713 | - return $this->get_field_or_extra_meta('MSG_error'); |
|
| 714 | - } |
|
| 715 | - |
|
| 716 | - |
|
| 717 | - /** |
|
| 718 | - * Sets an error message. |
|
| 719 | - * |
|
| 720 | - * @param $message |
|
| 721 | - * @return bool|int |
|
| 722 | - */ |
|
| 723 | - public function set_error_message($message) |
|
| 724 | - { |
|
| 725 | - return $this->set_field_or_extra_meta('MSG_error', $message); |
|
| 726 | - } |
|
| 727 | - |
|
| 728 | - |
|
| 729 | - /** |
|
| 730 | - * This retrieves the associated template pack with this message. |
|
| 731 | - * |
|
| 732 | - * @return EE_Messages_Template_Pack | null |
|
| 733 | - */ |
|
| 734 | - public function get_template_pack() |
|
| 735 | - { |
|
| 736 | - /** |
|
| 737 | - * This is deprecated functionality that will be removed eventually but included here now for backward compat. |
|
| 738 | - */ |
|
| 739 | - if (! empty($this->template_pack)) { |
|
| 740 | - return $this->template_pack; |
|
| 741 | - } |
|
| 742 | - /** @type EE_Message_Template_Group $grp */ |
|
| 743 | - $grp = $this->get_first_related('Message_Template_Group'); |
|
| 744 | - // if no group then let's try to get the first related group by internal messenger and message type (will use global grp). |
|
| 745 | - if (! $grp instanceof EE_Message_Template_Group) { |
|
| 746 | - $grp = EEM_Message_Template_Group::instance()->get_one( |
|
| 747 | - array( |
|
| 748 | - array( |
|
| 749 | - 'MTP_messenger' => $this->messenger(), |
|
| 750 | - 'MTP_message_type' => $this->message_type(), |
|
| 751 | - 'MTP_is_global' => true, |
|
| 752 | - ), |
|
| 753 | - ) |
|
| 754 | - ); |
|
| 755 | - } |
|
| 756 | - |
|
| 757 | - return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null; |
|
| 758 | - } |
|
| 759 | - |
|
| 760 | - |
|
| 761 | - /** |
|
| 762 | - * Retrieves the variation used for generating this message. |
|
| 763 | - * |
|
| 764 | - * @return string |
|
| 765 | - */ |
|
| 766 | - public function get_template_pack_variation() |
|
| 767 | - { |
|
| 768 | - /** |
|
| 769 | - * This is deprecated functionality that will be removed eventually but included here now for backward compat. |
|
| 770 | - */ |
|
| 771 | - if (! empty($this->template_variation)) { |
|
| 772 | - return $this->template_variation; |
|
| 773 | - } |
|
| 774 | - |
|
| 775 | - /** @type EE_Message_Template_Group $grp */ |
|
| 776 | - $grp = $this->get_first_related('Message_Template_Group'); |
|
| 777 | - |
|
| 778 | - // if no group then let's try to get the first related group by internal messenger and message type (will use global grp). |
|
| 779 | - if (! $grp instanceof EE_Message_Template_Group) { |
|
| 780 | - $grp = EEM_Message_Template_Group::instance()->get_one( |
|
| 781 | - array( |
|
| 782 | - array( |
|
| 783 | - 'MTP_messenger' => $this->messenger(), |
|
| 784 | - 'MTP_message_type' => $this->message_type(), |
|
| 785 | - 'MTP_is_global' => true, |
|
| 786 | - ), |
|
| 787 | - ) |
|
| 788 | - ); |
|
| 789 | - } |
|
| 790 | - |
|
| 791 | - return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : ''; |
|
| 792 | - } |
|
| 793 | - |
|
| 794 | - /** |
|
| 795 | - * Return the link to the admin details for the object. |
|
| 796 | - * |
|
| 797 | - * @return string |
|
| 798 | - */ |
|
| 799 | - public function get_admin_details_link() |
|
| 800 | - { |
|
| 801 | - EE_Registry::instance()->load_helper('URL'); |
|
| 802 | - EE_Registry::instance()->load_helper('MSG_Template'); |
|
| 803 | - switch ($this->STS_ID()) { |
|
| 804 | - case EEM_Message::status_failed: |
|
| 805 | - case EEM_Message::status_debug_only: |
|
| 806 | - return EEH_MSG_Template::generate_error_display_trigger($this); |
|
| 807 | - break; |
|
| 808 | - |
|
| 809 | - case EEM_Message::status_sent: |
|
| 810 | - return EEH_MSG_Template::generate_browser_trigger($this); |
|
| 811 | - break; |
|
| 812 | - |
|
| 813 | - default: |
|
| 814 | - return ''; |
|
| 815 | - } |
|
| 816 | - } |
|
| 817 | - |
|
| 818 | - /** |
|
| 819 | - * Returns the link to the editor for the object. Sometimes this is the same as the details. |
|
| 820 | - * |
|
| 821 | - * @return string |
|
| 822 | - */ |
|
| 823 | - public function get_admin_edit_link() |
|
| 824 | - { |
|
| 825 | - return $this->get_admin_details_link(); |
|
| 826 | - } |
|
| 827 | - |
|
| 828 | - /** |
|
| 829 | - * Returns the link to a settings page for the object. |
|
| 830 | - * |
|
| 831 | - * @return string |
|
| 832 | - */ |
|
| 833 | - public function get_admin_settings_link() |
|
| 834 | - { |
|
| 835 | - EE_Registry::instance()->load_helper('URL'); |
|
| 836 | - return EEH_URL::add_query_args_and_nonce( |
|
| 837 | - array( |
|
| 838 | - 'page' => 'espresso_messages', |
|
| 839 | - 'action' => 'settings', |
|
| 840 | - ), |
|
| 841 | - admin_url('admin.php') |
|
| 842 | - ); |
|
| 843 | - } |
|
| 844 | - |
|
| 845 | - /** |
|
| 846 | - * Returns the link to the "overview" for the object (typically the "list table" view). |
|
| 847 | - * |
|
| 848 | - * @return string |
|
| 849 | - */ |
|
| 850 | - public function get_admin_overview_link() |
|
| 851 | - { |
|
| 852 | - EE_Registry::instance()->load_helper('URL'); |
|
| 853 | - return EEH_URL::add_query_args_and_nonce( |
|
| 854 | - array( |
|
| 855 | - 'page' => 'espresso_messages', |
|
| 856 | - 'action' => 'default', |
|
| 857 | - ), |
|
| 858 | - admin_url('admin.php') |
|
| 859 | - ); |
|
| 860 | - } |
|
| 861 | - |
|
| 862 | - |
|
| 863 | - /** |
|
| 864 | - * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for |
|
| 865 | - * it. |
|
| 866 | - * Note this also SAVES the current message object to the db because it adds an error message to accompany the |
|
| 867 | - * status. |
|
| 868 | - * |
|
| 869 | - */ |
|
| 870 | - public function set_messenger_is_executing() |
|
| 871 | - { |
|
| 872 | - $this->set_STS_ID(EEM_Message::status_messenger_executing); |
|
| 873 | - $this->set_error_message( |
|
| 874 | - esc_html__( |
|
| 875 | - 'A message with this status indicates that there was a problem that occurred while the message was being |
|
| 13 | + /** |
|
| 14 | + * @deprecated 4.9.0 Added for backward compat with add-on's |
|
| 15 | + * @type null |
|
| 16 | + */ |
|
| 17 | + public $template_pack; |
|
| 18 | + |
|
| 19 | + /** |
|
| 20 | + * @deprecated 4.9.0 Added for backward compat with add-on's |
|
| 21 | + * @type null |
|
| 22 | + */ |
|
| 23 | + public $template_variation; |
|
| 24 | + |
|
| 25 | + /** |
|
| 26 | + * @deprecated 4.9.0 Added for backward compat with add-on's |
|
| 27 | + * @type string |
|
| 28 | + */ |
|
| 29 | + public $content = ''; |
|
| 30 | + |
|
| 31 | + |
|
| 32 | + /** |
|
| 33 | + * @type EE_messenger $_messenger |
|
| 34 | + */ |
|
| 35 | + protected $_messenger = null; |
|
| 36 | + |
|
| 37 | + /** |
|
| 38 | + * @type EE_message_type $_message_type |
|
| 39 | + */ |
|
| 40 | + protected $_message_type = null; |
|
| 41 | + |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * @param array $props_n_values |
|
| 45 | + * @param string $timezone |
|
| 46 | + * @param array $date_formats incoming date formats in an array. First value is the date_format, second is time |
|
| 47 | + * format. |
|
| 48 | + * @return EE_Message |
|
| 49 | + */ |
|
| 50 | + public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array()) |
|
| 51 | + { |
|
| 52 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__); |
|
| 53 | + // if object doesn't exist, let's generate a unique token on instantiation so that its available even before saving to db. |
|
| 54 | + if (! $has_object) { |
|
| 55 | + EE_Registry::instance()->load_helper('URL'); |
|
| 56 | + $props_n_values['MSG_token'] = EEH_URL::generate_unique_token(); |
|
| 57 | + } |
|
| 58 | + return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
| 59 | + } |
|
| 60 | + |
|
| 61 | + |
|
| 62 | + /** |
|
| 63 | + * @param array $props_n_values |
|
| 64 | + * @param string $timezone |
|
| 65 | + * @return EE_Message |
|
| 66 | + */ |
|
| 67 | + public static function new_instance_from_db($props_n_values = array(), $timezone = '') |
|
| 68 | + { |
|
| 69 | + return new self($props_n_values, true, $timezone); |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + |
|
| 73 | + /** |
|
| 74 | + * Gets MSG_token |
|
| 75 | + * |
|
| 76 | + * @return int |
|
| 77 | + */ |
|
| 78 | + public function MSG_token() |
|
| 79 | + { |
|
| 80 | + return $this->get('MSG_token'); |
|
| 81 | + } |
|
| 82 | + |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * Sets MSG_token |
|
| 86 | + * |
|
| 87 | + * @param int $MSG_token |
|
| 88 | + */ |
|
| 89 | + public function set_MSG_token($MSG_token) |
|
| 90 | + { |
|
| 91 | + $this->set('MSG_token', $MSG_token); |
|
| 92 | + } |
|
| 93 | + |
|
| 94 | + |
|
| 95 | + /** |
|
| 96 | + * Gets GRP_ID |
|
| 97 | + * |
|
| 98 | + * @return int |
|
| 99 | + */ |
|
| 100 | + public function GRP_ID() |
|
| 101 | + { |
|
| 102 | + return $this->get('GRP_ID'); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + |
|
| 106 | + /** |
|
| 107 | + * Sets GRP_ID |
|
| 108 | + * |
|
| 109 | + * @param int $GRP_ID |
|
| 110 | + */ |
|
| 111 | + public function set_GRP_ID($GRP_ID) |
|
| 112 | + { |
|
| 113 | + $this->set('GRP_ID', $GRP_ID); |
|
| 114 | + } |
|
| 115 | + |
|
| 116 | + |
|
| 117 | + /** |
|
| 118 | + * Gets TXN_ID |
|
| 119 | + * |
|
| 120 | + * @return int |
|
| 121 | + */ |
|
| 122 | + public function TXN_ID() |
|
| 123 | + { |
|
| 124 | + return $this->get('TXN_ID'); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + |
|
| 128 | + /** |
|
| 129 | + * Sets TXN_ID |
|
| 130 | + * |
|
| 131 | + * @param int $TXN_ID |
|
| 132 | + */ |
|
| 133 | + public function set_TXN_ID($TXN_ID) |
|
| 134 | + { |
|
| 135 | + $this->set('TXN_ID', $TXN_ID); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + |
|
| 139 | + /** |
|
| 140 | + * Gets messenger |
|
| 141 | + * |
|
| 142 | + * @return string |
|
| 143 | + */ |
|
| 144 | + public function messenger() |
|
| 145 | + { |
|
| 146 | + return $this->get('MSG_messenger'); |
|
| 147 | + } |
|
| 148 | + |
|
| 149 | + |
|
| 150 | + /** |
|
| 151 | + * Sets messenger |
|
| 152 | + * |
|
| 153 | + * @param string $messenger |
|
| 154 | + */ |
|
| 155 | + public function set_messenger($messenger) |
|
| 156 | + { |
|
| 157 | + $this->set('MSG_messenger', $messenger); |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + |
|
| 161 | + /** |
|
| 162 | + * Returns corresponding messenger object for the set messenger on this message |
|
| 163 | + * |
|
| 164 | + * @return EE_messenger | null |
|
| 165 | + */ |
|
| 166 | + public function messenger_object() |
|
| 167 | + { |
|
| 168 | + return $this->_messenger; |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * Sets messenger |
|
| 174 | + * |
|
| 175 | + * @param EE_messenger $messenger |
|
| 176 | + */ |
|
| 177 | + public function set_messenger_object(EE_messenger $messenger) |
|
| 178 | + { |
|
| 179 | + $this->_messenger = $messenger; |
|
| 180 | + } |
|
| 181 | + |
|
| 182 | + |
|
| 183 | + /** |
|
| 184 | + * validates messenger |
|
| 185 | + * |
|
| 186 | + * @param bool $throw_exceptions |
|
| 187 | + * @return bool |
|
| 188 | + * @throws \EE_Error |
|
| 189 | + */ |
|
| 190 | + public function valid_messenger($throw_exceptions = false) |
|
| 191 | + { |
|
| 192 | + if ($this->_messenger instanceof EE_messenger) { |
|
| 193 | + return true; |
|
| 194 | + } |
|
| 195 | + if ($throw_exceptions) { |
|
| 196 | + throw new EE_Error( |
|
| 197 | + sprintf( |
|
| 198 | + __( |
|
| 199 | + 'The "%1$s" messenger set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.', |
|
| 200 | + 'event_espresso' |
|
| 201 | + ), |
|
| 202 | + $this->messenger() |
|
| 203 | + ) |
|
| 204 | + ); |
|
| 205 | + } |
|
| 206 | + return false; |
|
| 207 | + } |
|
| 208 | + |
|
| 209 | + |
|
| 210 | + /** |
|
| 211 | + * This returns the set localized label for the messenger on this message. |
|
| 212 | + * Note, if unable to retrieve the EE_messenger object then will just return the messenger slug saved |
|
| 213 | + * with this message. |
|
| 214 | + * |
|
| 215 | + * @param bool $plural whether to return the plural label or not. |
|
| 216 | + * @return string |
|
| 217 | + */ |
|
| 218 | + public function messenger_label($plural = false) |
|
| 219 | + { |
|
| 220 | + $label_type = $plural ? 'plural' : 'singular'; |
|
| 221 | + $messenger = $this->messenger_object(); |
|
| 222 | + return $messenger instanceof EE_messenger ? $messenger->label[ $label_type ] : $this->messenger(); |
|
| 223 | + } |
|
| 224 | + |
|
| 225 | + |
|
| 226 | + /** |
|
| 227 | + * Gets message_type |
|
| 228 | + * |
|
| 229 | + * @return string |
|
| 230 | + */ |
|
| 231 | + public function message_type() |
|
| 232 | + { |
|
| 233 | + return $this->get('MSG_message_type'); |
|
| 234 | + } |
|
| 235 | + |
|
| 236 | + |
|
| 237 | + /** |
|
| 238 | + * Sets message_type |
|
| 239 | + * |
|
| 240 | + * @param string $message_type |
|
| 241 | + */ |
|
| 242 | + public function set_message_type($message_type) |
|
| 243 | + { |
|
| 244 | + $this->set('MSG_message_type', $message_type); |
|
| 245 | + } |
|
| 246 | + |
|
| 247 | + |
|
| 248 | + /** |
|
| 249 | + * Returns the message type object for the set message type on this message |
|
| 250 | + * |
|
| 251 | + * @return EE_message_type | null |
|
| 252 | + */ |
|
| 253 | + public function message_type_object() |
|
| 254 | + { |
|
| 255 | + return $this->_message_type; |
|
| 256 | + } |
|
| 257 | + |
|
| 258 | + |
|
| 259 | + /** |
|
| 260 | + * Sets message_type |
|
| 261 | + * |
|
| 262 | + * @param EE_message_type $message_type |
|
| 263 | + * @param bool $set_priority This indicates whether to set the priority to whatever the priority is on |
|
| 264 | + * the message type or not. |
|
| 265 | + */ |
|
| 266 | + public function set_message_type_object(EE_message_type $message_type, $set_priority = false) |
|
| 267 | + { |
|
| 268 | + $this->_message_type = $message_type; |
|
| 269 | + if ($set_priority) { |
|
| 270 | + $this->set_priority($this->_message_type->get_priority()); |
|
| 271 | + } |
|
| 272 | + } |
|
| 273 | + |
|
| 274 | + |
|
| 275 | + /** |
|
| 276 | + * validates message_type |
|
| 277 | + * |
|
| 278 | + * @param bool $throw_exceptions |
|
| 279 | + * @return bool |
|
| 280 | + * @throws \EE_Error |
|
| 281 | + */ |
|
| 282 | + public function valid_message_type($throw_exceptions = false) |
|
| 283 | + { |
|
| 284 | + if ($this->_message_type instanceof EE_message_type) { |
|
| 285 | + return true; |
|
| 286 | + } |
|
| 287 | + if ($throw_exceptions) { |
|
| 288 | + throw new EE_Error( |
|
| 289 | + sprintf( |
|
| 290 | + __( |
|
| 291 | + 'The %1$s message type set for this message is missing or invalid. Please double-check the spelling and verify that the correct files exist.', |
|
| 292 | + 'event_espresso' |
|
| 293 | + ), |
|
| 294 | + $this->message_type() |
|
| 295 | + ) |
|
| 296 | + ); |
|
| 297 | + } |
|
| 298 | + return false; |
|
| 299 | + } |
|
| 300 | + |
|
| 301 | + |
|
| 302 | + /** |
|
| 303 | + * validates messenger and message_type (that they are valid EE_messenger and EE_message_type objects). |
|
| 304 | + * |
|
| 305 | + * @param bool $throw_exceptions |
|
| 306 | + * @return bool |
|
| 307 | + * @throws \EE_Error |
|
| 308 | + */ |
|
| 309 | + public function is_valid($throw_exceptions = false) |
|
| 310 | + { |
|
| 311 | + if ($this->valid_messenger($throw_exceptions) && $this->valid_message_type($throw_exceptions)) { |
|
| 312 | + return true; |
|
| 313 | + } |
|
| 314 | + return false; |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + |
|
| 318 | + /** |
|
| 319 | + * This validates whether the internal messenger and message type objects are valid for sending. |
|
| 320 | + * Three checks are done: |
|
| 321 | + * 1. There is a valid messenger object. |
|
| 322 | + * 2. There is a valid message type object. |
|
| 323 | + * 3. The message type object is active for the messenger. |
|
| 324 | + * |
|
| 325 | + * @throws EE_Error But only if $throw_exceptions is set to true. |
|
| 326 | + * @param bool $throw_exceptions |
|
| 327 | + * @return bool |
|
| 328 | + */ |
|
| 329 | + public function is_valid_for_sending_or_generation($throw_exceptions = false) |
|
| 330 | + { |
|
| 331 | + $valid = false; |
|
| 332 | + if ($this->is_valid($throw_exceptions)) { |
|
| 333 | + /** @var EE_Message_Resource_Manager $message_resource_manager */ |
|
| 334 | + $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
| 335 | + $valid = $message_resource_manager->is_message_type_active_for_messenger( |
|
| 336 | + $this->messenger(), |
|
| 337 | + $this->message_type() |
|
| 338 | + ); |
|
| 339 | + if (! $valid && $throw_exceptions) { |
|
| 340 | + throw new EE_Error( |
|
| 341 | + sprintf( |
|
| 342 | + __( |
|
| 343 | + 'The %1$s message type is not a valid message type for the %2$s messenger so it will not be sent.', |
|
| 344 | + 'event_espresso' |
|
| 345 | + ), |
|
| 346 | + $this->message_type(), |
|
| 347 | + $this->messenger() |
|
| 348 | + ) |
|
| 349 | + ); |
|
| 350 | + } |
|
| 351 | + } |
|
| 352 | + return $valid; |
|
| 353 | + } |
|
| 354 | + |
|
| 355 | + |
|
| 356 | + /** |
|
| 357 | + * This returns the set localized label for the message type on this message. |
|
| 358 | + * Note, if unable to retrieve the EE_message_type object then will just return the message type slug saved |
|
| 359 | + * with this message. |
|
| 360 | + * |
|
| 361 | + * @param bool $plural whether to return the plural label or not. |
|
| 362 | + * @return string |
|
| 363 | + */ |
|
| 364 | + public function message_type_label($plural = false) |
|
| 365 | + { |
|
| 366 | + $label_type = $plural ? 'plural' : 'singular'; |
|
| 367 | + $message_type = $this->message_type_object(); |
|
| 368 | + return $message_type instanceof EE_message_type |
|
| 369 | + ? $message_type->label[ $label_type ] |
|
| 370 | + : str_replace( |
|
| 371 | + '_', |
|
| 372 | + ' ', |
|
| 373 | + $this->message_type() |
|
| 374 | + ); |
|
| 375 | + } |
|
| 376 | + |
|
| 377 | + |
|
| 378 | + /** |
|
| 379 | + * Gets context |
|
| 380 | + * |
|
| 381 | + * @return string |
|
| 382 | + */ |
|
| 383 | + public function context() |
|
| 384 | + { |
|
| 385 | + return $this->get('MSG_context'); |
|
| 386 | + } |
|
| 387 | + |
|
| 388 | + |
|
| 389 | + /** |
|
| 390 | + * This returns the corresponding localized label for the given context slug, if possible from installed message |
|
| 391 | + * types. Otherwise, this will just return the set context slug on this object. |
|
| 392 | + * |
|
| 393 | + * @return string |
|
| 394 | + */ |
|
| 395 | + public function context_label() |
|
| 396 | + { |
|
| 397 | + /** @type EE_Message_Resource_Manager $message_resource_manager */ |
|
| 398 | + $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager'); |
|
| 399 | + $contexts = $message_resource_manager->get_all_contexts(); |
|
| 400 | + return isset($contexts[ $this->context() ]) ? $contexts[ $this->context() ] : $this->context(); |
|
| 401 | + } |
|
| 402 | + |
|
| 403 | + |
|
| 404 | + /** |
|
| 405 | + * Sets context |
|
| 406 | + * |
|
| 407 | + * @param string $context |
|
| 408 | + */ |
|
| 409 | + public function set_context($context) |
|
| 410 | + { |
|
| 411 | + $this->set('MSG_context', $context); |
|
| 412 | + } |
|
| 413 | + |
|
| 414 | + |
|
| 415 | + /** |
|
| 416 | + * Gets recipient_ID |
|
| 417 | + * |
|
| 418 | + * @return int |
|
| 419 | + */ |
|
| 420 | + public function recipient_ID() |
|
| 421 | + { |
|
| 422 | + return $this->get('MSG_recipient_ID'); |
|
| 423 | + } |
|
| 424 | + |
|
| 425 | + |
|
| 426 | + /** |
|
| 427 | + * Sets recipient_ID |
|
| 428 | + * |
|
| 429 | + * @param string $recipient_ID |
|
| 430 | + */ |
|
| 431 | + public function set_recipient_ID($recipient_ID) |
|
| 432 | + { |
|
| 433 | + $this->set('MSG_recipient_ID', $recipient_ID); |
|
| 434 | + } |
|
| 435 | + |
|
| 436 | + |
|
| 437 | + /** |
|
| 438 | + * Gets recipient_type |
|
| 439 | + * |
|
| 440 | + * @return string |
|
| 441 | + */ |
|
| 442 | + public function recipient_type() |
|
| 443 | + { |
|
| 444 | + return $this->get('MSG_recipient_type'); |
|
| 445 | + } |
|
| 446 | + |
|
| 447 | + |
|
| 448 | + /** |
|
| 449 | + * Return the related object matching the recipient type and ID. |
|
| 450 | + * |
|
| 451 | + * @return EE_Base_Class | null |
|
| 452 | + */ |
|
| 453 | + public function recipient_object() |
|
| 454 | + { |
|
| 455 | + if (! $this->recipient_type() || ! $this->recipient_ID()) { |
|
| 456 | + return null; |
|
| 457 | + } |
|
| 458 | + |
|
| 459 | + return $this->get_first_related($this->recipient_type()); |
|
| 460 | + } |
|
| 461 | + |
|
| 462 | + |
|
| 463 | + /** |
|
| 464 | + * Sets recipient_type |
|
| 465 | + * |
|
| 466 | + * @param string $recipient_type |
|
| 467 | + */ |
|
| 468 | + public function set_recipient_type($recipient_type) |
|
| 469 | + { |
|
| 470 | + $this->set('MSG_recipient_type', $recipient_type); |
|
| 471 | + } |
|
| 472 | + |
|
| 473 | + |
|
| 474 | + /** |
|
| 475 | + * Gets content |
|
| 476 | + * |
|
| 477 | + * @return string |
|
| 478 | + */ |
|
| 479 | + public function content() |
|
| 480 | + { |
|
| 481 | + return $this->get('MSG_content'); |
|
| 482 | + } |
|
| 483 | + |
|
| 484 | + |
|
| 485 | + /** |
|
| 486 | + * Sets content |
|
| 487 | + * |
|
| 488 | + * @param string $content |
|
| 489 | + */ |
|
| 490 | + public function set_content($content) |
|
| 491 | + { |
|
| 492 | + $this->set('MSG_content', $content); |
|
| 493 | + } |
|
| 494 | + |
|
| 495 | + |
|
| 496 | + /** |
|
| 497 | + * Gets subject |
|
| 498 | + * |
|
| 499 | + * @return string |
|
| 500 | + */ |
|
| 501 | + public function subject() |
|
| 502 | + { |
|
| 503 | + return $this->get('MSG_subject'); |
|
| 504 | + } |
|
| 505 | + |
|
| 506 | + |
|
| 507 | + /** |
|
| 508 | + * Sets subject |
|
| 509 | + * |
|
| 510 | + * @param string $subject |
|
| 511 | + */ |
|
| 512 | + public function set_subject($subject) |
|
| 513 | + { |
|
| 514 | + $this->set('MSG_subject', $subject); |
|
| 515 | + } |
|
| 516 | + |
|
| 517 | + |
|
| 518 | + /** |
|
| 519 | + * Gets to |
|
| 520 | + * |
|
| 521 | + * @return string |
|
| 522 | + */ |
|
| 523 | + public function to() |
|
| 524 | + { |
|
| 525 | + $to = $this->get('MSG_to'); |
|
| 526 | + return empty($to) ? __('No recipient', 'event_espresso') : $to; |
|
| 527 | + } |
|
| 528 | + |
|
| 529 | + |
|
| 530 | + /** |
|
| 531 | + * Sets to |
|
| 532 | + * |
|
| 533 | + * @param string $to |
|
| 534 | + */ |
|
| 535 | + public function set_to($to) |
|
| 536 | + { |
|
| 537 | + $this->set('MSG_to', $to); |
|
| 538 | + } |
|
| 539 | + |
|
| 540 | + |
|
| 541 | + /** |
|
| 542 | + * Gets from |
|
| 543 | + * |
|
| 544 | + * @return string |
|
| 545 | + */ |
|
| 546 | + public function from() |
|
| 547 | + { |
|
| 548 | + return $this->get('MSG_from'); |
|
| 549 | + } |
|
| 550 | + |
|
| 551 | + |
|
| 552 | + /** |
|
| 553 | + * Sets from |
|
| 554 | + * |
|
| 555 | + * @param string $from |
|
| 556 | + */ |
|
| 557 | + public function set_from($from) |
|
| 558 | + { |
|
| 559 | + $this->set('MSG_from', $from); |
|
| 560 | + } |
|
| 561 | + |
|
| 562 | + |
|
| 563 | + /** |
|
| 564 | + * Gets priority |
|
| 565 | + * |
|
| 566 | + * @return int |
|
| 567 | + */ |
|
| 568 | + public function priority() |
|
| 569 | + { |
|
| 570 | + return $this->get('MSG_priority'); |
|
| 571 | + } |
|
| 572 | + |
|
| 573 | + |
|
| 574 | + /** |
|
| 575 | + * Sets priority |
|
| 576 | + * Note. Send Now Messengers always override any priority that may be set on a Message. So |
|
| 577 | + * this method calls the send_now method to verify that. |
|
| 578 | + * |
|
| 579 | + * @param int $priority |
|
| 580 | + */ |
|
| 581 | + public function set_priority($priority) |
|
| 582 | + { |
|
| 583 | + $priority = $this->send_now() ? EEM_Message::priority_high : $priority; |
|
| 584 | + parent::set('MSG_priority', $priority); |
|
| 585 | + } |
|
| 586 | + |
|
| 587 | + |
|
| 588 | + /** |
|
| 589 | + * Overrides parent::set method so we can capture any sets for priority. |
|
| 590 | + * |
|
| 591 | + * @param string $field_name |
|
| 592 | + * @param mixed $field_value |
|
| 593 | + * @param bool $use_default |
|
| 594 | + * @throws EE_Error |
|
| 595 | + * @see parent::set() for phpdocs |
|
| 596 | + */ |
|
| 597 | + public function set($field_name, $field_value, bool $use_default = false) |
|
| 598 | + { |
|
| 599 | + if ($field_name === 'MSG_priority') { |
|
| 600 | + $this->set_priority($field_value); |
|
| 601 | + } |
|
| 602 | + parent::set($field_name, $field_value, $use_default); |
|
| 603 | + } |
|
| 604 | + |
|
| 605 | + |
|
| 606 | + /** |
|
| 607 | + * @return bool |
|
| 608 | + * @throws \EE_Error |
|
| 609 | + */ |
|
| 610 | + public function send_now() |
|
| 611 | + { |
|
| 612 | + $send_now = $this->valid_messenger() && $this->messenger_object()->send_now() ? EEM_Message::priority_high |
|
| 613 | + : $this->priority(); |
|
| 614 | + return $send_now === EEM_Message::priority_high ? true : false; |
|
| 615 | + } |
|
| 616 | + |
|
| 617 | + |
|
| 618 | + /** |
|
| 619 | + * Gets STS_ID |
|
| 620 | + * |
|
| 621 | + * @return string |
|
| 622 | + */ |
|
| 623 | + public function STS_ID() |
|
| 624 | + { |
|
| 625 | + return $this->get('STS_ID'); |
|
| 626 | + } |
|
| 627 | + |
|
| 628 | + |
|
| 629 | + /** |
|
| 630 | + * Sets STS_ID |
|
| 631 | + * |
|
| 632 | + * @param string $STS_ID |
|
| 633 | + */ |
|
| 634 | + public function set_STS_ID($STS_ID) |
|
| 635 | + { |
|
| 636 | + $this->set('STS_ID', $STS_ID); |
|
| 637 | + } |
|
| 638 | + |
|
| 639 | + |
|
| 640 | + /** |
|
| 641 | + * Gets created |
|
| 642 | + * |
|
| 643 | + * @return string |
|
| 644 | + */ |
|
| 645 | + public function created() |
|
| 646 | + { |
|
| 647 | + return $this->get('MSG_created'); |
|
| 648 | + } |
|
| 649 | + |
|
| 650 | + |
|
| 651 | + /** |
|
| 652 | + * Sets created |
|
| 653 | + * |
|
| 654 | + * @param string $created |
|
| 655 | + */ |
|
| 656 | + public function set_created($created) |
|
| 657 | + { |
|
| 658 | + $this->set('MSG_created', $created); |
|
| 659 | + } |
|
| 660 | + |
|
| 661 | + |
|
| 662 | + /** |
|
| 663 | + * Gets modified |
|
| 664 | + * |
|
| 665 | + * @return string |
|
| 666 | + */ |
|
| 667 | + public function modified() |
|
| 668 | + { |
|
| 669 | + return $this->get('MSG_modified'); |
|
| 670 | + } |
|
| 671 | + |
|
| 672 | + |
|
| 673 | + /** |
|
| 674 | + * Sets modified |
|
| 675 | + * |
|
| 676 | + * @param string $modified |
|
| 677 | + */ |
|
| 678 | + public function set_modified($modified) |
|
| 679 | + { |
|
| 680 | + $this->set('MSG_modified', $modified); |
|
| 681 | + } |
|
| 682 | + |
|
| 683 | + |
|
| 684 | + /** |
|
| 685 | + * Sets generation data for this message. |
|
| 686 | + * |
|
| 687 | + * @param mixed $data |
|
| 688 | + */ |
|
| 689 | + public function set_generation_data($data) |
|
| 690 | + { |
|
| 691 | + $this->set_field_or_extra_meta('MSG_generation_data', $data); |
|
| 692 | + } |
|
| 693 | + |
|
| 694 | + |
|
| 695 | + /** |
|
| 696 | + * Returns any set generation data for this message. |
|
| 697 | + * |
|
| 698 | + * @return mixed|null |
|
| 699 | + */ |
|
| 700 | + public function get_generation_data() |
|
| 701 | + { |
|
| 702 | + return $this->get_field_or_extra_meta('MSG_generation_data'); |
|
| 703 | + } |
|
| 704 | + |
|
| 705 | + |
|
| 706 | + /** |
|
| 707 | + * Gets any error message. |
|
| 708 | + * |
|
| 709 | + * @return mixed|null |
|
| 710 | + */ |
|
| 711 | + public function error_message() |
|
| 712 | + { |
|
| 713 | + return $this->get_field_or_extra_meta('MSG_error'); |
|
| 714 | + } |
|
| 715 | + |
|
| 716 | + |
|
| 717 | + /** |
|
| 718 | + * Sets an error message. |
|
| 719 | + * |
|
| 720 | + * @param $message |
|
| 721 | + * @return bool|int |
|
| 722 | + */ |
|
| 723 | + public function set_error_message($message) |
|
| 724 | + { |
|
| 725 | + return $this->set_field_or_extra_meta('MSG_error', $message); |
|
| 726 | + } |
|
| 727 | + |
|
| 728 | + |
|
| 729 | + /** |
|
| 730 | + * This retrieves the associated template pack with this message. |
|
| 731 | + * |
|
| 732 | + * @return EE_Messages_Template_Pack | null |
|
| 733 | + */ |
|
| 734 | + public function get_template_pack() |
|
| 735 | + { |
|
| 736 | + /** |
|
| 737 | + * This is deprecated functionality that will be removed eventually but included here now for backward compat. |
|
| 738 | + */ |
|
| 739 | + if (! empty($this->template_pack)) { |
|
| 740 | + return $this->template_pack; |
|
| 741 | + } |
|
| 742 | + /** @type EE_Message_Template_Group $grp */ |
|
| 743 | + $grp = $this->get_first_related('Message_Template_Group'); |
|
| 744 | + // if no group then let's try to get the first related group by internal messenger and message type (will use global grp). |
|
| 745 | + if (! $grp instanceof EE_Message_Template_Group) { |
|
| 746 | + $grp = EEM_Message_Template_Group::instance()->get_one( |
|
| 747 | + array( |
|
| 748 | + array( |
|
| 749 | + 'MTP_messenger' => $this->messenger(), |
|
| 750 | + 'MTP_message_type' => $this->message_type(), |
|
| 751 | + 'MTP_is_global' => true, |
|
| 752 | + ), |
|
| 753 | + ) |
|
| 754 | + ); |
|
| 755 | + } |
|
| 756 | + |
|
| 757 | + return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack() : null; |
|
| 758 | + } |
|
| 759 | + |
|
| 760 | + |
|
| 761 | + /** |
|
| 762 | + * Retrieves the variation used for generating this message. |
|
| 763 | + * |
|
| 764 | + * @return string |
|
| 765 | + */ |
|
| 766 | + public function get_template_pack_variation() |
|
| 767 | + { |
|
| 768 | + /** |
|
| 769 | + * This is deprecated functionality that will be removed eventually but included here now for backward compat. |
|
| 770 | + */ |
|
| 771 | + if (! empty($this->template_variation)) { |
|
| 772 | + return $this->template_variation; |
|
| 773 | + } |
|
| 774 | + |
|
| 775 | + /** @type EE_Message_Template_Group $grp */ |
|
| 776 | + $grp = $this->get_first_related('Message_Template_Group'); |
|
| 777 | + |
|
| 778 | + // if no group then let's try to get the first related group by internal messenger and message type (will use global grp). |
|
| 779 | + if (! $grp instanceof EE_Message_Template_Group) { |
|
| 780 | + $grp = EEM_Message_Template_Group::instance()->get_one( |
|
| 781 | + array( |
|
| 782 | + array( |
|
| 783 | + 'MTP_messenger' => $this->messenger(), |
|
| 784 | + 'MTP_message_type' => $this->message_type(), |
|
| 785 | + 'MTP_is_global' => true, |
|
| 786 | + ), |
|
| 787 | + ) |
|
| 788 | + ); |
|
| 789 | + } |
|
| 790 | + |
|
| 791 | + return $grp instanceof EE_Message_Template_Group ? $grp->get_template_pack_variation() : ''; |
|
| 792 | + } |
|
| 793 | + |
|
| 794 | + /** |
|
| 795 | + * Return the link to the admin details for the object. |
|
| 796 | + * |
|
| 797 | + * @return string |
|
| 798 | + */ |
|
| 799 | + public function get_admin_details_link() |
|
| 800 | + { |
|
| 801 | + EE_Registry::instance()->load_helper('URL'); |
|
| 802 | + EE_Registry::instance()->load_helper('MSG_Template'); |
|
| 803 | + switch ($this->STS_ID()) { |
|
| 804 | + case EEM_Message::status_failed: |
|
| 805 | + case EEM_Message::status_debug_only: |
|
| 806 | + return EEH_MSG_Template::generate_error_display_trigger($this); |
|
| 807 | + break; |
|
| 808 | + |
|
| 809 | + case EEM_Message::status_sent: |
|
| 810 | + return EEH_MSG_Template::generate_browser_trigger($this); |
|
| 811 | + break; |
|
| 812 | + |
|
| 813 | + default: |
|
| 814 | + return ''; |
|
| 815 | + } |
|
| 816 | + } |
|
| 817 | + |
|
| 818 | + /** |
|
| 819 | + * Returns the link to the editor for the object. Sometimes this is the same as the details. |
|
| 820 | + * |
|
| 821 | + * @return string |
|
| 822 | + */ |
|
| 823 | + public function get_admin_edit_link() |
|
| 824 | + { |
|
| 825 | + return $this->get_admin_details_link(); |
|
| 826 | + } |
|
| 827 | + |
|
| 828 | + /** |
|
| 829 | + * Returns the link to a settings page for the object. |
|
| 830 | + * |
|
| 831 | + * @return string |
|
| 832 | + */ |
|
| 833 | + public function get_admin_settings_link() |
|
| 834 | + { |
|
| 835 | + EE_Registry::instance()->load_helper('URL'); |
|
| 836 | + return EEH_URL::add_query_args_and_nonce( |
|
| 837 | + array( |
|
| 838 | + 'page' => 'espresso_messages', |
|
| 839 | + 'action' => 'settings', |
|
| 840 | + ), |
|
| 841 | + admin_url('admin.php') |
|
| 842 | + ); |
|
| 843 | + } |
|
| 844 | + |
|
| 845 | + /** |
|
| 846 | + * Returns the link to the "overview" for the object (typically the "list table" view). |
|
| 847 | + * |
|
| 848 | + * @return string |
|
| 849 | + */ |
|
| 850 | + public function get_admin_overview_link() |
|
| 851 | + { |
|
| 852 | + EE_Registry::instance()->load_helper('URL'); |
|
| 853 | + return EEH_URL::add_query_args_and_nonce( |
|
| 854 | + array( |
|
| 855 | + 'page' => 'espresso_messages', |
|
| 856 | + 'action' => 'default', |
|
| 857 | + ), |
|
| 858 | + admin_url('admin.php') |
|
| 859 | + ); |
|
| 860 | + } |
|
| 861 | + |
|
| 862 | + |
|
| 863 | + /** |
|
| 864 | + * This sets the EEM_Message::status_messenger_executing class on the message and the appropriate error message for |
|
| 865 | + * it. |
|
| 866 | + * Note this also SAVES the current message object to the db because it adds an error message to accompany the |
|
| 867 | + * status. |
|
| 868 | + * |
|
| 869 | + */ |
|
| 870 | + public function set_messenger_is_executing() |
|
| 871 | + { |
|
| 872 | + $this->set_STS_ID(EEM_Message::status_messenger_executing); |
|
| 873 | + $this->set_error_message( |
|
| 874 | + esc_html__( |
|
| 875 | + 'A message with this status indicates that there was a problem that occurred while the message was being |
|
| 876 | 876 | processed by the messenger. It is still possible that the message was sent successfully, but at some |
| 877 | 877 | point during the processing there was a failure. This usually is indicative of a timeout issue with PHP |
| 878 | 878 | or memory limits being reached. If you see this repeatedly you may want to consider upgrading the memory |
| 879 | 879 | available to PHP on your server.', |
| 880 | - 'event_espresso' |
|
| 881 | - ) |
|
| 882 | - ); |
|
| 883 | - } |
|
| 880 | + 'event_espresso' |
|
| 881 | + ) |
|
| 882 | + ); |
|
| 883 | + } |
|
| 884 | 884 | } |
@@ -17,2117 +17,2117 @@ |
||
| 17 | 17 | { |
| 18 | 18 | |
| 19 | 19 | |
| 20 | - /** |
|
| 21 | - * Used to reference when a registration has never been checked in. |
|
| 22 | - * |
|
| 23 | - * @deprecated use \EE_Checkin::status_checked_never instead |
|
| 24 | - * @type int |
|
| 25 | - */ |
|
| 26 | - const checkin_status_never = 2; |
|
| 27 | - |
|
| 28 | - /** |
|
| 29 | - * Used to reference when a registration has been checked in. |
|
| 30 | - * |
|
| 31 | - * @deprecated use \EE_Checkin::status_checked_in instead |
|
| 32 | - * @type int |
|
| 33 | - */ |
|
| 34 | - const checkin_status_in = 1; |
|
| 35 | - |
|
| 36 | - |
|
| 37 | - /** |
|
| 38 | - * Used to reference when a registration has been checked out. |
|
| 39 | - * |
|
| 40 | - * @deprecated use \EE_Checkin::status_checked_out instead |
|
| 41 | - * @type int |
|
| 42 | - */ |
|
| 43 | - const checkin_status_out = 0; |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - /** |
|
| 47 | - * extra meta key for tracking reg status os trashed registrations |
|
| 48 | - * |
|
| 49 | - * @type string |
|
| 50 | - */ |
|
| 51 | - const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status'; |
|
| 52 | - |
|
| 53 | - |
|
| 54 | - /** |
|
| 55 | - * extra meta key for tracking if registration has reserved ticket |
|
| 56 | - * |
|
| 57 | - * @type string |
|
| 58 | - */ |
|
| 59 | - const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket'; |
|
| 60 | - |
|
| 61 | - |
|
| 62 | - /** |
|
| 63 | - * @param array $props_n_values incoming values |
|
| 64 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 65 | - * used.) |
|
| 66 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 67 | - * date_format and the second value is the time format |
|
| 68 | - * @return EE_Registration |
|
| 69 | - * @throws EE_Error |
|
| 70 | - */ |
|
| 71 | - public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array()) |
|
| 72 | - { |
|
| 73 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 74 | - return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
| 75 | - } |
|
| 76 | - |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * @param array $props_n_values incoming values from the database |
|
| 80 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 81 | - * the website will be used. |
|
| 82 | - * @return EE_Registration |
|
| 83 | - */ |
|
| 84 | - public static function new_instance_from_db($props_n_values = array(), $timezone = '') |
|
| 85 | - { |
|
| 86 | - return new self($props_n_values, true, $timezone); |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - |
|
| 90 | - /** |
|
| 91 | - * Set Event ID |
|
| 92 | - * |
|
| 93 | - * @param int $EVT_ID Event ID |
|
| 94 | - * @throws EE_Error |
|
| 95 | - * @throws RuntimeException |
|
| 96 | - */ |
|
| 97 | - public function set_event($EVT_ID = 0) |
|
| 98 | - { |
|
| 99 | - $this->set('EVT_ID', $EVT_ID); |
|
| 100 | - } |
|
| 101 | - |
|
| 102 | - |
|
| 103 | - /** |
|
| 104 | - * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can |
|
| 105 | - * be routed to internal methods |
|
| 106 | - * |
|
| 107 | - * @param string $field_name |
|
| 108 | - * @param mixed $field_value |
|
| 109 | - * @param bool $use_default |
|
| 110 | - * @throws EE_Error |
|
| 111 | - * @throws EntityNotFoundException |
|
| 112 | - * @throws InvalidArgumentException |
|
| 113 | - * @throws InvalidDataTypeException |
|
| 114 | - * @throws InvalidInterfaceException |
|
| 115 | - * @throws ReflectionException |
|
| 116 | - * @throws RuntimeException |
|
| 117 | - */ |
|
| 118 | - public function set($field_name, $field_value, bool $use_default = false) |
|
| 119 | - { |
|
| 120 | - switch ($field_name) { |
|
| 121 | - case 'REG_code': |
|
| 122 | - if (! empty($field_value) && $this->reg_code() === null) { |
|
| 123 | - $this->set_reg_code($field_value, $use_default); |
|
| 124 | - } |
|
| 125 | - break; |
|
| 126 | - case 'STS_ID': |
|
| 127 | - $this->set_status($field_value, $use_default); |
|
| 128 | - break; |
|
| 129 | - default: |
|
| 130 | - parent::set($field_name, $field_value, $use_default); |
|
| 131 | - } |
|
| 132 | - } |
|
| 133 | - |
|
| 134 | - |
|
| 135 | - /** |
|
| 136 | - * Set Status ID |
|
| 137 | - * updates the registration status and ALSO... |
|
| 138 | - * calls reserve_registration_space() if the reg status changes TO approved from any other reg status |
|
| 139 | - * calls release_registration_space() if the reg status changes FROM approved to any other reg status |
|
| 140 | - * |
|
| 141 | - * @param string $new_STS_ID |
|
| 142 | - * @param boolean $use_default |
|
| 143 | - * @param ContextInterface|null $context |
|
| 144 | - * @return bool |
|
| 145 | - * @throws DomainException |
|
| 146 | - * @throws EE_Error |
|
| 147 | - * @throws EntityNotFoundException |
|
| 148 | - * @throws InvalidArgumentException |
|
| 149 | - * @throws InvalidDataTypeException |
|
| 150 | - * @throws InvalidInterfaceException |
|
| 151 | - * @throws ReflectionException |
|
| 152 | - * @throws RuntimeException |
|
| 153 | - * @throws UnexpectedEntityException |
|
| 154 | - */ |
|
| 155 | - public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null) |
|
| 156 | - { |
|
| 157 | - // get current REG_Status |
|
| 158 | - $old_STS_ID = $this->status_ID(); |
|
| 159 | - // if status has changed |
|
| 160 | - if ( |
|
| 161 | - $old_STS_ID !== $new_STS_ID // and that status has actually changed |
|
| 162 | - && ! empty($old_STS_ID) // and that old status is actually set |
|
| 163 | - && ! empty($new_STS_ID) // as well as the new status |
|
| 164 | - && $this->ID() // ensure registration is in the db |
|
| 165 | - ) { |
|
| 166 | - // update internal status first |
|
| 167 | - parent::set('STS_ID', $new_STS_ID, $use_default); |
|
| 168 | - // THEN handle other changes that occur when reg status changes |
|
| 169 | - // TO approved |
|
| 170 | - if ($new_STS_ID === EEM_Registration::status_id_approved) { |
|
| 171 | - // reserve a space by incrementing ticket and datetime sold values |
|
| 172 | - $this->reserveRegistrationSpace(); |
|
| 173 | - do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context); |
|
| 174 | - // OR FROM approved |
|
| 175 | - } elseif ($old_STS_ID === EEM_Registration::status_id_approved) { |
|
| 176 | - // release a space by decrementing ticket and datetime sold values |
|
| 177 | - $this->releaseRegistrationSpace(); |
|
| 178 | - do_action( |
|
| 179 | - 'AHEE__EE_Registration__set_status__from_approved', |
|
| 180 | - $this, |
|
| 181 | - $old_STS_ID, |
|
| 182 | - $new_STS_ID, |
|
| 183 | - $context |
|
| 184 | - ); |
|
| 185 | - } |
|
| 186 | - // update status |
|
| 187 | - parent::set('STS_ID', $new_STS_ID, $use_default); |
|
| 188 | - $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context); |
|
| 189 | - if ($this->statusChangeUpdatesTransaction($context)) { |
|
| 190 | - $this->updateTransactionAfterStatusChange(); |
|
| 191 | - } |
|
| 192 | - do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context); |
|
| 193 | - return true; |
|
| 194 | - } |
|
| 195 | - // even though the old value matches the new value, it's still good to |
|
| 196 | - // allow the parent set method to have a say |
|
| 197 | - parent::set('STS_ID', $new_STS_ID, $use_default); |
|
| 198 | - return true; |
|
| 199 | - } |
|
| 200 | - |
|
| 201 | - |
|
| 202 | - /** |
|
| 203 | - * update REGs and TXN when cancelled or declined registrations involved |
|
| 204 | - * |
|
| 205 | - * @param string $new_STS_ID |
|
| 206 | - * @param string $old_STS_ID |
|
| 207 | - * @param ContextInterface|null $context |
|
| 208 | - * @throws EE_Error |
|
| 209 | - * @throws InvalidArgumentException |
|
| 210 | - * @throws InvalidDataTypeException |
|
| 211 | - * @throws InvalidInterfaceException |
|
| 212 | - * @throws ReflectionException |
|
| 213 | - * @throws RuntimeException |
|
| 214 | - */ |
|
| 215 | - private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null) |
|
| 216 | - { |
|
| 217 | - // these reg statuses should not be considered in any calculations involving monies owing |
|
| 218 | - $closed_reg_statuses = EEM_Registration::closed_reg_statuses(); |
|
| 219 | - // true if registration has been cancelled or declined |
|
| 220 | - $this->updateIfCanceled( |
|
| 221 | - $closed_reg_statuses, |
|
| 222 | - $new_STS_ID, |
|
| 223 | - $old_STS_ID, |
|
| 224 | - $context |
|
| 225 | - ); |
|
| 226 | - $this->updateIfReinstated( |
|
| 227 | - $closed_reg_statuses, |
|
| 228 | - $new_STS_ID, |
|
| 229 | - $old_STS_ID, |
|
| 230 | - $context |
|
| 231 | - ); |
|
| 232 | - } |
|
| 233 | - |
|
| 234 | - |
|
| 235 | - /** |
|
| 236 | - * update REGs and TXN when cancelled or declined registrations involved |
|
| 237 | - * |
|
| 238 | - * @param array $closed_reg_statuses |
|
| 239 | - * @param string $new_STS_ID |
|
| 240 | - * @param string $old_STS_ID |
|
| 241 | - * @param ContextInterface|null $context |
|
| 242 | - * @throws EE_Error |
|
| 243 | - * @throws InvalidArgumentException |
|
| 244 | - * @throws InvalidDataTypeException |
|
| 245 | - * @throws InvalidInterfaceException |
|
| 246 | - * @throws ReflectionException |
|
| 247 | - * @throws RuntimeException |
|
| 248 | - */ |
|
| 249 | - private function updateIfCanceled( |
|
| 250 | - array $closed_reg_statuses, |
|
| 251 | - $new_STS_ID, |
|
| 252 | - $old_STS_ID, |
|
| 253 | - ContextInterface $context = null |
|
| 254 | - ) { |
|
| 255 | - // true if registration has been cancelled or declined |
|
| 256 | - if ( |
|
| 257 | - in_array($new_STS_ID, $closed_reg_statuses, true) |
|
| 258 | - && ! in_array($old_STS_ID, $closed_reg_statuses, true) |
|
| 259 | - ) { |
|
| 260 | - /** @type EE_Registration_Processor $registration_processor */ |
|
| 261 | - $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
| 262 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 263 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 264 | - // cancelled or declined registration |
|
| 265 | - $registration_processor->update_registration_after_being_canceled_or_declined( |
|
| 266 | - $this, |
|
| 267 | - $closed_reg_statuses |
|
| 268 | - ); |
|
| 269 | - $transaction_processor->update_transaction_after_canceled_or_declined_registration( |
|
| 270 | - $this, |
|
| 271 | - $closed_reg_statuses, |
|
| 272 | - false |
|
| 273 | - ); |
|
| 274 | - do_action( |
|
| 275 | - 'AHEE__EE_Registration__set_status__canceled_or_declined', |
|
| 276 | - $this, |
|
| 277 | - $old_STS_ID, |
|
| 278 | - $new_STS_ID, |
|
| 279 | - $context |
|
| 280 | - ); |
|
| 281 | - return; |
|
| 282 | - } |
|
| 283 | - } |
|
| 284 | - |
|
| 285 | - |
|
| 286 | - /** |
|
| 287 | - * update REGs and TXN when cancelled or declined registrations involved |
|
| 288 | - * |
|
| 289 | - * @param array $closed_reg_statuses |
|
| 290 | - * @param string $new_STS_ID |
|
| 291 | - * @param string $old_STS_ID |
|
| 292 | - * @param ContextInterface|null $context |
|
| 293 | - * @throws EE_Error |
|
| 294 | - * @throws InvalidArgumentException |
|
| 295 | - * @throws InvalidDataTypeException |
|
| 296 | - * @throws InvalidInterfaceException |
|
| 297 | - * @throws ReflectionException |
|
| 298 | - */ |
|
| 299 | - private function updateIfReinstated( |
|
| 300 | - array $closed_reg_statuses, |
|
| 301 | - $new_STS_ID, |
|
| 302 | - $old_STS_ID, |
|
| 303 | - ContextInterface $context = null |
|
| 304 | - ) { |
|
| 305 | - // true if reinstating cancelled or declined registration |
|
| 306 | - if ( |
|
| 307 | - in_array($old_STS_ID, $closed_reg_statuses, true) |
|
| 308 | - && ! in_array($new_STS_ID, $closed_reg_statuses, true) |
|
| 309 | - ) { |
|
| 310 | - /** @type EE_Registration_Processor $registration_processor */ |
|
| 311 | - $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
| 312 | - /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 313 | - $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 314 | - // reinstating cancelled or declined registration |
|
| 315 | - $registration_processor->update_canceled_or_declined_registration_after_being_reinstated( |
|
| 316 | - $this, |
|
| 317 | - $closed_reg_statuses |
|
| 318 | - ); |
|
| 319 | - $transaction_processor->update_transaction_after_reinstating_canceled_registration( |
|
| 320 | - $this, |
|
| 321 | - $closed_reg_statuses, |
|
| 322 | - false |
|
| 323 | - ); |
|
| 324 | - do_action( |
|
| 325 | - 'AHEE__EE_Registration__set_status__after_reinstated', |
|
| 326 | - $this, |
|
| 327 | - $old_STS_ID, |
|
| 328 | - $new_STS_ID, |
|
| 329 | - $context |
|
| 330 | - ); |
|
| 331 | - } |
|
| 332 | - } |
|
| 333 | - |
|
| 334 | - |
|
| 335 | - /** |
|
| 336 | - * @param ContextInterface|null $context |
|
| 337 | - * @return bool |
|
| 338 | - */ |
|
| 339 | - private function statusChangeUpdatesTransaction(ContextInterface $context = null) |
|
| 340 | - { |
|
| 341 | - $contexts_that_do_not_update_transaction = (array) apply_filters( |
|
| 342 | - 'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction', |
|
| 343 | - array('spco_reg_step_attendee_information_process_registrations'), |
|
| 344 | - $context, |
|
| 345 | - $this |
|
| 346 | - ); |
|
| 347 | - return ! ( |
|
| 348 | - $context instanceof ContextInterface |
|
| 349 | - && in_array($context->slug(), $contexts_that_do_not_update_transaction, true) |
|
| 350 | - ); |
|
| 351 | - } |
|
| 352 | - |
|
| 353 | - |
|
| 354 | - /** |
|
| 355 | - * @throws EE_Error |
|
| 356 | - * @throws EntityNotFoundException |
|
| 357 | - * @throws InvalidArgumentException |
|
| 358 | - * @throws InvalidDataTypeException |
|
| 359 | - * @throws InvalidInterfaceException |
|
| 360 | - * @throws ReflectionException |
|
| 361 | - * @throws RuntimeException |
|
| 362 | - */ |
|
| 363 | - private function updateTransactionAfterStatusChange() |
|
| 364 | - { |
|
| 365 | - /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 366 | - $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 367 | - $transaction_payments->recalculate_transaction_total($this->transaction(), false); |
|
| 368 | - $this->transaction()->update_status_based_on_total_paid(true); |
|
| 369 | - } |
|
| 370 | - |
|
| 371 | - |
|
| 372 | - /** |
|
| 373 | - * get Status ID |
|
| 374 | - */ |
|
| 375 | - public function status_ID() |
|
| 376 | - { |
|
| 377 | - return $this->get('STS_ID'); |
|
| 378 | - } |
|
| 379 | - |
|
| 380 | - |
|
| 381 | - /** |
|
| 382 | - * Gets the ticket this registration is for |
|
| 383 | - * |
|
| 384 | - * @param boolean $include_archived whether to include archived tickets or not. |
|
| 385 | - * |
|
| 386 | - * @return EE_Ticket|EE_Base_Class |
|
| 387 | - * @throws EE_Error |
|
| 388 | - */ |
|
| 389 | - public function ticket($include_archived = true) |
|
| 390 | - { |
|
| 391 | - $query_params = array(); |
|
| 392 | - if ($include_archived) { |
|
| 393 | - $query_params['default_where_conditions'] = 'none'; |
|
| 394 | - } |
|
| 395 | - return $this->get_first_related('Ticket', $query_params); |
|
| 396 | - } |
|
| 397 | - |
|
| 398 | - |
|
| 399 | - /** |
|
| 400 | - * Gets the event this registration is for |
|
| 401 | - * |
|
| 402 | - * @return EE_Event |
|
| 403 | - * @throws EE_Error |
|
| 404 | - * @throws EntityNotFoundException |
|
| 405 | - */ |
|
| 406 | - public function event() |
|
| 407 | - { |
|
| 408 | - $event = $this->get_first_related('Event'); |
|
| 409 | - if (! $event instanceof \EE_Event) { |
|
| 410 | - throw new EntityNotFoundException('Event ID', $this->event_ID()); |
|
| 411 | - } |
|
| 412 | - return $event; |
|
| 413 | - } |
|
| 414 | - |
|
| 415 | - |
|
| 416 | - /** |
|
| 417 | - * Gets the "author" of the registration. Note that for the purposes of registrations, the author will correspond |
|
| 418 | - * with the author of the event this registration is for. |
|
| 419 | - * |
|
| 420 | - * @since 4.5.0 |
|
| 421 | - * @return int |
|
| 422 | - * @throws EE_Error |
|
| 423 | - * @throws EntityNotFoundException |
|
| 424 | - */ |
|
| 425 | - public function wp_user() |
|
| 426 | - { |
|
| 427 | - $event = $this->event(); |
|
| 428 | - if ($event instanceof EE_Event) { |
|
| 429 | - return $event->wp_user(); |
|
| 430 | - } |
|
| 431 | - return 0; |
|
| 432 | - } |
|
| 433 | - |
|
| 434 | - |
|
| 435 | - /** |
|
| 436 | - * increments this registration's related ticket sold and corresponding datetime sold values |
|
| 437 | - * |
|
| 438 | - * @return void |
|
| 439 | - * @throws DomainException |
|
| 440 | - * @throws EE_Error |
|
| 441 | - * @throws EntityNotFoundException |
|
| 442 | - * @throws InvalidArgumentException |
|
| 443 | - * @throws InvalidDataTypeException |
|
| 444 | - * @throws InvalidInterfaceException |
|
| 445 | - * @throws ReflectionException |
|
| 446 | - * @throws UnexpectedEntityException |
|
| 447 | - */ |
|
| 448 | - private function reserveRegistrationSpace() |
|
| 449 | - { |
|
| 450 | - // reserved ticket and datetime counts will be decremented as sold counts are incremented |
|
| 451 | - // so stop tracking that this reg has a ticket reserved |
|
| 452 | - $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')'); |
|
| 453 | - $ticket = $this->ticket(); |
|
| 454 | - $ticket->increaseSold(); |
|
| 455 | - // possibly set event status to sold out |
|
| 456 | - $this->event()->perform_sold_out_status_check(); |
|
| 457 | - } |
|
| 458 | - |
|
| 459 | - |
|
| 460 | - /** |
|
| 461 | - * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values |
|
| 462 | - * |
|
| 463 | - * @return void |
|
| 464 | - * @throws DomainException |
|
| 465 | - * @throws EE_Error |
|
| 466 | - * @throws EntityNotFoundException |
|
| 467 | - * @throws InvalidArgumentException |
|
| 468 | - * @throws InvalidDataTypeException |
|
| 469 | - * @throws InvalidInterfaceException |
|
| 470 | - * @throws ReflectionException |
|
| 471 | - * @throws UnexpectedEntityException |
|
| 472 | - */ |
|
| 473 | - private function releaseRegistrationSpace() |
|
| 474 | - { |
|
| 475 | - $ticket = $this->ticket(); |
|
| 476 | - $ticket->decreaseSold(); |
|
| 477 | - // possibly change event status from sold out back to previous status |
|
| 478 | - $this->event()->perform_sold_out_status_check(); |
|
| 479 | - } |
|
| 480 | - |
|
| 481 | - |
|
| 482 | - /** |
|
| 483 | - * tracks this registration's ticket reservation in extra meta |
|
| 484 | - * and can increment related ticket reserved and corresponding datetime reserved values |
|
| 485 | - * |
|
| 486 | - * @param bool $update_ticket if true, will increment ticket and datetime reserved count |
|
| 487 | - * @return void |
|
| 488 | - * @throws EE_Error |
|
| 489 | - * @throws InvalidArgumentException |
|
| 490 | - * @throws InvalidDataTypeException |
|
| 491 | - * @throws InvalidInterfaceException |
|
| 492 | - * @throws ReflectionException |
|
| 493 | - */ |
|
| 494 | - public function reserve_ticket($update_ticket = false, $source = 'unknown') |
|
| 495 | - { |
|
| 496 | - // only reserve ticket if space is not currently reserved |
|
| 497 | - if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) { |
|
| 498 | - $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}"); |
|
| 499 | - // IMPORTANT !!! |
|
| 500 | - // although checking $update_ticket first would be more efficient, |
|
| 501 | - // we NEED to ALWAYS call update_extra_meta(), which is why that is done first |
|
| 502 | - if ( |
|
| 503 | - $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) |
|
| 504 | - && $update_ticket |
|
| 505 | - ) { |
|
| 506 | - $ticket = $this->ticket(); |
|
| 507 | - $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')'); |
|
| 508 | - $ticket->save(); |
|
| 509 | - } |
|
| 510 | - } |
|
| 511 | - } |
|
| 512 | - |
|
| 513 | - |
|
| 514 | - /** |
|
| 515 | - * stops tracking this registration's ticket reservation in extra meta |
|
| 516 | - * decrements (subtracts) related ticket reserved and corresponding datetime reserved values |
|
| 517 | - * |
|
| 518 | - * @param bool $update_ticket if true, will decrement ticket and datetime reserved count |
|
| 519 | - * @return void |
|
| 520 | - * @throws EE_Error |
|
| 521 | - * @throws InvalidArgumentException |
|
| 522 | - * @throws InvalidDataTypeException |
|
| 523 | - * @throws InvalidInterfaceException |
|
| 524 | - * @throws ReflectionException |
|
| 525 | - */ |
|
| 526 | - public function release_reserved_ticket($update_ticket = false, $source = 'unknown') |
|
| 527 | - { |
|
| 528 | - // only release ticket if space is currently reserved |
|
| 529 | - if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) { |
|
| 530 | - $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}"); |
|
| 531 | - // IMPORTANT !!! |
|
| 532 | - // although checking $update_ticket first would be more efficient, |
|
| 533 | - // we NEED to ALWAYS call update_extra_meta(), which is why that is done first |
|
| 534 | - if ( |
|
| 535 | - $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false) |
|
| 536 | - && $update_ticket |
|
| 537 | - ) { |
|
| 538 | - $ticket = $this->ticket(); |
|
| 539 | - $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')'); |
|
| 540 | - } |
|
| 541 | - } |
|
| 542 | - } |
|
| 543 | - |
|
| 544 | - |
|
| 545 | - /** |
|
| 546 | - * Set Attendee ID |
|
| 547 | - * |
|
| 548 | - * @param int $ATT_ID Attendee ID |
|
| 549 | - * @throws EE_Error |
|
| 550 | - * @throws RuntimeException |
|
| 551 | - */ |
|
| 552 | - public function set_attendee_id($ATT_ID = 0) |
|
| 553 | - { |
|
| 554 | - $this->set('ATT_ID', $ATT_ID); |
|
| 555 | - } |
|
| 556 | - |
|
| 557 | - |
|
| 558 | - /** |
|
| 559 | - * Set Transaction ID |
|
| 560 | - * |
|
| 561 | - * @param int $TXN_ID Transaction ID |
|
| 562 | - * @throws EE_Error |
|
| 563 | - * @throws RuntimeException |
|
| 564 | - */ |
|
| 565 | - public function set_transaction_id($TXN_ID = 0) |
|
| 566 | - { |
|
| 567 | - $this->set('TXN_ID', $TXN_ID); |
|
| 568 | - } |
|
| 569 | - |
|
| 570 | - |
|
| 571 | - /** |
|
| 572 | - * Set Session |
|
| 573 | - * |
|
| 574 | - * @param string $REG_session PHP Session ID |
|
| 575 | - * @throws EE_Error |
|
| 576 | - * @throws RuntimeException |
|
| 577 | - */ |
|
| 578 | - public function set_session($REG_session = '') |
|
| 579 | - { |
|
| 580 | - $this->set('REG_session', $REG_session); |
|
| 581 | - } |
|
| 582 | - |
|
| 583 | - |
|
| 584 | - /** |
|
| 585 | - * Set Registration URL Link |
|
| 586 | - * |
|
| 587 | - * @param string $REG_url_link Registration URL Link |
|
| 588 | - * @throws EE_Error |
|
| 589 | - * @throws RuntimeException |
|
| 590 | - */ |
|
| 591 | - public function set_reg_url_link($REG_url_link = '') |
|
| 592 | - { |
|
| 593 | - $this->set('REG_url_link', $REG_url_link); |
|
| 594 | - } |
|
| 595 | - |
|
| 596 | - |
|
| 597 | - /** |
|
| 598 | - * Set Attendee Counter |
|
| 599 | - * |
|
| 600 | - * @param int $REG_count Primary Attendee |
|
| 601 | - * @throws EE_Error |
|
| 602 | - * @throws RuntimeException |
|
| 603 | - */ |
|
| 604 | - public function set_count($REG_count = 1) |
|
| 605 | - { |
|
| 606 | - $this->set('REG_count', $REG_count); |
|
| 607 | - } |
|
| 608 | - |
|
| 609 | - |
|
| 610 | - /** |
|
| 611 | - * Set Group Size |
|
| 612 | - * |
|
| 613 | - * @param boolean $REG_group_size Group Registration |
|
| 614 | - * @throws EE_Error |
|
| 615 | - * @throws RuntimeException |
|
| 616 | - */ |
|
| 617 | - public function set_group_size($REG_group_size = false) |
|
| 618 | - { |
|
| 619 | - $this->set('REG_group_size', $REG_group_size); |
|
| 620 | - } |
|
| 621 | - |
|
| 622 | - |
|
| 623 | - /** |
|
| 624 | - * is_not_approved - convenience method that returns TRUE if REG status ID == |
|
| 625 | - * EEM_Registration::status_id_not_approved |
|
| 626 | - * |
|
| 627 | - * @return boolean |
|
| 628 | - */ |
|
| 629 | - public function is_not_approved() |
|
| 630 | - { |
|
| 631 | - return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false; |
|
| 632 | - } |
|
| 633 | - |
|
| 634 | - |
|
| 635 | - /** |
|
| 636 | - * is_pending_payment - convenience method that returns TRUE if REG status ID == |
|
| 637 | - * EEM_Registration::status_id_pending_payment |
|
| 638 | - * |
|
| 639 | - * @return boolean |
|
| 640 | - */ |
|
| 641 | - public function is_pending_payment() |
|
| 642 | - { |
|
| 643 | - return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false; |
|
| 644 | - } |
|
| 645 | - |
|
| 646 | - |
|
| 647 | - /** |
|
| 648 | - * is_approved - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved |
|
| 649 | - * |
|
| 650 | - * @return boolean |
|
| 651 | - */ |
|
| 652 | - public function is_approved() |
|
| 653 | - { |
|
| 654 | - return $this->status_ID() == EEM_Registration::status_id_approved ? true : false; |
|
| 655 | - } |
|
| 656 | - |
|
| 657 | - |
|
| 658 | - /** |
|
| 659 | - * is_cancelled - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled |
|
| 660 | - * |
|
| 661 | - * @return boolean |
|
| 662 | - */ |
|
| 663 | - public function is_cancelled() |
|
| 664 | - { |
|
| 665 | - return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false; |
|
| 666 | - } |
|
| 667 | - |
|
| 668 | - |
|
| 669 | - /** |
|
| 670 | - * is_declined - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined |
|
| 671 | - * |
|
| 672 | - * @return boolean |
|
| 673 | - */ |
|
| 674 | - public function is_declined() |
|
| 675 | - { |
|
| 676 | - return $this->status_ID() == EEM_Registration::status_id_declined ? true : false; |
|
| 677 | - } |
|
| 678 | - |
|
| 679 | - |
|
| 680 | - /** |
|
| 681 | - * is_incomplete - convenience method that returns TRUE if REG status ID == |
|
| 682 | - * EEM_Registration::status_id_incomplete |
|
| 683 | - * |
|
| 684 | - * @return boolean |
|
| 685 | - */ |
|
| 686 | - public function is_incomplete() |
|
| 687 | - { |
|
| 688 | - return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false; |
|
| 689 | - } |
|
| 690 | - |
|
| 691 | - |
|
| 692 | - /** |
|
| 693 | - * Set Registration Date |
|
| 694 | - * |
|
| 695 | - * @param mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of |
|
| 696 | - * Date |
|
| 697 | - * @throws EE_Error |
|
| 698 | - * @throws RuntimeException |
|
| 699 | - */ |
|
| 700 | - public function set_reg_date($REG_date = false) |
|
| 701 | - { |
|
| 702 | - $this->set('REG_date', $REG_date); |
|
| 703 | - } |
|
| 704 | - |
|
| 705 | - |
|
| 706 | - /** |
|
| 707 | - * Set final price owing for this registration after all ticket/price modifications |
|
| 708 | - * |
|
| 709 | - * @access public |
|
| 710 | - * @param float $REG_final_price |
|
| 711 | - * @throws EE_Error |
|
| 712 | - * @throws RuntimeException |
|
| 713 | - */ |
|
| 714 | - public function set_final_price($REG_final_price = 0.00) |
|
| 715 | - { |
|
| 716 | - $this->set('REG_final_price', $REG_final_price); |
|
| 717 | - } |
|
| 718 | - |
|
| 719 | - |
|
| 720 | - /** |
|
| 721 | - * Set amount paid towards this registration's final price |
|
| 722 | - * |
|
| 723 | - * @access public |
|
| 724 | - * @param float $REG_paid |
|
| 725 | - * @throws EE_Error |
|
| 726 | - * @throws RuntimeException |
|
| 727 | - */ |
|
| 728 | - public function set_paid($REG_paid = 0.00) |
|
| 729 | - { |
|
| 730 | - $this->set('REG_paid', $REG_paid); |
|
| 731 | - } |
|
| 732 | - |
|
| 733 | - |
|
| 734 | - /** |
|
| 735 | - * Attendee Is Going |
|
| 736 | - * |
|
| 737 | - * @param boolean $REG_att_is_going Attendee Is Going |
|
| 738 | - * @throws EE_Error |
|
| 739 | - * @throws RuntimeException |
|
| 740 | - */ |
|
| 741 | - public function set_att_is_going($REG_att_is_going = false) |
|
| 742 | - { |
|
| 743 | - $this->set('REG_att_is_going', $REG_att_is_going); |
|
| 744 | - } |
|
| 745 | - |
|
| 746 | - |
|
| 747 | - /** |
|
| 748 | - * Gets the related attendee |
|
| 749 | - * |
|
| 750 | - * @return EE_Attendee |
|
| 751 | - * @throws EE_Error |
|
| 752 | - */ |
|
| 753 | - public function attendee() |
|
| 754 | - { |
|
| 755 | - return $this->get_first_related('Attendee'); |
|
| 756 | - } |
|
| 757 | - |
|
| 758 | - /** |
|
| 759 | - * Gets the name of the attendee. |
|
| 760 | - * @since $VID:$ |
|
| 761 | - * @param bool $apply_html_entities set to true if you want to use HTML entities. |
|
| 762 | - * @return string |
|
| 763 | - * @throws EE_Error |
|
| 764 | - * @throws InvalidArgumentException |
|
| 765 | - * @throws InvalidDataTypeException |
|
| 766 | - * @throws InvalidInterfaceException |
|
| 767 | - * @throws ReflectionException |
|
| 768 | - */ |
|
| 769 | - public function attendeeName($apply_html_entities = false) |
|
| 770 | - { |
|
| 771 | - $attendee = $this->get_first_related('Attendee'); |
|
| 772 | - if ($attendee instanceof EE_Attendee) { |
|
| 773 | - $attendee_name = $attendee->full_name($apply_html_entities); |
|
| 774 | - } else { |
|
| 775 | - $attendee_name = esc_html__('Unknown', 'event_espresso'); |
|
| 776 | - } |
|
| 777 | - return $attendee_name; |
|
| 778 | - } |
|
| 779 | - |
|
| 780 | - |
|
| 781 | - /** |
|
| 782 | - * get Event ID |
|
| 783 | - */ |
|
| 784 | - public function event_ID() |
|
| 785 | - { |
|
| 786 | - return $this->get('EVT_ID'); |
|
| 787 | - } |
|
| 788 | - |
|
| 789 | - |
|
| 790 | - /** |
|
| 791 | - * get Event ID |
|
| 792 | - */ |
|
| 793 | - public function event_name() |
|
| 794 | - { |
|
| 795 | - $event = $this->event_obj(); |
|
| 796 | - if ($event) { |
|
| 797 | - return $event->name(); |
|
| 798 | - } else { |
|
| 799 | - return null; |
|
| 800 | - } |
|
| 801 | - } |
|
| 802 | - |
|
| 803 | - |
|
| 804 | - /** |
|
| 805 | - * Fetches the event this registration is for |
|
| 806 | - * |
|
| 807 | - * @return EE_Event |
|
| 808 | - * @throws EE_Error |
|
| 809 | - */ |
|
| 810 | - public function event_obj() |
|
| 811 | - { |
|
| 812 | - return $this->get_first_related('Event'); |
|
| 813 | - } |
|
| 814 | - |
|
| 815 | - |
|
| 816 | - /** |
|
| 817 | - * get Attendee ID |
|
| 818 | - */ |
|
| 819 | - public function attendee_ID() |
|
| 820 | - { |
|
| 821 | - return $this->get('ATT_ID'); |
|
| 822 | - } |
|
| 823 | - |
|
| 824 | - |
|
| 825 | - /** |
|
| 826 | - * get PHP Session ID |
|
| 827 | - */ |
|
| 828 | - public function session_ID() |
|
| 829 | - { |
|
| 830 | - return $this->get('REG_session'); |
|
| 831 | - } |
|
| 832 | - |
|
| 833 | - |
|
| 834 | - /** |
|
| 835 | - * Gets the string which represents the URL trigger for the receipt template in the message template system. |
|
| 836 | - * |
|
| 837 | - * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
| 838 | - * @return string |
|
| 839 | - */ |
|
| 840 | - public function receipt_url($messenger = 'html') |
|
| 841 | - { |
|
| 842 | - |
|
| 843 | - /** |
|
| 844 | - * The below will be deprecated one version after this. We check first if there is a custom receipt template |
|
| 845 | - * already in use on old system. If there is then we just return the standard url for it. |
|
| 846 | - * |
|
| 847 | - * @since 4.5.0 |
|
| 848 | - */ |
|
| 849 | - $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php'; |
|
| 850 | - $has_custom = EEH_Template::locate_template( |
|
| 851 | - $template_relative_path, |
|
| 852 | - array(), |
|
| 853 | - true, |
|
| 854 | - true, |
|
| 855 | - true |
|
| 856 | - ); |
|
| 857 | - |
|
| 858 | - if ($has_custom) { |
|
| 859 | - return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch')); |
|
| 860 | - } |
|
| 861 | - return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt'); |
|
| 862 | - } |
|
| 863 | - |
|
| 864 | - |
|
| 865 | - /** |
|
| 866 | - * Gets the string which represents the URL trigger for the invoice template in the message template system. |
|
| 867 | - * |
|
| 868 | - * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
| 869 | - * @return string |
|
| 870 | - * @throws EE_Error |
|
| 871 | - */ |
|
| 872 | - public function invoice_url($messenger = 'html') |
|
| 873 | - { |
|
| 874 | - /** |
|
| 875 | - * The below will be deprecated one version after this. We check first if there is a custom invoice template |
|
| 876 | - * already in use on old system. If there is then we just return the standard url for it. |
|
| 877 | - * |
|
| 878 | - * @since 4.5.0 |
|
| 879 | - */ |
|
| 880 | - $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php'; |
|
| 881 | - $has_custom = EEH_Template::locate_template( |
|
| 882 | - $template_relative_path, |
|
| 883 | - array(), |
|
| 884 | - true, |
|
| 885 | - true, |
|
| 886 | - true |
|
| 887 | - ); |
|
| 888 | - |
|
| 889 | - if ($has_custom) { |
|
| 890 | - if ($messenger == 'html') { |
|
| 891 | - return $this->invoice_url('launch'); |
|
| 892 | - } |
|
| 893 | - $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice'; |
|
| 894 | - |
|
| 895 | - $query_args = array('ee' => $route, 'id' => $this->reg_url_link()); |
|
| 896 | - if ($messenger == 'html') { |
|
| 897 | - $query_args['html'] = true; |
|
| 898 | - } |
|
| 899 | - return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id)); |
|
| 900 | - } |
|
| 901 | - return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice'); |
|
| 902 | - } |
|
| 903 | - |
|
| 904 | - |
|
| 905 | - /** |
|
| 906 | - * get Registration URL Link |
|
| 907 | - * |
|
| 908 | - * @access public |
|
| 909 | - * @return string |
|
| 910 | - * @throws EE_Error |
|
| 911 | - */ |
|
| 912 | - public function reg_url_link() |
|
| 913 | - { |
|
| 914 | - return (string) $this->get('REG_url_link'); |
|
| 915 | - } |
|
| 916 | - |
|
| 917 | - |
|
| 918 | - /** |
|
| 919 | - * Echoes out invoice_url() |
|
| 920 | - * |
|
| 921 | - * @param string $type 'download','launch', or 'html' (default is 'launch') |
|
| 922 | - * @return void |
|
| 923 | - * @throws EE_Error |
|
| 924 | - */ |
|
| 925 | - public function e_invoice_url($type = 'launch') |
|
| 926 | - { |
|
| 927 | - echo $this->invoice_url($type); |
|
| 928 | - } |
|
| 929 | - |
|
| 930 | - |
|
| 931 | - /** |
|
| 932 | - * Echoes out payment_overview_url |
|
| 933 | - */ |
|
| 934 | - public function e_payment_overview_url() |
|
| 935 | - { |
|
| 936 | - echo $this->payment_overview_url(); |
|
| 937 | - } |
|
| 938 | - |
|
| 939 | - |
|
| 940 | - /** |
|
| 941 | - * Gets the URL for the checkout payment options reg step |
|
| 942 | - * with this registration's REG_url_link added as a query parameter |
|
| 943 | - * |
|
| 944 | - * @param bool $clear_session Set to true when you want to clear the session on revisiting the |
|
| 945 | - * payment overview url. |
|
| 946 | - * @return string |
|
| 947 | - * @throws InvalidInterfaceException |
|
| 948 | - * @throws InvalidDataTypeException |
|
| 949 | - * @throws EE_Error |
|
| 950 | - * @throws InvalidArgumentException |
|
| 951 | - */ |
|
| 952 | - public function payment_overview_url($clear_session = false) |
|
| 953 | - { |
|
| 954 | - return add_query_arg( |
|
| 955 | - (array) apply_filters( |
|
| 956 | - 'FHEE__EE_Registration__payment_overview_url__query_args', |
|
| 957 | - array( |
|
| 958 | - 'e_reg_url_link' => $this->reg_url_link(), |
|
| 959 | - 'step' => 'payment_options', |
|
| 960 | - 'revisit' => true, |
|
| 961 | - 'clear_session' => (bool) $clear_session, |
|
| 962 | - ), |
|
| 963 | - $this |
|
| 964 | - ), |
|
| 965 | - EE_Registry::instance()->CFG->core->reg_page_url() |
|
| 966 | - ); |
|
| 967 | - } |
|
| 968 | - |
|
| 969 | - |
|
| 970 | - /** |
|
| 971 | - * Gets the URL for the checkout attendee information reg step |
|
| 972 | - * with this registration's REG_url_link added as a query parameter |
|
| 973 | - * |
|
| 974 | - * @return string |
|
| 975 | - * @throws InvalidInterfaceException |
|
| 976 | - * @throws InvalidDataTypeException |
|
| 977 | - * @throws EE_Error |
|
| 978 | - * @throws InvalidArgumentException |
|
| 979 | - */ |
|
| 980 | - public function edit_attendee_information_url() |
|
| 981 | - { |
|
| 982 | - return add_query_arg( |
|
| 983 | - (array) apply_filters( |
|
| 984 | - 'FHEE__EE_Registration__edit_attendee_information_url__query_args', |
|
| 985 | - array( |
|
| 986 | - 'e_reg_url_link' => $this->reg_url_link(), |
|
| 987 | - 'step' => 'attendee_information', |
|
| 988 | - 'revisit' => true, |
|
| 989 | - ), |
|
| 990 | - $this |
|
| 991 | - ), |
|
| 992 | - EE_Registry::instance()->CFG->core->reg_page_url() |
|
| 993 | - ); |
|
| 994 | - } |
|
| 995 | - |
|
| 996 | - |
|
| 997 | - /** |
|
| 998 | - * Simply generates and returns the appropriate admin_url link to edit this registration |
|
| 999 | - * |
|
| 1000 | - * @return string |
|
| 1001 | - * @throws EE_Error |
|
| 1002 | - */ |
|
| 1003 | - public function get_admin_edit_url() |
|
| 1004 | - { |
|
| 1005 | - return EEH_URL::add_query_args_and_nonce( |
|
| 1006 | - array( |
|
| 1007 | - 'page' => 'espresso_registrations', |
|
| 1008 | - 'action' => 'view_registration', |
|
| 1009 | - '_REG_ID' => $this->ID(), |
|
| 1010 | - ), |
|
| 1011 | - admin_url('admin.php') |
|
| 1012 | - ); |
|
| 1013 | - } |
|
| 1014 | - |
|
| 1015 | - |
|
| 1016 | - /** |
|
| 1017 | - * is_primary_registrant? |
|
| 1018 | - */ |
|
| 1019 | - public function is_primary_registrant() |
|
| 1020 | - { |
|
| 1021 | - return $this->get('REG_count') === 1 ? true : false; |
|
| 1022 | - } |
|
| 1023 | - |
|
| 1024 | - |
|
| 1025 | - /** |
|
| 1026 | - * This returns the primary registration object for this registration group (which may be this object). |
|
| 1027 | - * |
|
| 1028 | - * @return EE_Registration |
|
| 1029 | - * @throws EE_Error |
|
| 1030 | - */ |
|
| 1031 | - public function get_primary_registration() |
|
| 1032 | - { |
|
| 1033 | - if ($this->is_primary_registrant()) { |
|
| 1034 | - return $this; |
|
| 1035 | - } |
|
| 1036 | - |
|
| 1037 | - // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1 |
|
| 1038 | - /** @var EE_Registration $primary_registrant */ |
|
| 1039 | - $primary_registrant = EEM_Registration::instance()->get_one( |
|
| 1040 | - array( |
|
| 1041 | - array( |
|
| 1042 | - 'TXN_ID' => $this->transaction_ID(), |
|
| 1043 | - 'REG_count' => 1, |
|
| 1044 | - ), |
|
| 1045 | - ) |
|
| 1046 | - ); |
|
| 1047 | - return $primary_registrant; |
|
| 1048 | - } |
|
| 1049 | - |
|
| 1050 | - |
|
| 1051 | - /** |
|
| 1052 | - * get Attendee Number |
|
| 1053 | - * |
|
| 1054 | - * @access public |
|
| 1055 | - */ |
|
| 1056 | - public function count() |
|
| 1057 | - { |
|
| 1058 | - return $this->get('REG_count'); |
|
| 1059 | - } |
|
| 1060 | - |
|
| 1061 | - |
|
| 1062 | - /** |
|
| 1063 | - * get Group Size |
|
| 1064 | - */ |
|
| 1065 | - public function group_size() |
|
| 1066 | - { |
|
| 1067 | - return $this->get('REG_group_size'); |
|
| 1068 | - } |
|
| 1069 | - |
|
| 1070 | - |
|
| 1071 | - /** |
|
| 1072 | - * get Registration Date |
|
| 1073 | - */ |
|
| 1074 | - public function date() |
|
| 1075 | - { |
|
| 1076 | - return $this->get('REG_date'); |
|
| 1077 | - } |
|
| 1078 | - |
|
| 1079 | - |
|
| 1080 | - /** |
|
| 1081 | - * gets a pretty date |
|
| 1082 | - * |
|
| 1083 | - * @param string $date_format |
|
| 1084 | - * @param string $time_format |
|
| 1085 | - * @return string |
|
| 1086 | - * @throws EE_Error |
|
| 1087 | - */ |
|
| 1088 | - public function pretty_date($date_format = null, $time_format = null) |
|
| 1089 | - { |
|
| 1090 | - return $this->get_datetime('REG_date', $date_format, $time_format); |
|
| 1091 | - } |
|
| 1092 | - |
|
| 1093 | - |
|
| 1094 | - /** |
|
| 1095 | - * final_price |
|
| 1096 | - * the registration's share of the transaction total, so that the |
|
| 1097 | - * sum of all the transaction's REG_final_prices equal the transaction's total |
|
| 1098 | - * |
|
| 1099 | - * @return float |
|
| 1100 | - * @throws EE_Error |
|
| 1101 | - */ |
|
| 1102 | - public function final_price() |
|
| 1103 | - { |
|
| 1104 | - return $this->get('REG_final_price'); |
|
| 1105 | - } |
|
| 1106 | - |
|
| 1107 | - |
|
| 1108 | - /** |
|
| 1109 | - * pretty_final_price |
|
| 1110 | - * final price as formatted string, with correct decimal places and currency symbol |
|
| 1111 | - * |
|
| 1112 | - * @return string |
|
| 1113 | - * @throws EE_Error |
|
| 1114 | - */ |
|
| 1115 | - public function pretty_final_price() |
|
| 1116 | - { |
|
| 1117 | - return $this->get_pretty('REG_final_price'); |
|
| 1118 | - } |
|
| 1119 | - |
|
| 1120 | - |
|
| 1121 | - /** |
|
| 1122 | - * get paid (yeah) |
|
| 1123 | - * |
|
| 1124 | - * @return float |
|
| 1125 | - * @throws EE_Error |
|
| 1126 | - */ |
|
| 1127 | - public function paid() |
|
| 1128 | - { |
|
| 1129 | - return $this->get('REG_paid'); |
|
| 1130 | - } |
|
| 1131 | - |
|
| 1132 | - |
|
| 1133 | - /** |
|
| 1134 | - * pretty_paid |
|
| 1135 | - * |
|
| 1136 | - * @return float |
|
| 1137 | - * @throws EE_Error |
|
| 1138 | - */ |
|
| 1139 | - public function pretty_paid() |
|
| 1140 | - { |
|
| 1141 | - return $this->get_pretty('REG_paid'); |
|
| 1142 | - } |
|
| 1143 | - |
|
| 1144 | - |
|
| 1145 | - /** |
|
| 1146 | - * owes_monies_and_can_pay |
|
| 1147 | - * whether or not this registration has monies owing and it's' status allows payment |
|
| 1148 | - * |
|
| 1149 | - * @param array $requires_payment |
|
| 1150 | - * @return bool |
|
| 1151 | - * @throws EE_Error |
|
| 1152 | - */ |
|
| 1153 | - public function owes_monies_and_can_pay($requires_payment = array()) |
|
| 1154 | - { |
|
| 1155 | - // these reg statuses require payment (if event is not free) |
|
| 1156 | - $requires_payment = ! empty($requires_payment) |
|
| 1157 | - ? $requires_payment |
|
| 1158 | - : EEM_Registration::reg_statuses_that_allow_payment(); |
|
| 1159 | - if ( |
|
| 1160 | - in_array($this->status_ID(), $requires_payment) && |
|
| 1161 | - $this->final_price() != 0 && |
|
| 1162 | - $this->final_price() != $this->paid() |
|
| 1163 | - ) { |
|
| 1164 | - return true; |
|
| 1165 | - } else { |
|
| 1166 | - return false; |
|
| 1167 | - } |
|
| 1168 | - } |
|
| 1169 | - |
|
| 1170 | - |
|
| 1171 | - /** |
|
| 1172 | - * Prints out the return value of $this->pretty_status() |
|
| 1173 | - * |
|
| 1174 | - * @param bool $show_icons |
|
| 1175 | - * @return void |
|
| 1176 | - * @throws EE_Error |
|
| 1177 | - */ |
|
| 1178 | - public function e_pretty_status($show_icons = false) |
|
| 1179 | - { |
|
| 1180 | - echo $this->pretty_status($show_icons); |
|
| 1181 | - } |
|
| 1182 | - |
|
| 1183 | - |
|
| 1184 | - /** |
|
| 1185 | - * Returns a nice version of the status for displaying to customers |
|
| 1186 | - * |
|
| 1187 | - * @param bool $show_icons |
|
| 1188 | - * @return string |
|
| 1189 | - * @throws EE_Error |
|
| 1190 | - */ |
|
| 1191 | - public function pretty_status($show_icons = false) |
|
| 1192 | - { |
|
| 1193 | - $status = EEM_Status::instance()->localized_status( |
|
| 1194 | - array($this->status_ID() => esc_html__('unknown', 'event_espresso')), |
|
| 1195 | - false, |
|
| 1196 | - 'sentence' |
|
| 1197 | - ); |
|
| 1198 | - $icon = ''; |
|
| 1199 | - switch ($this->status_ID()) { |
|
| 1200 | - case EEM_Registration::status_id_approved: |
|
| 1201 | - $icon = $show_icons |
|
| 1202 | - ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>' |
|
| 1203 | - : ''; |
|
| 1204 | - break; |
|
| 1205 | - case EEM_Registration::status_id_pending_payment: |
|
| 1206 | - $icon = $show_icons |
|
| 1207 | - ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>' |
|
| 1208 | - : ''; |
|
| 1209 | - break; |
|
| 1210 | - case EEM_Registration::status_id_not_approved: |
|
| 1211 | - $icon = $show_icons |
|
| 1212 | - ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>' |
|
| 1213 | - : ''; |
|
| 1214 | - break; |
|
| 1215 | - case EEM_Registration::status_id_cancelled: |
|
| 1216 | - $icon = $show_icons |
|
| 1217 | - ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>' |
|
| 1218 | - : ''; |
|
| 1219 | - break; |
|
| 1220 | - case EEM_Registration::status_id_incomplete: |
|
| 1221 | - $icon = $show_icons |
|
| 1222 | - ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>' |
|
| 1223 | - : ''; |
|
| 1224 | - break; |
|
| 1225 | - case EEM_Registration::status_id_declined: |
|
| 1226 | - $icon = $show_icons |
|
| 1227 | - ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' |
|
| 1228 | - : ''; |
|
| 1229 | - break; |
|
| 1230 | - case EEM_Registration::status_id_wait_list: |
|
| 1231 | - $icon = $show_icons |
|
| 1232 | - ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>' |
|
| 1233 | - : ''; |
|
| 1234 | - break; |
|
| 1235 | - } |
|
| 1236 | - return $icon . $status[ $this->status_ID() ]; |
|
| 1237 | - } |
|
| 1238 | - |
|
| 1239 | - |
|
| 1240 | - /** |
|
| 1241 | - * get Attendee Is Going |
|
| 1242 | - */ |
|
| 1243 | - public function att_is_going() |
|
| 1244 | - { |
|
| 1245 | - return $this->get('REG_att_is_going'); |
|
| 1246 | - } |
|
| 1247 | - |
|
| 1248 | - |
|
| 1249 | - /** |
|
| 1250 | - * Gets related answers |
|
| 1251 | - * |
|
| 1252 | - * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1253 | - * @return EE_Answer[] |
|
| 1254 | - * @throws EE_Error |
|
| 1255 | - */ |
|
| 1256 | - public function answers($query_params = null) |
|
| 1257 | - { |
|
| 1258 | - return $this->get_many_related('Answer', $query_params); |
|
| 1259 | - } |
|
| 1260 | - |
|
| 1261 | - |
|
| 1262 | - /** |
|
| 1263 | - * Gets the registration's answer value to the specified question |
|
| 1264 | - * (either the question's ID or a question object) |
|
| 1265 | - * |
|
| 1266 | - * @param EE_Question|int $question |
|
| 1267 | - * @param bool $pretty_value |
|
| 1268 | - * @return array|string if pretty_value= true, the result will always be a string |
|
| 1269 | - * (because the answer might be an array of answer values, so passing pretty_value=true |
|
| 1270 | - * will convert it into some kind of string) |
|
| 1271 | - * @throws EE_Error |
|
| 1272 | - */ |
|
| 1273 | - public function answer_value_to_question($question, $pretty_value = true) |
|
| 1274 | - { |
|
| 1275 | - $question_id = EEM_Question::instance()->ensure_is_ID($question); |
|
| 1276 | - return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value); |
|
| 1277 | - } |
|
| 1278 | - |
|
| 1279 | - |
|
| 1280 | - /** |
|
| 1281 | - * question_groups |
|
| 1282 | - * returns an array of EE_Question_Group objects for this registration |
|
| 1283 | - * |
|
| 1284 | - * @return EE_Question_Group[] |
|
| 1285 | - * @throws EE_Error |
|
| 1286 | - * @throws InvalidArgumentException |
|
| 1287 | - * @throws InvalidDataTypeException |
|
| 1288 | - * @throws InvalidInterfaceException |
|
| 1289 | - * @throws ReflectionException |
|
| 1290 | - */ |
|
| 1291 | - public function question_groups() |
|
| 1292 | - { |
|
| 1293 | - return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this); |
|
| 1294 | - } |
|
| 1295 | - |
|
| 1296 | - |
|
| 1297 | - /** |
|
| 1298 | - * count_question_groups |
|
| 1299 | - * returns a count of the number of EE_Question_Group objects for this registration |
|
| 1300 | - * |
|
| 1301 | - * @return int |
|
| 1302 | - * @throws EE_Error |
|
| 1303 | - * @throws EntityNotFoundException |
|
| 1304 | - * @throws InvalidArgumentException |
|
| 1305 | - * @throws InvalidDataTypeException |
|
| 1306 | - * @throws InvalidInterfaceException |
|
| 1307 | - * @throws ReflectionException |
|
| 1308 | - */ |
|
| 1309 | - public function count_question_groups() |
|
| 1310 | - { |
|
| 1311 | - return EEM_Event::instance()->count_related( |
|
| 1312 | - $this->event_ID(), |
|
| 1313 | - 'Question_Group', |
|
| 1314 | - [ |
|
| 1315 | - [ |
|
| 1316 | - 'Event_Question_Group.' |
|
| 1317 | - . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true, |
|
| 1318 | - ] |
|
| 1319 | - ] |
|
| 1320 | - ); |
|
| 1321 | - } |
|
| 1322 | - |
|
| 1323 | - |
|
| 1324 | - /** |
|
| 1325 | - * Returns the registration date in the 'standard' string format |
|
| 1326 | - * (function may be improved in the future to allow for different formats and timezones) |
|
| 1327 | - * |
|
| 1328 | - * @return string |
|
| 1329 | - * @throws EE_Error |
|
| 1330 | - */ |
|
| 1331 | - public function reg_date() |
|
| 1332 | - { |
|
| 1333 | - return $this->get_datetime('REG_date'); |
|
| 1334 | - } |
|
| 1335 | - |
|
| 1336 | - |
|
| 1337 | - /** |
|
| 1338 | - * Gets the datetime-ticket for this registration (ie, it can be used to isolate |
|
| 1339 | - * the ticket this registration purchased, or the datetime they have registered |
|
| 1340 | - * to attend) |
|
| 1341 | - * |
|
| 1342 | - * @return EE_Datetime_Ticket |
|
| 1343 | - * @throws EE_Error |
|
| 1344 | - */ |
|
| 1345 | - public function datetime_ticket() |
|
| 1346 | - { |
|
| 1347 | - return $this->get_first_related('Datetime_Ticket'); |
|
| 1348 | - } |
|
| 1349 | - |
|
| 1350 | - |
|
| 1351 | - /** |
|
| 1352 | - * Sets the registration's datetime_ticket. |
|
| 1353 | - * |
|
| 1354 | - * @param EE_Datetime_Ticket $datetime_ticket |
|
| 1355 | - * @return EE_Datetime_Ticket |
|
| 1356 | - * @throws EE_Error |
|
| 1357 | - */ |
|
| 1358 | - public function set_datetime_ticket($datetime_ticket) |
|
| 1359 | - { |
|
| 1360 | - return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket'); |
|
| 1361 | - } |
|
| 1362 | - |
|
| 1363 | - /** |
|
| 1364 | - * Gets deleted |
|
| 1365 | - * |
|
| 1366 | - * @return bool |
|
| 1367 | - * @throws EE_Error |
|
| 1368 | - */ |
|
| 1369 | - public function deleted() |
|
| 1370 | - { |
|
| 1371 | - return $this->get('REG_deleted'); |
|
| 1372 | - } |
|
| 1373 | - |
|
| 1374 | - /** |
|
| 1375 | - * Sets deleted |
|
| 1376 | - * |
|
| 1377 | - * @param boolean $deleted |
|
| 1378 | - * @return bool |
|
| 1379 | - * @throws EE_Error |
|
| 1380 | - * @throws RuntimeException |
|
| 1381 | - */ |
|
| 1382 | - public function set_deleted($deleted) |
|
| 1383 | - { |
|
| 1384 | - if ($deleted) { |
|
| 1385 | - $this->delete(); |
|
| 1386 | - } else { |
|
| 1387 | - $this->restore(); |
|
| 1388 | - } |
|
| 1389 | - } |
|
| 1390 | - |
|
| 1391 | - |
|
| 1392 | - /** |
|
| 1393 | - * Get the status object of this object |
|
| 1394 | - * |
|
| 1395 | - * @return EE_Status |
|
| 1396 | - * @throws EE_Error |
|
| 1397 | - */ |
|
| 1398 | - public function status_obj() |
|
| 1399 | - { |
|
| 1400 | - return $this->get_first_related('Status'); |
|
| 1401 | - } |
|
| 1402 | - |
|
| 1403 | - |
|
| 1404 | - /** |
|
| 1405 | - * Returns the number of times this registration has checked into any of the datetimes |
|
| 1406 | - * its available for |
|
| 1407 | - * |
|
| 1408 | - * @return int |
|
| 1409 | - * @throws EE_Error |
|
| 1410 | - */ |
|
| 1411 | - public function count_checkins() |
|
| 1412 | - { |
|
| 1413 | - return $this->get_model()->count_related($this, 'Checkin'); |
|
| 1414 | - } |
|
| 1415 | - |
|
| 1416 | - |
|
| 1417 | - /** |
|
| 1418 | - * Returns the number of current Check-ins this registration is checked into for any of the datetimes the |
|
| 1419 | - * registration is for. Note, this is ONLY checked in (does not include checkedout) |
|
| 1420 | - * |
|
| 1421 | - * @return int |
|
| 1422 | - * @throws EE_Error |
|
| 1423 | - */ |
|
| 1424 | - public function count_checkins_not_checkedout() |
|
| 1425 | - { |
|
| 1426 | - return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1))); |
|
| 1427 | - } |
|
| 1428 | - |
|
| 1429 | - |
|
| 1430 | - /** |
|
| 1431 | - * The purpose of this method is simply to check whether this registration can checkin to the given datetime. |
|
| 1432 | - * |
|
| 1433 | - * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
| 1434 | - * @param bool $check_approved This is used to indicate whether the caller wants can_checkin to also |
|
| 1435 | - * consider registration status as well as datetime access. |
|
| 1436 | - * @return bool |
|
| 1437 | - * @throws EE_Error |
|
| 1438 | - */ |
|
| 1439 | - public function can_checkin($DTT_OR_ID, $check_approved = true) |
|
| 1440 | - { |
|
| 1441 | - $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
| 1442 | - |
|
| 1443 | - // first check registration status |
|
| 1444 | - if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) { |
|
| 1445 | - return false; |
|
| 1446 | - } |
|
| 1447 | - // is there a datetime ticket that matches this dtt_ID? |
|
| 1448 | - if ( |
|
| 1449 | - ! (EEM_Datetime_Ticket::instance()->exists( |
|
| 1450 | - array( |
|
| 1451 | - array( |
|
| 1452 | - 'TKT_ID' => $this->get('TKT_ID'), |
|
| 1453 | - 'DTT_ID' => $DTT_ID, |
|
| 1454 | - ), |
|
| 1455 | - ) |
|
| 1456 | - )) |
|
| 1457 | - ) { |
|
| 1458 | - return false; |
|
| 1459 | - } |
|
| 1460 | - |
|
| 1461 | - // final check is against TKT_uses |
|
| 1462 | - return $this->verify_can_checkin_against_TKT_uses($DTT_ID); |
|
| 1463 | - } |
|
| 1464 | - |
|
| 1465 | - |
|
| 1466 | - /** |
|
| 1467 | - * This method verifies whether the user can checkin for the given datetime considering the max uses value set on |
|
| 1468 | - * the ticket. To do this, a query is done to get the count of the datetime records already checked into. If the |
|
| 1469 | - * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses, |
|
| 1470 | - * then return false. Otherwise return true. |
|
| 1471 | - * |
|
| 1472 | - * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
| 1473 | - * @return bool true means can checkin. false means cannot checkin. |
|
| 1474 | - * @throws EE_Error |
|
| 1475 | - */ |
|
| 1476 | - public function verify_can_checkin_against_TKT_uses($DTT_OR_ID) |
|
| 1477 | - { |
|
| 1478 | - $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
| 1479 | - |
|
| 1480 | - if (! $DTT_ID) { |
|
| 1481 | - return false; |
|
| 1482 | - } |
|
| 1483 | - |
|
| 1484 | - $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF; |
|
| 1485 | - |
|
| 1486 | - // if max uses is not set or equals infinity then return true cause its not a factor for whether user can |
|
| 1487 | - // check-in or not. |
|
| 1488 | - if (! $max_uses || $max_uses === EE_INF) { |
|
| 1489 | - return true; |
|
| 1490 | - } |
|
| 1491 | - |
|
| 1492 | - // does this datetime have a checkin record? If so, then the dtt count has already been verified so we can just |
|
| 1493 | - // go ahead and toggle. |
|
| 1494 | - if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) { |
|
| 1495 | - return true; |
|
| 1496 | - } |
|
| 1497 | - |
|
| 1498 | - // made it here so the last check is whether the number of checkins per unique datetime on this registration |
|
| 1499 | - // disallows further check-ins. |
|
| 1500 | - $count_unique_dtt_checkins = EEM_Checkin::instance()->count( |
|
| 1501 | - array( |
|
| 1502 | - array( |
|
| 1503 | - 'REG_ID' => $this->ID(), |
|
| 1504 | - 'CHK_in' => true, |
|
| 1505 | - ), |
|
| 1506 | - ), |
|
| 1507 | - 'DTT_ID', |
|
| 1508 | - true |
|
| 1509 | - ); |
|
| 1510 | - // checkins have already reached their max number of uses |
|
| 1511 | - // so registrant can NOT checkin |
|
| 1512 | - if ($count_unique_dtt_checkins >= $max_uses) { |
|
| 1513 | - EE_Error::add_error( |
|
| 1514 | - esc_html__( |
|
| 1515 | - 'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.', |
|
| 1516 | - 'event_espresso' |
|
| 1517 | - ), |
|
| 1518 | - __FILE__, |
|
| 1519 | - __FUNCTION__, |
|
| 1520 | - __LINE__ |
|
| 1521 | - ); |
|
| 1522 | - return false; |
|
| 1523 | - } |
|
| 1524 | - return true; |
|
| 1525 | - } |
|
| 1526 | - |
|
| 1527 | - |
|
| 1528 | - /** |
|
| 1529 | - * toggle Check-in status for this registration |
|
| 1530 | - * Check-ins are toggled in the following order: |
|
| 1531 | - * never checked in -> checked in |
|
| 1532 | - * checked in -> checked out |
|
| 1533 | - * checked out -> checked in |
|
| 1534 | - * |
|
| 1535 | - * @param int $DTT_ID include specific datetime to toggle Check-in for. |
|
| 1536 | - * If not included or null, then it is assumed latest datetime is being toggled. |
|
| 1537 | - * @param bool $verify If true then can_checkin() is used to verify whether the person |
|
| 1538 | - * can be checked in or not. Otherwise this forces change in checkin status. |
|
| 1539 | - * @return bool|int the chk_in status toggled to OR false if nothing got changed. |
|
| 1540 | - * @throws EE_Error |
|
| 1541 | - */ |
|
| 1542 | - public function toggle_checkin_status($DTT_ID = null, $verify = false) |
|
| 1543 | - { |
|
| 1544 | - if (empty($DTT_ID)) { |
|
| 1545 | - $datetime = $this->get_latest_related_datetime(); |
|
| 1546 | - $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0; |
|
| 1547 | - // verify the registration can checkin for the given DTT_ID |
|
| 1548 | - } elseif (! $this->can_checkin($DTT_ID, $verify)) { |
|
| 1549 | - EE_Error::add_error( |
|
| 1550 | - sprintf( |
|
| 1551 | - esc_html__( |
|
| 1552 | - 'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access', |
|
| 1553 | - 'event_espresso' |
|
| 1554 | - ), |
|
| 1555 | - $this->ID(), |
|
| 1556 | - $DTT_ID |
|
| 1557 | - ), |
|
| 1558 | - __FILE__, |
|
| 1559 | - __FUNCTION__, |
|
| 1560 | - __LINE__ |
|
| 1561 | - ); |
|
| 1562 | - return false; |
|
| 1563 | - } |
|
| 1564 | - $status_paths = array( |
|
| 1565 | - EE_Checkin::status_checked_never => EE_Checkin::status_checked_in, |
|
| 1566 | - EE_Checkin::status_checked_in => EE_Checkin::status_checked_out, |
|
| 1567 | - EE_Checkin::status_checked_out => EE_Checkin::status_checked_in, |
|
| 1568 | - ); |
|
| 1569 | - // start by getting the current status so we know what status we'll be changing to. |
|
| 1570 | - $cur_status = $this->check_in_status_for_datetime($DTT_ID, null); |
|
| 1571 | - $status_to = $status_paths[ $cur_status ]; |
|
| 1572 | - // database only records true for checked IN or false for checked OUT |
|
| 1573 | - // no record ( null ) means checked in NEVER, but we obviously don't save that |
|
| 1574 | - $new_status = $status_to === EE_Checkin::status_checked_in ? true : false; |
|
| 1575 | - // add relation - note Check-ins are always creating new rows |
|
| 1576 | - // because we are keeping track of Check-ins over time. |
|
| 1577 | - // Eventually we'll probably want to show a list table |
|
| 1578 | - // for the individual Check-ins so that they can be managed. |
|
| 1579 | - $checkin = EE_Checkin::new_instance( |
|
| 1580 | - array( |
|
| 1581 | - 'REG_ID' => $this->ID(), |
|
| 1582 | - 'DTT_ID' => $DTT_ID, |
|
| 1583 | - 'CHK_in' => $new_status, |
|
| 1584 | - ) |
|
| 1585 | - ); |
|
| 1586 | - // if the record could not be saved then return false |
|
| 1587 | - if ($checkin->save() === 0) { |
|
| 1588 | - if (WP_DEBUG) { |
|
| 1589 | - global $wpdb; |
|
| 1590 | - $error = sprintf( |
|
| 1591 | - esc_html__( |
|
| 1592 | - 'Registration check in update failed because of the following database error: %1$s%2$s', |
|
| 1593 | - 'event_espresso' |
|
| 1594 | - ), |
|
| 1595 | - '<br />', |
|
| 1596 | - $wpdb->last_error |
|
| 1597 | - ); |
|
| 1598 | - } else { |
|
| 1599 | - $error = esc_html__( |
|
| 1600 | - 'Registration check in update failed because of an unknown database error', |
|
| 1601 | - 'event_espresso' |
|
| 1602 | - ); |
|
| 1603 | - } |
|
| 1604 | - EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__); |
|
| 1605 | - return false; |
|
| 1606 | - } |
|
| 1607 | - // Fire a checked_in and checkout_out action. |
|
| 1608 | - $checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out'; |
|
| 1609 | - do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID); |
|
| 1610 | - return $status_to; |
|
| 1611 | - } |
|
| 1612 | - |
|
| 1613 | - |
|
| 1614 | - /** |
|
| 1615 | - * Returns the latest datetime related to this registration (via the ticket attached to the registration). |
|
| 1616 | - * "Latest" is defined by the `DTT_EVT_start` column. |
|
| 1617 | - * |
|
| 1618 | - * @return EE_Datetime|null |
|
| 1619 | - * @throws EE_Error |
|
| 1620 | - */ |
|
| 1621 | - public function get_latest_related_datetime() |
|
| 1622 | - { |
|
| 1623 | - return EEM_Datetime::instance()->get_one( |
|
| 1624 | - array( |
|
| 1625 | - array( |
|
| 1626 | - 'Ticket.Registration.REG_ID' => $this->ID(), |
|
| 1627 | - ), |
|
| 1628 | - 'order_by' => array('DTT_EVT_start' => 'DESC'), |
|
| 1629 | - ) |
|
| 1630 | - ); |
|
| 1631 | - } |
|
| 1632 | - |
|
| 1633 | - |
|
| 1634 | - /** |
|
| 1635 | - * Returns the earliest datetime related to this registration (via the ticket attached to the registration). |
|
| 1636 | - * "Earliest" is defined by the `DTT_EVT_start` column. |
|
| 1637 | - * |
|
| 1638 | - * @throws EE_Error |
|
| 1639 | - */ |
|
| 1640 | - public function get_earliest_related_datetime() |
|
| 1641 | - { |
|
| 1642 | - return EEM_Datetime::instance()->get_one( |
|
| 1643 | - array( |
|
| 1644 | - array( |
|
| 1645 | - 'Ticket.Registration.REG_ID' => $this->ID(), |
|
| 1646 | - ), |
|
| 1647 | - 'order_by' => array('DTT_EVT_start' => 'ASC'), |
|
| 1648 | - ) |
|
| 1649 | - ); |
|
| 1650 | - } |
|
| 1651 | - |
|
| 1652 | - |
|
| 1653 | - /** |
|
| 1654 | - * This method simply returns the check-in status for this registration and the given datetime. |
|
| 1655 | - * If neither the datetime nor the checkin values are provided as arguments, |
|
| 1656 | - * then this will return the LATEST check-in status for the registration across all datetimes it belongs to. |
|
| 1657 | - * |
|
| 1658 | - * @param int $DTT_ID The ID of the datetime we're checking against |
|
| 1659 | - * (if empty we'll get the primary datetime for |
|
| 1660 | - * this registration (via event) and use it's ID); |
|
| 1661 | - * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id. |
|
| 1662 | - * |
|
| 1663 | - * @return int Integer representing Check-in status. |
|
| 1664 | - * @throws EE_Error |
|
| 1665 | - */ |
|
| 1666 | - public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null) |
|
| 1667 | - { |
|
| 1668 | - $checkin_query_params = array( |
|
| 1669 | - 'order_by' => array('CHK_timestamp' => 'DESC'), |
|
| 1670 | - ); |
|
| 1671 | - |
|
| 1672 | - if ($DTT_ID > 0) { |
|
| 1673 | - $checkin_query_params[0] = array('DTT_ID' => $DTT_ID); |
|
| 1674 | - } |
|
| 1675 | - |
|
| 1676 | - // get checkin object (if exists) |
|
| 1677 | - $checkin = $checkin instanceof EE_Checkin |
|
| 1678 | - ? $checkin |
|
| 1679 | - : $this->get_first_related('Checkin', $checkin_query_params); |
|
| 1680 | - if ($checkin instanceof EE_Checkin) { |
|
| 1681 | - if ($checkin->get('CHK_in')) { |
|
| 1682 | - return EE_Checkin::status_checked_in; // checked in |
|
| 1683 | - } |
|
| 1684 | - return EE_Checkin::status_checked_out; // had checked in but is now checked out. |
|
| 1685 | - } |
|
| 1686 | - return EE_Checkin::status_checked_never; // never been checked in |
|
| 1687 | - } |
|
| 1688 | - |
|
| 1689 | - |
|
| 1690 | - /** |
|
| 1691 | - * This method returns a localized message for the toggled Check-in message. |
|
| 1692 | - * |
|
| 1693 | - * @param int $DTT_ID include specific datetime to get the correct Check-in message. If not included or null, |
|
| 1694 | - * then it is assumed Check-in for primary datetime was toggled. |
|
| 1695 | - * @param bool $error This just flags that you want an error message returned. This is put in so that the error |
|
| 1696 | - * message can be customized with the attendee name. |
|
| 1697 | - * @return string internationalized message |
|
| 1698 | - * @throws EE_Error |
|
| 1699 | - */ |
|
| 1700 | - public function get_checkin_msg($DTT_ID, $error = false) |
|
| 1701 | - { |
|
| 1702 | - // let's get the attendee first so we can include the name of the attendee |
|
| 1703 | - $attendee = $this->get_first_related('Attendee'); |
|
| 1704 | - if ($attendee instanceof EE_Attendee) { |
|
| 1705 | - if ($error) { |
|
| 1706 | - return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name()); |
|
| 1707 | - } |
|
| 1708 | - $cur_status = $this->check_in_status_for_datetime($DTT_ID); |
|
| 1709 | - // what is the status message going to be? |
|
| 1710 | - switch ($cur_status) { |
|
| 1711 | - case EE_Checkin::status_checked_never: |
|
| 1712 | - return sprintf( |
|
| 1713 | - __("%s has been removed from Check-in records", "event_espresso"), |
|
| 1714 | - $attendee->full_name() |
|
| 1715 | - ); |
|
| 1716 | - break; |
|
| 1717 | - case EE_Checkin::status_checked_in: |
|
| 1718 | - return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name()); |
|
| 1719 | - break; |
|
| 1720 | - case EE_Checkin::status_checked_out: |
|
| 1721 | - return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name()); |
|
| 1722 | - break; |
|
| 1723 | - } |
|
| 1724 | - } |
|
| 1725 | - return esc_html__("The check-in status could not be determined.", "event_espresso"); |
|
| 1726 | - } |
|
| 1727 | - |
|
| 1728 | - |
|
| 1729 | - /** |
|
| 1730 | - * Returns the related EE_Transaction to this registration |
|
| 1731 | - * |
|
| 1732 | - * @return EE_Transaction |
|
| 1733 | - * @throws EE_Error |
|
| 1734 | - * @throws EntityNotFoundException |
|
| 1735 | - */ |
|
| 1736 | - public function transaction() |
|
| 1737 | - { |
|
| 1738 | - $transaction = $this->get_first_related('Transaction'); |
|
| 1739 | - if (! $transaction instanceof \EE_Transaction) { |
|
| 1740 | - throw new EntityNotFoundException('Transaction ID', $this->transaction_ID()); |
|
| 1741 | - } |
|
| 1742 | - return $transaction; |
|
| 1743 | - } |
|
| 1744 | - |
|
| 1745 | - |
|
| 1746 | - /** |
|
| 1747 | - * get Registration Code |
|
| 1748 | - */ |
|
| 1749 | - public function reg_code() |
|
| 1750 | - { |
|
| 1751 | - return $this->get('REG_code'); |
|
| 1752 | - } |
|
| 1753 | - |
|
| 1754 | - |
|
| 1755 | - /** |
|
| 1756 | - * get Transaction ID |
|
| 1757 | - */ |
|
| 1758 | - public function transaction_ID() |
|
| 1759 | - { |
|
| 1760 | - return $this->get('TXN_ID'); |
|
| 1761 | - } |
|
| 1762 | - |
|
| 1763 | - |
|
| 1764 | - /** |
|
| 1765 | - * @return int |
|
| 1766 | - * @throws EE_Error |
|
| 1767 | - */ |
|
| 1768 | - public function ticket_ID() |
|
| 1769 | - { |
|
| 1770 | - return $this->get('TKT_ID'); |
|
| 1771 | - } |
|
| 1772 | - |
|
| 1773 | - |
|
| 1774 | - /** |
|
| 1775 | - * Set Registration Code |
|
| 1776 | - * |
|
| 1777 | - * @access public |
|
| 1778 | - * @param string $REG_code Registration Code |
|
| 1779 | - * @param boolean $use_default |
|
| 1780 | - * @throws EE_Error |
|
| 1781 | - */ |
|
| 1782 | - public function set_reg_code($REG_code, $use_default = false) |
|
| 1783 | - { |
|
| 1784 | - if (empty($REG_code)) { |
|
| 1785 | - EE_Error::add_error( |
|
| 1786 | - esc_html__('REG_code can not be empty.', 'event_espresso'), |
|
| 1787 | - __FILE__, |
|
| 1788 | - __FUNCTION__, |
|
| 1789 | - __LINE__ |
|
| 1790 | - ); |
|
| 1791 | - return; |
|
| 1792 | - } |
|
| 1793 | - if (! $this->reg_code()) { |
|
| 1794 | - parent::set('REG_code', $REG_code, $use_default); |
|
| 1795 | - } else { |
|
| 1796 | - EE_Error::doing_it_wrong( |
|
| 1797 | - __CLASS__ . '::' . __FUNCTION__, |
|
| 1798 | - esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'), |
|
| 1799 | - '4.6.0' |
|
| 1800 | - ); |
|
| 1801 | - } |
|
| 1802 | - } |
|
| 1803 | - |
|
| 1804 | - |
|
| 1805 | - /** |
|
| 1806 | - * Returns all other registrations in the same group as this registrant who have the same ticket option. |
|
| 1807 | - * Note, if you want to just get all registrations in the same transaction (group), use: |
|
| 1808 | - * $registration->transaction()->registrations(); |
|
| 1809 | - * |
|
| 1810 | - * @since 4.5.0 |
|
| 1811 | - * @return EE_Registration[] or empty array if this isn't a group registration. |
|
| 1812 | - * @throws EE_Error |
|
| 1813 | - */ |
|
| 1814 | - public function get_all_other_registrations_in_group() |
|
| 1815 | - { |
|
| 1816 | - if ($this->group_size() < 2) { |
|
| 1817 | - return array(); |
|
| 1818 | - } |
|
| 1819 | - |
|
| 1820 | - $query[0] = array( |
|
| 1821 | - 'TXN_ID' => $this->transaction_ID(), |
|
| 1822 | - 'REG_ID' => array('!=', $this->ID()), |
|
| 1823 | - 'TKT_ID' => $this->ticket_ID(), |
|
| 1824 | - ); |
|
| 1825 | - /** @var EE_Registration[] $registrations */ |
|
| 1826 | - $registrations = $this->get_model()->get_all($query); |
|
| 1827 | - return $registrations; |
|
| 1828 | - } |
|
| 1829 | - |
|
| 1830 | - /** |
|
| 1831 | - * Return the link to the admin details for the object. |
|
| 1832 | - * |
|
| 1833 | - * @return string |
|
| 1834 | - * @throws EE_Error |
|
| 1835 | - */ |
|
| 1836 | - public function get_admin_details_link() |
|
| 1837 | - { |
|
| 1838 | - EE_Registry::instance()->load_helper('URL'); |
|
| 1839 | - return EEH_URL::add_query_args_and_nonce( |
|
| 1840 | - array( |
|
| 1841 | - 'page' => 'espresso_registrations', |
|
| 1842 | - 'action' => 'view_registration', |
|
| 1843 | - '_REG_ID' => $this->ID(), |
|
| 1844 | - ), |
|
| 1845 | - admin_url('admin.php') |
|
| 1846 | - ); |
|
| 1847 | - } |
|
| 1848 | - |
|
| 1849 | - /** |
|
| 1850 | - * Returns the link to the editor for the object. Sometimes this is the same as the details. |
|
| 1851 | - * |
|
| 1852 | - * @return string |
|
| 1853 | - * @throws EE_Error |
|
| 1854 | - */ |
|
| 1855 | - public function get_admin_edit_link() |
|
| 1856 | - { |
|
| 1857 | - return $this->get_admin_details_link(); |
|
| 1858 | - } |
|
| 1859 | - |
|
| 1860 | - /** |
|
| 1861 | - * Returns the link to a settings page for the object. |
|
| 1862 | - * |
|
| 1863 | - * @return string |
|
| 1864 | - * @throws EE_Error |
|
| 1865 | - */ |
|
| 1866 | - public function get_admin_settings_link() |
|
| 1867 | - { |
|
| 1868 | - return $this->get_admin_details_link(); |
|
| 1869 | - } |
|
| 1870 | - |
|
| 1871 | - /** |
|
| 1872 | - * Returns the link to the "overview" for the object (typically the "list table" view). |
|
| 1873 | - * |
|
| 1874 | - * @return string |
|
| 1875 | - */ |
|
| 1876 | - public function get_admin_overview_link() |
|
| 1877 | - { |
|
| 1878 | - EE_Registry::instance()->load_helper('URL'); |
|
| 1879 | - return EEH_URL::add_query_args_and_nonce( |
|
| 1880 | - array( |
|
| 1881 | - 'page' => 'espresso_registrations', |
|
| 1882 | - ), |
|
| 1883 | - admin_url('admin.php') |
|
| 1884 | - ); |
|
| 1885 | - } |
|
| 1886 | - |
|
| 1887 | - |
|
| 1888 | - /** |
|
| 1889 | - * @param array $query_params |
|
| 1890 | - * |
|
| 1891 | - * @return \EE_Registration[] |
|
| 1892 | - * @throws EE_Error |
|
| 1893 | - */ |
|
| 1894 | - public function payments($query_params = array()) |
|
| 1895 | - { |
|
| 1896 | - return $this->get_many_related('Payment', $query_params); |
|
| 1897 | - } |
|
| 1898 | - |
|
| 1899 | - |
|
| 1900 | - /** |
|
| 1901 | - * @param array $query_params |
|
| 1902 | - * |
|
| 1903 | - * @return \EE_Registration_Payment[] |
|
| 1904 | - * @throws EE_Error |
|
| 1905 | - */ |
|
| 1906 | - public function registration_payments($query_params = array()) |
|
| 1907 | - { |
|
| 1908 | - return $this->get_many_related('Registration_Payment', $query_params); |
|
| 1909 | - } |
|
| 1910 | - |
|
| 1911 | - |
|
| 1912 | - /** |
|
| 1913 | - * This grabs the payment method corresponding to the last payment made for the amount owing on the registration. |
|
| 1914 | - * Note: if there are no payments on the registration there will be no payment method returned. |
|
| 1915 | - * |
|
| 1916 | - * @return EE_Payment_Method|null |
|
| 1917 | - */ |
|
| 1918 | - public function payment_method() |
|
| 1919 | - { |
|
| 1920 | - return EEM_Payment_Method::instance()->get_last_used_for_registration($this); |
|
| 1921 | - } |
|
| 1922 | - |
|
| 1923 | - |
|
| 1924 | - /** |
|
| 1925 | - * @return \EE_Line_Item |
|
| 1926 | - * @throws EntityNotFoundException |
|
| 1927 | - * @throws EE_Error |
|
| 1928 | - */ |
|
| 1929 | - public function ticket_line_item() |
|
| 1930 | - { |
|
| 1931 | - $ticket = $this->ticket(); |
|
| 1932 | - $transaction = $this->transaction(); |
|
| 1933 | - $line_item = null; |
|
| 1934 | - $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs( |
|
| 1935 | - $transaction->total_line_item(), |
|
| 1936 | - 'Ticket', |
|
| 1937 | - array($ticket->ID()) |
|
| 1938 | - ); |
|
| 1939 | - foreach ($ticket_line_items as $ticket_line_item) { |
|
| 1940 | - if ( |
|
| 1941 | - $ticket_line_item instanceof \EE_Line_Item |
|
| 1942 | - && $ticket_line_item->OBJ_type() === 'Ticket' |
|
| 1943 | - && $ticket_line_item->OBJ_ID() === $ticket->ID() |
|
| 1944 | - ) { |
|
| 1945 | - $line_item = $ticket_line_item; |
|
| 1946 | - break; |
|
| 1947 | - } |
|
| 1948 | - } |
|
| 1949 | - if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) { |
|
| 1950 | - throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID()); |
|
| 1951 | - } |
|
| 1952 | - return $line_item; |
|
| 1953 | - } |
|
| 1954 | - |
|
| 1955 | - |
|
| 1956 | - /** |
|
| 1957 | - * Soft Deletes this model object. |
|
| 1958 | - * |
|
| 1959 | - * @return boolean | int |
|
| 1960 | - * @throws RuntimeException |
|
| 1961 | - * @throws EE_Error |
|
| 1962 | - */ |
|
| 1963 | - public function delete() |
|
| 1964 | - { |
|
| 1965 | - if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) { |
|
| 1966 | - $this->set_status(EEM_Registration::status_id_cancelled); |
|
| 1967 | - } |
|
| 1968 | - return parent::delete(); |
|
| 1969 | - } |
|
| 1970 | - |
|
| 1971 | - |
|
| 1972 | - /** |
|
| 1973 | - * Restores whatever the previous status was on a registration before it was trashed (if possible) |
|
| 1974 | - * |
|
| 1975 | - * @throws EE_Error |
|
| 1976 | - * @throws RuntimeException |
|
| 1977 | - */ |
|
| 1978 | - public function restore() |
|
| 1979 | - { |
|
| 1980 | - $previous_status = $this->get_extra_meta( |
|
| 1981 | - EE_Registration::PRE_TRASH_REG_STATUS_KEY, |
|
| 1982 | - true, |
|
| 1983 | - EEM_Registration::status_id_cancelled |
|
| 1984 | - ); |
|
| 1985 | - if ($previous_status) { |
|
| 1986 | - $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY); |
|
| 1987 | - $this->set_status($previous_status); |
|
| 1988 | - } |
|
| 1989 | - return parent::restore(); |
|
| 1990 | - } |
|
| 1991 | - |
|
| 1992 | - |
|
| 1993 | - /** |
|
| 1994 | - * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price |
|
| 1995 | - * |
|
| 1996 | - * @param boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic |
|
| 1997 | - * depending on whether the reg status changes to or from "Approved" |
|
| 1998 | - * @return boolean whether the Registration status was updated |
|
| 1999 | - * @throws EE_Error |
|
| 2000 | - * @throws RuntimeException |
|
| 2001 | - */ |
|
| 2002 | - public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true) |
|
| 2003 | - { |
|
| 2004 | - $paid = $this->paid(); |
|
| 2005 | - $price = $this->final_price(); |
|
| 2006 | - switch (true) { |
|
| 2007 | - // overpaid or paid |
|
| 2008 | - case EEH_Money::compare_floats($paid, $price, '>'): |
|
| 2009 | - case EEH_Money::compare_floats($paid, $price): |
|
| 2010 | - $new_status = EEM_Registration::status_id_approved; |
|
| 2011 | - break; |
|
| 2012 | - // underpaid |
|
| 2013 | - case EEH_Money::compare_floats($paid, $price, '<'): |
|
| 2014 | - $new_status = EEM_Registration::status_id_pending_payment; |
|
| 2015 | - break; |
|
| 2016 | - // uhhh Houston... |
|
| 2017 | - default: |
|
| 2018 | - throw new RuntimeException( |
|
| 2019 | - esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso') |
|
| 2020 | - ); |
|
| 2021 | - } |
|
| 2022 | - if ($new_status !== $this->status_ID()) { |
|
| 2023 | - if ($trigger_set_status_logic) { |
|
| 2024 | - return $this->set_status($new_status); |
|
| 2025 | - } |
|
| 2026 | - parent::set('STS_ID', $new_status); |
|
| 2027 | - return true; |
|
| 2028 | - } |
|
| 2029 | - return false; |
|
| 2030 | - } |
|
| 2031 | - |
|
| 2032 | - |
|
| 2033 | - /*************************** DEPRECATED ***************************/ |
|
| 2034 | - |
|
| 2035 | - |
|
| 2036 | - /** |
|
| 2037 | - * @deprecated |
|
| 2038 | - * @since 4.7.0 |
|
| 2039 | - * @access public |
|
| 2040 | - */ |
|
| 2041 | - public function price_paid() |
|
| 2042 | - { |
|
| 2043 | - EE_Error::doing_it_wrong( |
|
| 2044 | - 'EE_Registration::price_paid()', |
|
| 2045 | - esc_html__( |
|
| 2046 | - 'This method is deprecated, please use EE_Registration::final_price() instead.', |
|
| 2047 | - 'event_espresso' |
|
| 2048 | - ), |
|
| 2049 | - '4.7.0' |
|
| 2050 | - ); |
|
| 2051 | - return $this->final_price(); |
|
| 2052 | - } |
|
| 2053 | - |
|
| 2054 | - |
|
| 2055 | - /** |
|
| 2056 | - * @deprecated |
|
| 2057 | - * @since 4.7.0 |
|
| 2058 | - * @access public |
|
| 2059 | - * @param float $REG_final_price |
|
| 2060 | - * @throws EE_Error |
|
| 2061 | - * @throws RuntimeException |
|
| 2062 | - */ |
|
| 2063 | - public function set_price_paid($REG_final_price = 0.00) |
|
| 2064 | - { |
|
| 2065 | - EE_Error::doing_it_wrong( |
|
| 2066 | - 'EE_Registration::set_price_paid()', |
|
| 2067 | - esc_html__( |
|
| 2068 | - 'This method is deprecated, please use EE_Registration::set_final_price() instead.', |
|
| 2069 | - 'event_espresso' |
|
| 2070 | - ), |
|
| 2071 | - '4.7.0' |
|
| 2072 | - ); |
|
| 2073 | - $this->set_final_price($REG_final_price); |
|
| 2074 | - } |
|
| 2075 | - |
|
| 2076 | - |
|
| 2077 | - /** |
|
| 2078 | - * @deprecated |
|
| 2079 | - * @since 4.7.0 |
|
| 2080 | - * @return string |
|
| 2081 | - * @throws EE_Error |
|
| 2082 | - */ |
|
| 2083 | - public function pretty_price_paid() |
|
| 2084 | - { |
|
| 2085 | - EE_Error::doing_it_wrong( |
|
| 2086 | - 'EE_Registration::pretty_price_paid()', |
|
| 2087 | - esc_html__( |
|
| 2088 | - 'This method is deprecated, please use EE_Registration::pretty_final_price() instead.', |
|
| 2089 | - 'event_espresso' |
|
| 2090 | - ), |
|
| 2091 | - '4.7.0' |
|
| 2092 | - ); |
|
| 2093 | - return $this->pretty_final_price(); |
|
| 2094 | - } |
|
| 2095 | - |
|
| 2096 | - |
|
| 2097 | - /** |
|
| 2098 | - * Gets the primary datetime related to this registration via the related Event to this registration |
|
| 2099 | - * |
|
| 2100 | - * @deprecated 4.9.17 |
|
| 2101 | - * @return EE_Datetime |
|
| 2102 | - * @throws EE_Error |
|
| 2103 | - * @throws EntityNotFoundException |
|
| 2104 | - */ |
|
| 2105 | - public function get_related_primary_datetime() |
|
| 2106 | - { |
|
| 2107 | - EE_Error::doing_it_wrong( |
|
| 2108 | - __METHOD__, |
|
| 2109 | - esc_html__( |
|
| 2110 | - 'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()', |
|
| 2111 | - 'event_espresso' |
|
| 2112 | - ), |
|
| 2113 | - '4.9.17', |
|
| 2114 | - '5.0.0' |
|
| 2115 | - ); |
|
| 2116 | - return $this->event()->primary_datetime(); |
|
| 2117 | - } |
|
| 2118 | - |
|
| 2119 | - /** |
|
| 2120 | - * Returns the contact's name (or "Unknown" if there is no contact.) |
|
| 2121 | - * @since $VID:$ |
|
| 2122 | - * @return string |
|
| 2123 | - * @throws EE_Error |
|
| 2124 | - * @throws InvalidArgumentException |
|
| 2125 | - * @throws InvalidDataTypeException |
|
| 2126 | - * @throws InvalidInterfaceException |
|
| 2127 | - * @throws ReflectionException |
|
| 2128 | - */ |
|
| 2129 | - public function name() |
|
| 2130 | - { |
|
| 2131 | - return $this->attendeeName(); |
|
| 2132 | - } |
|
| 20 | + /** |
|
| 21 | + * Used to reference when a registration has never been checked in. |
|
| 22 | + * |
|
| 23 | + * @deprecated use \EE_Checkin::status_checked_never instead |
|
| 24 | + * @type int |
|
| 25 | + */ |
|
| 26 | + const checkin_status_never = 2; |
|
| 27 | + |
|
| 28 | + /** |
|
| 29 | + * Used to reference when a registration has been checked in. |
|
| 30 | + * |
|
| 31 | + * @deprecated use \EE_Checkin::status_checked_in instead |
|
| 32 | + * @type int |
|
| 33 | + */ |
|
| 34 | + const checkin_status_in = 1; |
|
| 35 | + |
|
| 36 | + |
|
| 37 | + /** |
|
| 38 | + * Used to reference when a registration has been checked out. |
|
| 39 | + * |
|
| 40 | + * @deprecated use \EE_Checkin::status_checked_out instead |
|
| 41 | + * @type int |
|
| 42 | + */ |
|
| 43 | + const checkin_status_out = 0; |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + /** |
|
| 47 | + * extra meta key for tracking reg status os trashed registrations |
|
| 48 | + * |
|
| 49 | + * @type string |
|
| 50 | + */ |
|
| 51 | + const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status'; |
|
| 52 | + |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * extra meta key for tracking if registration has reserved ticket |
|
| 56 | + * |
|
| 57 | + * @type string |
|
| 58 | + */ |
|
| 59 | + const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket'; |
|
| 60 | + |
|
| 61 | + |
|
| 62 | + /** |
|
| 63 | + * @param array $props_n_values incoming values |
|
| 64 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 65 | + * used.) |
|
| 66 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 67 | + * date_format and the second value is the time format |
|
| 68 | + * @return EE_Registration |
|
| 69 | + * @throws EE_Error |
|
| 70 | + */ |
|
| 71 | + public static function new_instance($props_n_values = array(), $timezone = '', $date_formats = array()) |
|
| 72 | + { |
|
| 73 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 74 | + return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
| 75 | + } |
|
| 76 | + |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * @param array $props_n_values incoming values from the database |
|
| 80 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 81 | + * the website will be used. |
|
| 82 | + * @return EE_Registration |
|
| 83 | + */ |
|
| 84 | + public static function new_instance_from_db($props_n_values = array(), $timezone = '') |
|
| 85 | + { |
|
| 86 | + return new self($props_n_values, true, $timezone); |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + |
|
| 90 | + /** |
|
| 91 | + * Set Event ID |
|
| 92 | + * |
|
| 93 | + * @param int $EVT_ID Event ID |
|
| 94 | + * @throws EE_Error |
|
| 95 | + * @throws RuntimeException |
|
| 96 | + */ |
|
| 97 | + public function set_event($EVT_ID = 0) |
|
| 98 | + { |
|
| 99 | + $this->set('EVT_ID', $EVT_ID); |
|
| 100 | + } |
|
| 101 | + |
|
| 102 | + |
|
| 103 | + /** |
|
| 104 | + * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can |
|
| 105 | + * be routed to internal methods |
|
| 106 | + * |
|
| 107 | + * @param string $field_name |
|
| 108 | + * @param mixed $field_value |
|
| 109 | + * @param bool $use_default |
|
| 110 | + * @throws EE_Error |
|
| 111 | + * @throws EntityNotFoundException |
|
| 112 | + * @throws InvalidArgumentException |
|
| 113 | + * @throws InvalidDataTypeException |
|
| 114 | + * @throws InvalidInterfaceException |
|
| 115 | + * @throws ReflectionException |
|
| 116 | + * @throws RuntimeException |
|
| 117 | + */ |
|
| 118 | + public function set($field_name, $field_value, bool $use_default = false) |
|
| 119 | + { |
|
| 120 | + switch ($field_name) { |
|
| 121 | + case 'REG_code': |
|
| 122 | + if (! empty($field_value) && $this->reg_code() === null) { |
|
| 123 | + $this->set_reg_code($field_value, $use_default); |
|
| 124 | + } |
|
| 125 | + break; |
|
| 126 | + case 'STS_ID': |
|
| 127 | + $this->set_status($field_value, $use_default); |
|
| 128 | + break; |
|
| 129 | + default: |
|
| 130 | + parent::set($field_name, $field_value, $use_default); |
|
| 131 | + } |
|
| 132 | + } |
|
| 133 | + |
|
| 134 | + |
|
| 135 | + /** |
|
| 136 | + * Set Status ID |
|
| 137 | + * updates the registration status and ALSO... |
|
| 138 | + * calls reserve_registration_space() if the reg status changes TO approved from any other reg status |
|
| 139 | + * calls release_registration_space() if the reg status changes FROM approved to any other reg status |
|
| 140 | + * |
|
| 141 | + * @param string $new_STS_ID |
|
| 142 | + * @param boolean $use_default |
|
| 143 | + * @param ContextInterface|null $context |
|
| 144 | + * @return bool |
|
| 145 | + * @throws DomainException |
|
| 146 | + * @throws EE_Error |
|
| 147 | + * @throws EntityNotFoundException |
|
| 148 | + * @throws InvalidArgumentException |
|
| 149 | + * @throws InvalidDataTypeException |
|
| 150 | + * @throws InvalidInterfaceException |
|
| 151 | + * @throws ReflectionException |
|
| 152 | + * @throws RuntimeException |
|
| 153 | + * @throws UnexpectedEntityException |
|
| 154 | + */ |
|
| 155 | + public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null) |
|
| 156 | + { |
|
| 157 | + // get current REG_Status |
|
| 158 | + $old_STS_ID = $this->status_ID(); |
|
| 159 | + // if status has changed |
|
| 160 | + if ( |
|
| 161 | + $old_STS_ID !== $new_STS_ID // and that status has actually changed |
|
| 162 | + && ! empty($old_STS_ID) // and that old status is actually set |
|
| 163 | + && ! empty($new_STS_ID) // as well as the new status |
|
| 164 | + && $this->ID() // ensure registration is in the db |
|
| 165 | + ) { |
|
| 166 | + // update internal status first |
|
| 167 | + parent::set('STS_ID', $new_STS_ID, $use_default); |
|
| 168 | + // THEN handle other changes that occur when reg status changes |
|
| 169 | + // TO approved |
|
| 170 | + if ($new_STS_ID === EEM_Registration::status_id_approved) { |
|
| 171 | + // reserve a space by incrementing ticket and datetime sold values |
|
| 172 | + $this->reserveRegistrationSpace(); |
|
| 173 | + do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context); |
|
| 174 | + // OR FROM approved |
|
| 175 | + } elseif ($old_STS_ID === EEM_Registration::status_id_approved) { |
|
| 176 | + // release a space by decrementing ticket and datetime sold values |
|
| 177 | + $this->releaseRegistrationSpace(); |
|
| 178 | + do_action( |
|
| 179 | + 'AHEE__EE_Registration__set_status__from_approved', |
|
| 180 | + $this, |
|
| 181 | + $old_STS_ID, |
|
| 182 | + $new_STS_ID, |
|
| 183 | + $context |
|
| 184 | + ); |
|
| 185 | + } |
|
| 186 | + // update status |
|
| 187 | + parent::set('STS_ID', $new_STS_ID, $use_default); |
|
| 188 | + $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context); |
|
| 189 | + if ($this->statusChangeUpdatesTransaction($context)) { |
|
| 190 | + $this->updateTransactionAfterStatusChange(); |
|
| 191 | + } |
|
| 192 | + do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context); |
|
| 193 | + return true; |
|
| 194 | + } |
|
| 195 | + // even though the old value matches the new value, it's still good to |
|
| 196 | + // allow the parent set method to have a say |
|
| 197 | + parent::set('STS_ID', $new_STS_ID, $use_default); |
|
| 198 | + return true; |
|
| 199 | + } |
|
| 200 | + |
|
| 201 | + |
|
| 202 | + /** |
|
| 203 | + * update REGs and TXN when cancelled or declined registrations involved |
|
| 204 | + * |
|
| 205 | + * @param string $new_STS_ID |
|
| 206 | + * @param string $old_STS_ID |
|
| 207 | + * @param ContextInterface|null $context |
|
| 208 | + * @throws EE_Error |
|
| 209 | + * @throws InvalidArgumentException |
|
| 210 | + * @throws InvalidDataTypeException |
|
| 211 | + * @throws InvalidInterfaceException |
|
| 212 | + * @throws ReflectionException |
|
| 213 | + * @throws RuntimeException |
|
| 214 | + */ |
|
| 215 | + private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null) |
|
| 216 | + { |
|
| 217 | + // these reg statuses should not be considered in any calculations involving monies owing |
|
| 218 | + $closed_reg_statuses = EEM_Registration::closed_reg_statuses(); |
|
| 219 | + // true if registration has been cancelled or declined |
|
| 220 | + $this->updateIfCanceled( |
|
| 221 | + $closed_reg_statuses, |
|
| 222 | + $new_STS_ID, |
|
| 223 | + $old_STS_ID, |
|
| 224 | + $context |
|
| 225 | + ); |
|
| 226 | + $this->updateIfReinstated( |
|
| 227 | + $closed_reg_statuses, |
|
| 228 | + $new_STS_ID, |
|
| 229 | + $old_STS_ID, |
|
| 230 | + $context |
|
| 231 | + ); |
|
| 232 | + } |
|
| 233 | + |
|
| 234 | + |
|
| 235 | + /** |
|
| 236 | + * update REGs and TXN when cancelled or declined registrations involved |
|
| 237 | + * |
|
| 238 | + * @param array $closed_reg_statuses |
|
| 239 | + * @param string $new_STS_ID |
|
| 240 | + * @param string $old_STS_ID |
|
| 241 | + * @param ContextInterface|null $context |
|
| 242 | + * @throws EE_Error |
|
| 243 | + * @throws InvalidArgumentException |
|
| 244 | + * @throws InvalidDataTypeException |
|
| 245 | + * @throws InvalidInterfaceException |
|
| 246 | + * @throws ReflectionException |
|
| 247 | + * @throws RuntimeException |
|
| 248 | + */ |
|
| 249 | + private function updateIfCanceled( |
|
| 250 | + array $closed_reg_statuses, |
|
| 251 | + $new_STS_ID, |
|
| 252 | + $old_STS_ID, |
|
| 253 | + ContextInterface $context = null |
|
| 254 | + ) { |
|
| 255 | + // true if registration has been cancelled or declined |
|
| 256 | + if ( |
|
| 257 | + in_array($new_STS_ID, $closed_reg_statuses, true) |
|
| 258 | + && ! in_array($old_STS_ID, $closed_reg_statuses, true) |
|
| 259 | + ) { |
|
| 260 | + /** @type EE_Registration_Processor $registration_processor */ |
|
| 261 | + $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
| 262 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 263 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 264 | + // cancelled or declined registration |
|
| 265 | + $registration_processor->update_registration_after_being_canceled_or_declined( |
|
| 266 | + $this, |
|
| 267 | + $closed_reg_statuses |
|
| 268 | + ); |
|
| 269 | + $transaction_processor->update_transaction_after_canceled_or_declined_registration( |
|
| 270 | + $this, |
|
| 271 | + $closed_reg_statuses, |
|
| 272 | + false |
|
| 273 | + ); |
|
| 274 | + do_action( |
|
| 275 | + 'AHEE__EE_Registration__set_status__canceled_or_declined', |
|
| 276 | + $this, |
|
| 277 | + $old_STS_ID, |
|
| 278 | + $new_STS_ID, |
|
| 279 | + $context |
|
| 280 | + ); |
|
| 281 | + return; |
|
| 282 | + } |
|
| 283 | + } |
|
| 284 | + |
|
| 285 | + |
|
| 286 | + /** |
|
| 287 | + * update REGs and TXN when cancelled or declined registrations involved |
|
| 288 | + * |
|
| 289 | + * @param array $closed_reg_statuses |
|
| 290 | + * @param string $new_STS_ID |
|
| 291 | + * @param string $old_STS_ID |
|
| 292 | + * @param ContextInterface|null $context |
|
| 293 | + * @throws EE_Error |
|
| 294 | + * @throws InvalidArgumentException |
|
| 295 | + * @throws InvalidDataTypeException |
|
| 296 | + * @throws InvalidInterfaceException |
|
| 297 | + * @throws ReflectionException |
|
| 298 | + */ |
|
| 299 | + private function updateIfReinstated( |
|
| 300 | + array $closed_reg_statuses, |
|
| 301 | + $new_STS_ID, |
|
| 302 | + $old_STS_ID, |
|
| 303 | + ContextInterface $context = null |
|
| 304 | + ) { |
|
| 305 | + // true if reinstating cancelled or declined registration |
|
| 306 | + if ( |
|
| 307 | + in_array($old_STS_ID, $closed_reg_statuses, true) |
|
| 308 | + && ! in_array($new_STS_ID, $closed_reg_statuses, true) |
|
| 309 | + ) { |
|
| 310 | + /** @type EE_Registration_Processor $registration_processor */ |
|
| 311 | + $registration_processor = EE_Registry::instance()->load_class('Registration_Processor'); |
|
| 312 | + /** @type EE_Transaction_Processor $transaction_processor */ |
|
| 313 | + $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor'); |
|
| 314 | + // reinstating cancelled or declined registration |
|
| 315 | + $registration_processor->update_canceled_or_declined_registration_after_being_reinstated( |
|
| 316 | + $this, |
|
| 317 | + $closed_reg_statuses |
|
| 318 | + ); |
|
| 319 | + $transaction_processor->update_transaction_after_reinstating_canceled_registration( |
|
| 320 | + $this, |
|
| 321 | + $closed_reg_statuses, |
|
| 322 | + false |
|
| 323 | + ); |
|
| 324 | + do_action( |
|
| 325 | + 'AHEE__EE_Registration__set_status__after_reinstated', |
|
| 326 | + $this, |
|
| 327 | + $old_STS_ID, |
|
| 328 | + $new_STS_ID, |
|
| 329 | + $context |
|
| 330 | + ); |
|
| 331 | + } |
|
| 332 | + } |
|
| 333 | + |
|
| 334 | + |
|
| 335 | + /** |
|
| 336 | + * @param ContextInterface|null $context |
|
| 337 | + * @return bool |
|
| 338 | + */ |
|
| 339 | + private function statusChangeUpdatesTransaction(ContextInterface $context = null) |
|
| 340 | + { |
|
| 341 | + $contexts_that_do_not_update_transaction = (array) apply_filters( |
|
| 342 | + 'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction', |
|
| 343 | + array('spco_reg_step_attendee_information_process_registrations'), |
|
| 344 | + $context, |
|
| 345 | + $this |
|
| 346 | + ); |
|
| 347 | + return ! ( |
|
| 348 | + $context instanceof ContextInterface |
|
| 349 | + && in_array($context->slug(), $contexts_that_do_not_update_transaction, true) |
|
| 350 | + ); |
|
| 351 | + } |
|
| 352 | + |
|
| 353 | + |
|
| 354 | + /** |
|
| 355 | + * @throws EE_Error |
|
| 356 | + * @throws EntityNotFoundException |
|
| 357 | + * @throws InvalidArgumentException |
|
| 358 | + * @throws InvalidDataTypeException |
|
| 359 | + * @throws InvalidInterfaceException |
|
| 360 | + * @throws ReflectionException |
|
| 361 | + * @throws RuntimeException |
|
| 362 | + */ |
|
| 363 | + private function updateTransactionAfterStatusChange() |
|
| 364 | + { |
|
| 365 | + /** @type EE_Transaction_Payments $transaction_payments */ |
|
| 366 | + $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments'); |
|
| 367 | + $transaction_payments->recalculate_transaction_total($this->transaction(), false); |
|
| 368 | + $this->transaction()->update_status_based_on_total_paid(true); |
|
| 369 | + } |
|
| 370 | + |
|
| 371 | + |
|
| 372 | + /** |
|
| 373 | + * get Status ID |
|
| 374 | + */ |
|
| 375 | + public function status_ID() |
|
| 376 | + { |
|
| 377 | + return $this->get('STS_ID'); |
|
| 378 | + } |
|
| 379 | + |
|
| 380 | + |
|
| 381 | + /** |
|
| 382 | + * Gets the ticket this registration is for |
|
| 383 | + * |
|
| 384 | + * @param boolean $include_archived whether to include archived tickets or not. |
|
| 385 | + * |
|
| 386 | + * @return EE_Ticket|EE_Base_Class |
|
| 387 | + * @throws EE_Error |
|
| 388 | + */ |
|
| 389 | + public function ticket($include_archived = true) |
|
| 390 | + { |
|
| 391 | + $query_params = array(); |
|
| 392 | + if ($include_archived) { |
|
| 393 | + $query_params['default_where_conditions'] = 'none'; |
|
| 394 | + } |
|
| 395 | + return $this->get_first_related('Ticket', $query_params); |
|
| 396 | + } |
|
| 397 | + |
|
| 398 | + |
|
| 399 | + /** |
|
| 400 | + * Gets the event this registration is for |
|
| 401 | + * |
|
| 402 | + * @return EE_Event |
|
| 403 | + * @throws EE_Error |
|
| 404 | + * @throws EntityNotFoundException |
|
| 405 | + */ |
|
| 406 | + public function event() |
|
| 407 | + { |
|
| 408 | + $event = $this->get_first_related('Event'); |
|
| 409 | + if (! $event instanceof \EE_Event) { |
|
| 410 | + throw new EntityNotFoundException('Event ID', $this->event_ID()); |
|
| 411 | + } |
|
| 412 | + return $event; |
|
| 413 | + } |
|
| 414 | + |
|
| 415 | + |
|
| 416 | + /** |
|
| 417 | + * Gets the "author" of the registration. Note that for the purposes of registrations, the author will correspond |
|
| 418 | + * with the author of the event this registration is for. |
|
| 419 | + * |
|
| 420 | + * @since 4.5.0 |
|
| 421 | + * @return int |
|
| 422 | + * @throws EE_Error |
|
| 423 | + * @throws EntityNotFoundException |
|
| 424 | + */ |
|
| 425 | + public function wp_user() |
|
| 426 | + { |
|
| 427 | + $event = $this->event(); |
|
| 428 | + if ($event instanceof EE_Event) { |
|
| 429 | + return $event->wp_user(); |
|
| 430 | + } |
|
| 431 | + return 0; |
|
| 432 | + } |
|
| 433 | + |
|
| 434 | + |
|
| 435 | + /** |
|
| 436 | + * increments this registration's related ticket sold and corresponding datetime sold values |
|
| 437 | + * |
|
| 438 | + * @return void |
|
| 439 | + * @throws DomainException |
|
| 440 | + * @throws EE_Error |
|
| 441 | + * @throws EntityNotFoundException |
|
| 442 | + * @throws InvalidArgumentException |
|
| 443 | + * @throws InvalidDataTypeException |
|
| 444 | + * @throws InvalidInterfaceException |
|
| 445 | + * @throws ReflectionException |
|
| 446 | + * @throws UnexpectedEntityException |
|
| 447 | + */ |
|
| 448 | + private function reserveRegistrationSpace() |
|
| 449 | + { |
|
| 450 | + // reserved ticket and datetime counts will be decremented as sold counts are incremented |
|
| 451 | + // so stop tracking that this reg has a ticket reserved |
|
| 452 | + $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')'); |
|
| 453 | + $ticket = $this->ticket(); |
|
| 454 | + $ticket->increaseSold(); |
|
| 455 | + // possibly set event status to sold out |
|
| 456 | + $this->event()->perform_sold_out_status_check(); |
|
| 457 | + } |
|
| 458 | + |
|
| 459 | + |
|
| 460 | + /** |
|
| 461 | + * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values |
|
| 462 | + * |
|
| 463 | + * @return void |
|
| 464 | + * @throws DomainException |
|
| 465 | + * @throws EE_Error |
|
| 466 | + * @throws EntityNotFoundException |
|
| 467 | + * @throws InvalidArgumentException |
|
| 468 | + * @throws InvalidDataTypeException |
|
| 469 | + * @throws InvalidInterfaceException |
|
| 470 | + * @throws ReflectionException |
|
| 471 | + * @throws UnexpectedEntityException |
|
| 472 | + */ |
|
| 473 | + private function releaseRegistrationSpace() |
|
| 474 | + { |
|
| 475 | + $ticket = $this->ticket(); |
|
| 476 | + $ticket->decreaseSold(); |
|
| 477 | + // possibly change event status from sold out back to previous status |
|
| 478 | + $this->event()->perform_sold_out_status_check(); |
|
| 479 | + } |
|
| 480 | + |
|
| 481 | + |
|
| 482 | + /** |
|
| 483 | + * tracks this registration's ticket reservation in extra meta |
|
| 484 | + * and can increment related ticket reserved and corresponding datetime reserved values |
|
| 485 | + * |
|
| 486 | + * @param bool $update_ticket if true, will increment ticket and datetime reserved count |
|
| 487 | + * @return void |
|
| 488 | + * @throws EE_Error |
|
| 489 | + * @throws InvalidArgumentException |
|
| 490 | + * @throws InvalidDataTypeException |
|
| 491 | + * @throws InvalidInterfaceException |
|
| 492 | + * @throws ReflectionException |
|
| 493 | + */ |
|
| 494 | + public function reserve_ticket($update_ticket = false, $source = 'unknown') |
|
| 495 | + { |
|
| 496 | + // only reserve ticket if space is not currently reserved |
|
| 497 | + if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) { |
|
| 498 | + $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}"); |
|
| 499 | + // IMPORTANT !!! |
|
| 500 | + // although checking $update_ticket first would be more efficient, |
|
| 501 | + // we NEED to ALWAYS call update_extra_meta(), which is why that is done first |
|
| 502 | + if ( |
|
| 503 | + $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) |
|
| 504 | + && $update_ticket |
|
| 505 | + ) { |
|
| 506 | + $ticket = $this->ticket(); |
|
| 507 | + $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')'); |
|
| 508 | + $ticket->save(); |
|
| 509 | + } |
|
| 510 | + } |
|
| 511 | + } |
|
| 512 | + |
|
| 513 | + |
|
| 514 | + /** |
|
| 515 | + * stops tracking this registration's ticket reservation in extra meta |
|
| 516 | + * decrements (subtracts) related ticket reserved and corresponding datetime reserved values |
|
| 517 | + * |
|
| 518 | + * @param bool $update_ticket if true, will decrement ticket and datetime reserved count |
|
| 519 | + * @return void |
|
| 520 | + * @throws EE_Error |
|
| 521 | + * @throws InvalidArgumentException |
|
| 522 | + * @throws InvalidDataTypeException |
|
| 523 | + * @throws InvalidInterfaceException |
|
| 524 | + * @throws ReflectionException |
|
| 525 | + */ |
|
| 526 | + public function release_reserved_ticket($update_ticket = false, $source = 'unknown') |
|
| 527 | + { |
|
| 528 | + // only release ticket if space is currently reserved |
|
| 529 | + if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) { |
|
| 530 | + $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}"); |
|
| 531 | + // IMPORTANT !!! |
|
| 532 | + // although checking $update_ticket first would be more efficient, |
|
| 533 | + // we NEED to ALWAYS call update_extra_meta(), which is why that is done first |
|
| 534 | + if ( |
|
| 535 | + $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false) |
|
| 536 | + && $update_ticket |
|
| 537 | + ) { |
|
| 538 | + $ticket = $this->ticket(); |
|
| 539 | + $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')'); |
|
| 540 | + } |
|
| 541 | + } |
|
| 542 | + } |
|
| 543 | + |
|
| 544 | + |
|
| 545 | + /** |
|
| 546 | + * Set Attendee ID |
|
| 547 | + * |
|
| 548 | + * @param int $ATT_ID Attendee ID |
|
| 549 | + * @throws EE_Error |
|
| 550 | + * @throws RuntimeException |
|
| 551 | + */ |
|
| 552 | + public function set_attendee_id($ATT_ID = 0) |
|
| 553 | + { |
|
| 554 | + $this->set('ATT_ID', $ATT_ID); |
|
| 555 | + } |
|
| 556 | + |
|
| 557 | + |
|
| 558 | + /** |
|
| 559 | + * Set Transaction ID |
|
| 560 | + * |
|
| 561 | + * @param int $TXN_ID Transaction ID |
|
| 562 | + * @throws EE_Error |
|
| 563 | + * @throws RuntimeException |
|
| 564 | + */ |
|
| 565 | + public function set_transaction_id($TXN_ID = 0) |
|
| 566 | + { |
|
| 567 | + $this->set('TXN_ID', $TXN_ID); |
|
| 568 | + } |
|
| 569 | + |
|
| 570 | + |
|
| 571 | + /** |
|
| 572 | + * Set Session |
|
| 573 | + * |
|
| 574 | + * @param string $REG_session PHP Session ID |
|
| 575 | + * @throws EE_Error |
|
| 576 | + * @throws RuntimeException |
|
| 577 | + */ |
|
| 578 | + public function set_session($REG_session = '') |
|
| 579 | + { |
|
| 580 | + $this->set('REG_session', $REG_session); |
|
| 581 | + } |
|
| 582 | + |
|
| 583 | + |
|
| 584 | + /** |
|
| 585 | + * Set Registration URL Link |
|
| 586 | + * |
|
| 587 | + * @param string $REG_url_link Registration URL Link |
|
| 588 | + * @throws EE_Error |
|
| 589 | + * @throws RuntimeException |
|
| 590 | + */ |
|
| 591 | + public function set_reg_url_link($REG_url_link = '') |
|
| 592 | + { |
|
| 593 | + $this->set('REG_url_link', $REG_url_link); |
|
| 594 | + } |
|
| 595 | + |
|
| 596 | + |
|
| 597 | + /** |
|
| 598 | + * Set Attendee Counter |
|
| 599 | + * |
|
| 600 | + * @param int $REG_count Primary Attendee |
|
| 601 | + * @throws EE_Error |
|
| 602 | + * @throws RuntimeException |
|
| 603 | + */ |
|
| 604 | + public function set_count($REG_count = 1) |
|
| 605 | + { |
|
| 606 | + $this->set('REG_count', $REG_count); |
|
| 607 | + } |
|
| 608 | + |
|
| 609 | + |
|
| 610 | + /** |
|
| 611 | + * Set Group Size |
|
| 612 | + * |
|
| 613 | + * @param boolean $REG_group_size Group Registration |
|
| 614 | + * @throws EE_Error |
|
| 615 | + * @throws RuntimeException |
|
| 616 | + */ |
|
| 617 | + public function set_group_size($REG_group_size = false) |
|
| 618 | + { |
|
| 619 | + $this->set('REG_group_size', $REG_group_size); |
|
| 620 | + } |
|
| 621 | + |
|
| 622 | + |
|
| 623 | + /** |
|
| 624 | + * is_not_approved - convenience method that returns TRUE if REG status ID == |
|
| 625 | + * EEM_Registration::status_id_not_approved |
|
| 626 | + * |
|
| 627 | + * @return boolean |
|
| 628 | + */ |
|
| 629 | + public function is_not_approved() |
|
| 630 | + { |
|
| 631 | + return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false; |
|
| 632 | + } |
|
| 633 | + |
|
| 634 | + |
|
| 635 | + /** |
|
| 636 | + * is_pending_payment - convenience method that returns TRUE if REG status ID == |
|
| 637 | + * EEM_Registration::status_id_pending_payment |
|
| 638 | + * |
|
| 639 | + * @return boolean |
|
| 640 | + */ |
|
| 641 | + public function is_pending_payment() |
|
| 642 | + { |
|
| 643 | + return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false; |
|
| 644 | + } |
|
| 645 | + |
|
| 646 | + |
|
| 647 | + /** |
|
| 648 | + * is_approved - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved |
|
| 649 | + * |
|
| 650 | + * @return boolean |
|
| 651 | + */ |
|
| 652 | + public function is_approved() |
|
| 653 | + { |
|
| 654 | + return $this->status_ID() == EEM_Registration::status_id_approved ? true : false; |
|
| 655 | + } |
|
| 656 | + |
|
| 657 | + |
|
| 658 | + /** |
|
| 659 | + * is_cancelled - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled |
|
| 660 | + * |
|
| 661 | + * @return boolean |
|
| 662 | + */ |
|
| 663 | + public function is_cancelled() |
|
| 664 | + { |
|
| 665 | + return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false; |
|
| 666 | + } |
|
| 667 | + |
|
| 668 | + |
|
| 669 | + /** |
|
| 670 | + * is_declined - convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined |
|
| 671 | + * |
|
| 672 | + * @return boolean |
|
| 673 | + */ |
|
| 674 | + public function is_declined() |
|
| 675 | + { |
|
| 676 | + return $this->status_ID() == EEM_Registration::status_id_declined ? true : false; |
|
| 677 | + } |
|
| 678 | + |
|
| 679 | + |
|
| 680 | + /** |
|
| 681 | + * is_incomplete - convenience method that returns TRUE if REG status ID == |
|
| 682 | + * EEM_Registration::status_id_incomplete |
|
| 683 | + * |
|
| 684 | + * @return boolean |
|
| 685 | + */ |
|
| 686 | + public function is_incomplete() |
|
| 687 | + { |
|
| 688 | + return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false; |
|
| 689 | + } |
|
| 690 | + |
|
| 691 | + |
|
| 692 | + /** |
|
| 693 | + * Set Registration Date |
|
| 694 | + * |
|
| 695 | + * @param mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of |
|
| 696 | + * Date |
|
| 697 | + * @throws EE_Error |
|
| 698 | + * @throws RuntimeException |
|
| 699 | + */ |
|
| 700 | + public function set_reg_date($REG_date = false) |
|
| 701 | + { |
|
| 702 | + $this->set('REG_date', $REG_date); |
|
| 703 | + } |
|
| 704 | + |
|
| 705 | + |
|
| 706 | + /** |
|
| 707 | + * Set final price owing for this registration after all ticket/price modifications |
|
| 708 | + * |
|
| 709 | + * @access public |
|
| 710 | + * @param float $REG_final_price |
|
| 711 | + * @throws EE_Error |
|
| 712 | + * @throws RuntimeException |
|
| 713 | + */ |
|
| 714 | + public function set_final_price($REG_final_price = 0.00) |
|
| 715 | + { |
|
| 716 | + $this->set('REG_final_price', $REG_final_price); |
|
| 717 | + } |
|
| 718 | + |
|
| 719 | + |
|
| 720 | + /** |
|
| 721 | + * Set amount paid towards this registration's final price |
|
| 722 | + * |
|
| 723 | + * @access public |
|
| 724 | + * @param float $REG_paid |
|
| 725 | + * @throws EE_Error |
|
| 726 | + * @throws RuntimeException |
|
| 727 | + */ |
|
| 728 | + public function set_paid($REG_paid = 0.00) |
|
| 729 | + { |
|
| 730 | + $this->set('REG_paid', $REG_paid); |
|
| 731 | + } |
|
| 732 | + |
|
| 733 | + |
|
| 734 | + /** |
|
| 735 | + * Attendee Is Going |
|
| 736 | + * |
|
| 737 | + * @param boolean $REG_att_is_going Attendee Is Going |
|
| 738 | + * @throws EE_Error |
|
| 739 | + * @throws RuntimeException |
|
| 740 | + */ |
|
| 741 | + public function set_att_is_going($REG_att_is_going = false) |
|
| 742 | + { |
|
| 743 | + $this->set('REG_att_is_going', $REG_att_is_going); |
|
| 744 | + } |
|
| 745 | + |
|
| 746 | + |
|
| 747 | + /** |
|
| 748 | + * Gets the related attendee |
|
| 749 | + * |
|
| 750 | + * @return EE_Attendee |
|
| 751 | + * @throws EE_Error |
|
| 752 | + */ |
|
| 753 | + public function attendee() |
|
| 754 | + { |
|
| 755 | + return $this->get_first_related('Attendee'); |
|
| 756 | + } |
|
| 757 | + |
|
| 758 | + /** |
|
| 759 | + * Gets the name of the attendee. |
|
| 760 | + * @since $VID:$ |
|
| 761 | + * @param bool $apply_html_entities set to true if you want to use HTML entities. |
|
| 762 | + * @return string |
|
| 763 | + * @throws EE_Error |
|
| 764 | + * @throws InvalidArgumentException |
|
| 765 | + * @throws InvalidDataTypeException |
|
| 766 | + * @throws InvalidInterfaceException |
|
| 767 | + * @throws ReflectionException |
|
| 768 | + */ |
|
| 769 | + public function attendeeName($apply_html_entities = false) |
|
| 770 | + { |
|
| 771 | + $attendee = $this->get_first_related('Attendee'); |
|
| 772 | + if ($attendee instanceof EE_Attendee) { |
|
| 773 | + $attendee_name = $attendee->full_name($apply_html_entities); |
|
| 774 | + } else { |
|
| 775 | + $attendee_name = esc_html__('Unknown', 'event_espresso'); |
|
| 776 | + } |
|
| 777 | + return $attendee_name; |
|
| 778 | + } |
|
| 779 | + |
|
| 780 | + |
|
| 781 | + /** |
|
| 782 | + * get Event ID |
|
| 783 | + */ |
|
| 784 | + public function event_ID() |
|
| 785 | + { |
|
| 786 | + return $this->get('EVT_ID'); |
|
| 787 | + } |
|
| 788 | + |
|
| 789 | + |
|
| 790 | + /** |
|
| 791 | + * get Event ID |
|
| 792 | + */ |
|
| 793 | + public function event_name() |
|
| 794 | + { |
|
| 795 | + $event = $this->event_obj(); |
|
| 796 | + if ($event) { |
|
| 797 | + return $event->name(); |
|
| 798 | + } else { |
|
| 799 | + return null; |
|
| 800 | + } |
|
| 801 | + } |
|
| 802 | + |
|
| 803 | + |
|
| 804 | + /** |
|
| 805 | + * Fetches the event this registration is for |
|
| 806 | + * |
|
| 807 | + * @return EE_Event |
|
| 808 | + * @throws EE_Error |
|
| 809 | + */ |
|
| 810 | + public function event_obj() |
|
| 811 | + { |
|
| 812 | + return $this->get_first_related('Event'); |
|
| 813 | + } |
|
| 814 | + |
|
| 815 | + |
|
| 816 | + /** |
|
| 817 | + * get Attendee ID |
|
| 818 | + */ |
|
| 819 | + public function attendee_ID() |
|
| 820 | + { |
|
| 821 | + return $this->get('ATT_ID'); |
|
| 822 | + } |
|
| 823 | + |
|
| 824 | + |
|
| 825 | + /** |
|
| 826 | + * get PHP Session ID |
|
| 827 | + */ |
|
| 828 | + public function session_ID() |
|
| 829 | + { |
|
| 830 | + return $this->get('REG_session'); |
|
| 831 | + } |
|
| 832 | + |
|
| 833 | + |
|
| 834 | + /** |
|
| 835 | + * Gets the string which represents the URL trigger for the receipt template in the message template system. |
|
| 836 | + * |
|
| 837 | + * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
| 838 | + * @return string |
|
| 839 | + */ |
|
| 840 | + public function receipt_url($messenger = 'html') |
|
| 841 | + { |
|
| 842 | + |
|
| 843 | + /** |
|
| 844 | + * The below will be deprecated one version after this. We check first if there is a custom receipt template |
|
| 845 | + * already in use on old system. If there is then we just return the standard url for it. |
|
| 846 | + * |
|
| 847 | + * @since 4.5.0 |
|
| 848 | + */ |
|
| 849 | + $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php'; |
|
| 850 | + $has_custom = EEH_Template::locate_template( |
|
| 851 | + $template_relative_path, |
|
| 852 | + array(), |
|
| 853 | + true, |
|
| 854 | + true, |
|
| 855 | + true |
|
| 856 | + ); |
|
| 857 | + |
|
| 858 | + if ($has_custom) { |
|
| 859 | + return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch')); |
|
| 860 | + } |
|
| 861 | + return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt'); |
|
| 862 | + } |
|
| 863 | + |
|
| 864 | + |
|
| 865 | + /** |
|
| 866 | + * Gets the string which represents the URL trigger for the invoice template in the message template system. |
|
| 867 | + * |
|
| 868 | + * @param string $messenger 'pdf' or 'html'. Default 'html'. |
|
| 869 | + * @return string |
|
| 870 | + * @throws EE_Error |
|
| 871 | + */ |
|
| 872 | + public function invoice_url($messenger = 'html') |
|
| 873 | + { |
|
| 874 | + /** |
|
| 875 | + * The below will be deprecated one version after this. We check first if there is a custom invoice template |
|
| 876 | + * already in use on old system. If there is then we just return the standard url for it. |
|
| 877 | + * |
|
| 878 | + * @since 4.5.0 |
|
| 879 | + */ |
|
| 880 | + $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php'; |
|
| 881 | + $has_custom = EEH_Template::locate_template( |
|
| 882 | + $template_relative_path, |
|
| 883 | + array(), |
|
| 884 | + true, |
|
| 885 | + true, |
|
| 886 | + true |
|
| 887 | + ); |
|
| 888 | + |
|
| 889 | + if ($has_custom) { |
|
| 890 | + if ($messenger == 'html') { |
|
| 891 | + return $this->invoice_url('launch'); |
|
| 892 | + } |
|
| 893 | + $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice'; |
|
| 894 | + |
|
| 895 | + $query_args = array('ee' => $route, 'id' => $this->reg_url_link()); |
|
| 896 | + if ($messenger == 'html') { |
|
| 897 | + $query_args['html'] = true; |
|
| 898 | + } |
|
| 899 | + return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id)); |
|
| 900 | + } |
|
| 901 | + return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice'); |
|
| 902 | + } |
|
| 903 | + |
|
| 904 | + |
|
| 905 | + /** |
|
| 906 | + * get Registration URL Link |
|
| 907 | + * |
|
| 908 | + * @access public |
|
| 909 | + * @return string |
|
| 910 | + * @throws EE_Error |
|
| 911 | + */ |
|
| 912 | + public function reg_url_link() |
|
| 913 | + { |
|
| 914 | + return (string) $this->get('REG_url_link'); |
|
| 915 | + } |
|
| 916 | + |
|
| 917 | + |
|
| 918 | + /** |
|
| 919 | + * Echoes out invoice_url() |
|
| 920 | + * |
|
| 921 | + * @param string $type 'download','launch', or 'html' (default is 'launch') |
|
| 922 | + * @return void |
|
| 923 | + * @throws EE_Error |
|
| 924 | + */ |
|
| 925 | + public function e_invoice_url($type = 'launch') |
|
| 926 | + { |
|
| 927 | + echo $this->invoice_url($type); |
|
| 928 | + } |
|
| 929 | + |
|
| 930 | + |
|
| 931 | + /** |
|
| 932 | + * Echoes out payment_overview_url |
|
| 933 | + */ |
|
| 934 | + public function e_payment_overview_url() |
|
| 935 | + { |
|
| 936 | + echo $this->payment_overview_url(); |
|
| 937 | + } |
|
| 938 | + |
|
| 939 | + |
|
| 940 | + /** |
|
| 941 | + * Gets the URL for the checkout payment options reg step |
|
| 942 | + * with this registration's REG_url_link added as a query parameter |
|
| 943 | + * |
|
| 944 | + * @param bool $clear_session Set to true when you want to clear the session on revisiting the |
|
| 945 | + * payment overview url. |
|
| 946 | + * @return string |
|
| 947 | + * @throws InvalidInterfaceException |
|
| 948 | + * @throws InvalidDataTypeException |
|
| 949 | + * @throws EE_Error |
|
| 950 | + * @throws InvalidArgumentException |
|
| 951 | + */ |
|
| 952 | + public function payment_overview_url($clear_session = false) |
|
| 953 | + { |
|
| 954 | + return add_query_arg( |
|
| 955 | + (array) apply_filters( |
|
| 956 | + 'FHEE__EE_Registration__payment_overview_url__query_args', |
|
| 957 | + array( |
|
| 958 | + 'e_reg_url_link' => $this->reg_url_link(), |
|
| 959 | + 'step' => 'payment_options', |
|
| 960 | + 'revisit' => true, |
|
| 961 | + 'clear_session' => (bool) $clear_session, |
|
| 962 | + ), |
|
| 963 | + $this |
|
| 964 | + ), |
|
| 965 | + EE_Registry::instance()->CFG->core->reg_page_url() |
|
| 966 | + ); |
|
| 967 | + } |
|
| 968 | + |
|
| 969 | + |
|
| 970 | + /** |
|
| 971 | + * Gets the URL for the checkout attendee information reg step |
|
| 972 | + * with this registration's REG_url_link added as a query parameter |
|
| 973 | + * |
|
| 974 | + * @return string |
|
| 975 | + * @throws InvalidInterfaceException |
|
| 976 | + * @throws InvalidDataTypeException |
|
| 977 | + * @throws EE_Error |
|
| 978 | + * @throws InvalidArgumentException |
|
| 979 | + */ |
|
| 980 | + public function edit_attendee_information_url() |
|
| 981 | + { |
|
| 982 | + return add_query_arg( |
|
| 983 | + (array) apply_filters( |
|
| 984 | + 'FHEE__EE_Registration__edit_attendee_information_url__query_args', |
|
| 985 | + array( |
|
| 986 | + 'e_reg_url_link' => $this->reg_url_link(), |
|
| 987 | + 'step' => 'attendee_information', |
|
| 988 | + 'revisit' => true, |
|
| 989 | + ), |
|
| 990 | + $this |
|
| 991 | + ), |
|
| 992 | + EE_Registry::instance()->CFG->core->reg_page_url() |
|
| 993 | + ); |
|
| 994 | + } |
|
| 995 | + |
|
| 996 | + |
|
| 997 | + /** |
|
| 998 | + * Simply generates and returns the appropriate admin_url link to edit this registration |
|
| 999 | + * |
|
| 1000 | + * @return string |
|
| 1001 | + * @throws EE_Error |
|
| 1002 | + */ |
|
| 1003 | + public function get_admin_edit_url() |
|
| 1004 | + { |
|
| 1005 | + return EEH_URL::add_query_args_and_nonce( |
|
| 1006 | + array( |
|
| 1007 | + 'page' => 'espresso_registrations', |
|
| 1008 | + 'action' => 'view_registration', |
|
| 1009 | + '_REG_ID' => $this->ID(), |
|
| 1010 | + ), |
|
| 1011 | + admin_url('admin.php') |
|
| 1012 | + ); |
|
| 1013 | + } |
|
| 1014 | + |
|
| 1015 | + |
|
| 1016 | + /** |
|
| 1017 | + * is_primary_registrant? |
|
| 1018 | + */ |
|
| 1019 | + public function is_primary_registrant() |
|
| 1020 | + { |
|
| 1021 | + return $this->get('REG_count') === 1 ? true : false; |
|
| 1022 | + } |
|
| 1023 | + |
|
| 1024 | + |
|
| 1025 | + /** |
|
| 1026 | + * This returns the primary registration object for this registration group (which may be this object). |
|
| 1027 | + * |
|
| 1028 | + * @return EE_Registration |
|
| 1029 | + * @throws EE_Error |
|
| 1030 | + */ |
|
| 1031 | + public function get_primary_registration() |
|
| 1032 | + { |
|
| 1033 | + if ($this->is_primary_registrant()) { |
|
| 1034 | + return $this; |
|
| 1035 | + } |
|
| 1036 | + |
|
| 1037 | + // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1 |
|
| 1038 | + /** @var EE_Registration $primary_registrant */ |
|
| 1039 | + $primary_registrant = EEM_Registration::instance()->get_one( |
|
| 1040 | + array( |
|
| 1041 | + array( |
|
| 1042 | + 'TXN_ID' => $this->transaction_ID(), |
|
| 1043 | + 'REG_count' => 1, |
|
| 1044 | + ), |
|
| 1045 | + ) |
|
| 1046 | + ); |
|
| 1047 | + return $primary_registrant; |
|
| 1048 | + } |
|
| 1049 | + |
|
| 1050 | + |
|
| 1051 | + /** |
|
| 1052 | + * get Attendee Number |
|
| 1053 | + * |
|
| 1054 | + * @access public |
|
| 1055 | + */ |
|
| 1056 | + public function count() |
|
| 1057 | + { |
|
| 1058 | + return $this->get('REG_count'); |
|
| 1059 | + } |
|
| 1060 | + |
|
| 1061 | + |
|
| 1062 | + /** |
|
| 1063 | + * get Group Size |
|
| 1064 | + */ |
|
| 1065 | + public function group_size() |
|
| 1066 | + { |
|
| 1067 | + return $this->get('REG_group_size'); |
|
| 1068 | + } |
|
| 1069 | + |
|
| 1070 | + |
|
| 1071 | + /** |
|
| 1072 | + * get Registration Date |
|
| 1073 | + */ |
|
| 1074 | + public function date() |
|
| 1075 | + { |
|
| 1076 | + return $this->get('REG_date'); |
|
| 1077 | + } |
|
| 1078 | + |
|
| 1079 | + |
|
| 1080 | + /** |
|
| 1081 | + * gets a pretty date |
|
| 1082 | + * |
|
| 1083 | + * @param string $date_format |
|
| 1084 | + * @param string $time_format |
|
| 1085 | + * @return string |
|
| 1086 | + * @throws EE_Error |
|
| 1087 | + */ |
|
| 1088 | + public function pretty_date($date_format = null, $time_format = null) |
|
| 1089 | + { |
|
| 1090 | + return $this->get_datetime('REG_date', $date_format, $time_format); |
|
| 1091 | + } |
|
| 1092 | + |
|
| 1093 | + |
|
| 1094 | + /** |
|
| 1095 | + * final_price |
|
| 1096 | + * the registration's share of the transaction total, so that the |
|
| 1097 | + * sum of all the transaction's REG_final_prices equal the transaction's total |
|
| 1098 | + * |
|
| 1099 | + * @return float |
|
| 1100 | + * @throws EE_Error |
|
| 1101 | + */ |
|
| 1102 | + public function final_price() |
|
| 1103 | + { |
|
| 1104 | + return $this->get('REG_final_price'); |
|
| 1105 | + } |
|
| 1106 | + |
|
| 1107 | + |
|
| 1108 | + /** |
|
| 1109 | + * pretty_final_price |
|
| 1110 | + * final price as formatted string, with correct decimal places and currency symbol |
|
| 1111 | + * |
|
| 1112 | + * @return string |
|
| 1113 | + * @throws EE_Error |
|
| 1114 | + */ |
|
| 1115 | + public function pretty_final_price() |
|
| 1116 | + { |
|
| 1117 | + return $this->get_pretty('REG_final_price'); |
|
| 1118 | + } |
|
| 1119 | + |
|
| 1120 | + |
|
| 1121 | + /** |
|
| 1122 | + * get paid (yeah) |
|
| 1123 | + * |
|
| 1124 | + * @return float |
|
| 1125 | + * @throws EE_Error |
|
| 1126 | + */ |
|
| 1127 | + public function paid() |
|
| 1128 | + { |
|
| 1129 | + return $this->get('REG_paid'); |
|
| 1130 | + } |
|
| 1131 | + |
|
| 1132 | + |
|
| 1133 | + /** |
|
| 1134 | + * pretty_paid |
|
| 1135 | + * |
|
| 1136 | + * @return float |
|
| 1137 | + * @throws EE_Error |
|
| 1138 | + */ |
|
| 1139 | + public function pretty_paid() |
|
| 1140 | + { |
|
| 1141 | + return $this->get_pretty('REG_paid'); |
|
| 1142 | + } |
|
| 1143 | + |
|
| 1144 | + |
|
| 1145 | + /** |
|
| 1146 | + * owes_monies_and_can_pay |
|
| 1147 | + * whether or not this registration has monies owing and it's' status allows payment |
|
| 1148 | + * |
|
| 1149 | + * @param array $requires_payment |
|
| 1150 | + * @return bool |
|
| 1151 | + * @throws EE_Error |
|
| 1152 | + */ |
|
| 1153 | + public function owes_monies_and_can_pay($requires_payment = array()) |
|
| 1154 | + { |
|
| 1155 | + // these reg statuses require payment (if event is not free) |
|
| 1156 | + $requires_payment = ! empty($requires_payment) |
|
| 1157 | + ? $requires_payment |
|
| 1158 | + : EEM_Registration::reg_statuses_that_allow_payment(); |
|
| 1159 | + if ( |
|
| 1160 | + in_array($this->status_ID(), $requires_payment) && |
|
| 1161 | + $this->final_price() != 0 && |
|
| 1162 | + $this->final_price() != $this->paid() |
|
| 1163 | + ) { |
|
| 1164 | + return true; |
|
| 1165 | + } else { |
|
| 1166 | + return false; |
|
| 1167 | + } |
|
| 1168 | + } |
|
| 1169 | + |
|
| 1170 | + |
|
| 1171 | + /** |
|
| 1172 | + * Prints out the return value of $this->pretty_status() |
|
| 1173 | + * |
|
| 1174 | + * @param bool $show_icons |
|
| 1175 | + * @return void |
|
| 1176 | + * @throws EE_Error |
|
| 1177 | + */ |
|
| 1178 | + public function e_pretty_status($show_icons = false) |
|
| 1179 | + { |
|
| 1180 | + echo $this->pretty_status($show_icons); |
|
| 1181 | + } |
|
| 1182 | + |
|
| 1183 | + |
|
| 1184 | + /** |
|
| 1185 | + * Returns a nice version of the status for displaying to customers |
|
| 1186 | + * |
|
| 1187 | + * @param bool $show_icons |
|
| 1188 | + * @return string |
|
| 1189 | + * @throws EE_Error |
|
| 1190 | + */ |
|
| 1191 | + public function pretty_status($show_icons = false) |
|
| 1192 | + { |
|
| 1193 | + $status = EEM_Status::instance()->localized_status( |
|
| 1194 | + array($this->status_ID() => esc_html__('unknown', 'event_espresso')), |
|
| 1195 | + false, |
|
| 1196 | + 'sentence' |
|
| 1197 | + ); |
|
| 1198 | + $icon = ''; |
|
| 1199 | + switch ($this->status_ID()) { |
|
| 1200 | + case EEM_Registration::status_id_approved: |
|
| 1201 | + $icon = $show_icons |
|
| 1202 | + ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>' |
|
| 1203 | + : ''; |
|
| 1204 | + break; |
|
| 1205 | + case EEM_Registration::status_id_pending_payment: |
|
| 1206 | + $icon = $show_icons |
|
| 1207 | + ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>' |
|
| 1208 | + : ''; |
|
| 1209 | + break; |
|
| 1210 | + case EEM_Registration::status_id_not_approved: |
|
| 1211 | + $icon = $show_icons |
|
| 1212 | + ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>' |
|
| 1213 | + : ''; |
|
| 1214 | + break; |
|
| 1215 | + case EEM_Registration::status_id_cancelled: |
|
| 1216 | + $icon = $show_icons |
|
| 1217 | + ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>' |
|
| 1218 | + : ''; |
|
| 1219 | + break; |
|
| 1220 | + case EEM_Registration::status_id_incomplete: |
|
| 1221 | + $icon = $show_icons |
|
| 1222 | + ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>' |
|
| 1223 | + : ''; |
|
| 1224 | + break; |
|
| 1225 | + case EEM_Registration::status_id_declined: |
|
| 1226 | + $icon = $show_icons |
|
| 1227 | + ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>' |
|
| 1228 | + : ''; |
|
| 1229 | + break; |
|
| 1230 | + case EEM_Registration::status_id_wait_list: |
|
| 1231 | + $icon = $show_icons |
|
| 1232 | + ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>' |
|
| 1233 | + : ''; |
|
| 1234 | + break; |
|
| 1235 | + } |
|
| 1236 | + return $icon . $status[ $this->status_ID() ]; |
|
| 1237 | + } |
|
| 1238 | + |
|
| 1239 | + |
|
| 1240 | + /** |
|
| 1241 | + * get Attendee Is Going |
|
| 1242 | + */ |
|
| 1243 | + public function att_is_going() |
|
| 1244 | + { |
|
| 1245 | + return $this->get('REG_att_is_going'); |
|
| 1246 | + } |
|
| 1247 | + |
|
| 1248 | + |
|
| 1249 | + /** |
|
| 1250 | + * Gets related answers |
|
| 1251 | + * |
|
| 1252 | + * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1253 | + * @return EE_Answer[] |
|
| 1254 | + * @throws EE_Error |
|
| 1255 | + */ |
|
| 1256 | + public function answers($query_params = null) |
|
| 1257 | + { |
|
| 1258 | + return $this->get_many_related('Answer', $query_params); |
|
| 1259 | + } |
|
| 1260 | + |
|
| 1261 | + |
|
| 1262 | + /** |
|
| 1263 | + * Gets the registration's answer value to the specified question |
|
| 1264 | + * (either the question's ID or a question object) |
|
| 1265 | + * |
|
| 1266 | + * @param EE_Question|int $question |
|
| 1267 | + * @param bool $pretty_value |
|
| 1268 | + * @return array|string if pretty_value= true, the result will always be a string |
|
| 1269 | + * (because the answer might be an array of answer values, so passing pretty_value=true |
|
| 1270 | + * will convert it into some kind of string) |
|
| 1271 | + * @throws EE_Error |
|
| 1272 | + */ |
|
| 1273 | + public function answer_value_to_question($question, $pretty_value = true) |
|
| 1274 | + { |
|
| 1275 | + $question_id = EEM_Question::instance()->ensure_is_ID($question); |
|
| 1276 | + return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value); |
|
| 1277 | + } |
|
| 1278 | + |
|
| 1279 | + |
|
| 1280 | + /** |
|
| 1281 | + * question_groups |
|
| 1282 | + * returns an array of EE_Question_Group objects for this registration |
|
| 1283 | + * |
|
| 1284 | + * @return EE_Question_Group[] |
|
| 1285 | + * @throws EE_Error |
|
| 1286 | + * @throws InvalidArgumentException |
|
| 1287 | + * @throws InvalidDataTypeException |
|
| 1288 | + * @throws InvalidInterfaceException |
|
| 1289 | + * @throws ReflectionException |
|
| 1290 | + */ |
|
| 1291 | + public function question_groups() |
|
| 1292 | + { |
|
| 1293 | + return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this); |
|
| 1294 | + } |
|
| 1295 | + |
|
| 1296 | + |
|
| 1297 | + /** |
|
| 1298 | + * count_question_groups |
|
| 1299 | + * returns a count of the number of EE_Question_Group objects for this registration |
|
| 1300 | + * |
|
| 1301 | + * @return int |
|
| 1302 | + * @throws EE_Error |
|
| 1303 | + * @throws EntityNotFoundException |
|
| 1304 | + * @throws InvalidArgumentException |
|
| 1305 | + * @throws InvalidDataTypeException |
|
| 1306 | + * @throws InvalidInterfaceException |
|
| 1307 | + * @throws ReflectionException |
|
| 1308 | + */ |
|
| 1309 | + public function count_question_groups() |
|
| 1310 | + { |
|
| 1311 | + return EEM_Event::instance()->count_related( |
|
| 1312 | + $this->event_ID(), |
|
| 1313 | + 'Question_Group', |
|
| 1314 | + [ |
|
| 1315 | + [ |
|
| 1316 | + 'Event_Question_Group.' |
|
| 1317 | + . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true, |
|
| 1318 | + ] |
|
| 1319 | + ] |
|
| 1320 | + ); |
|
| 1321 | + } |
|
| 1322 | + |
|
| 1323 | + |
|
| 1324 | + /** |
|
| 1325 | + * Returns the registration date in the 'standard' string format |
|
| 1326 | + * (function may be improved in the future to allow for different formats and timezones) |
|
| 1327 | + * |
|
| 1328 | + * @return string |
|
| 1329 | + * @throws EE_Error |
|
| 1330 | + */ |
|
| 1331 | + public function reg_date() |
|
| 1332 | + { |
|
| 1333 | + return $this->get_datetime('REG_date'); |
|
| 1334 | + } |
|
| 1335 | + |
|
| 1336 | + |
|
| 1337 | + /** |
|
| 1338 | + * Gets the datetime-ticket for this registration (ie, it can be used to isolate |
|
| 1339 | + * the ticket this registration purchased, or the datetime they have registered |
|
| 1340 | + * to attend) |
|
| 1341 | + * |
|
| 1342 | + * @return EE_Datetime_Ticket |
|
| 1343 | + * @throws EE_Error |
|
| 1344 | + */ |
|
| 1345 | + public function datetime_ticket() |
|
| 1346 | + { |
|
| 1347 | + return $this->get_first_related('Datetime_Ticket'); |
|
| 1348 | + } |
|
| 1349 | + |
|
| 1350 | + |
|
| 1351 | + /** |
|
| 1352 | + * Sets the registration's datetime_ticket. |
|
| 1353 | + * |
|
| 1354 | + * @param EE_Datetime_Ticket $datetime_ticket |
|
| 1355 | + * @return EE_Datetime_Ticket |
|
| 1356 | + * @throws EE_Error |
|
| 1357 | + */ |
|
| 1358 | + public function set_datetime_ticket($datetime_ticket) |
|
| 1359 | + { |
|
| 1360 | + return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket'); |
|
| 1361 | + } |
|
| 1362 | + |
|
| 1363 | + /** |
|
| 1364 | + * Gets deleted |
|
| 1365 | + * |
|
| 1366 | + * @return bool |
|
| 1367 | + * @throws EE_Error |
|
| 1368 | + */ |
|
| 1369 | + public function deleted() |
|
| 1370 | + { |
|
| 1371 | + return $this->get('REG_deleted'); |
|
| 1372 | + } |
|
| 1373 | + |
|
| 1374 | + /** |
|
| 1375 | + * Sets deleted |
|
| 1376 | + * |
|
| 1377 | + * @param boolean $deleted |
|
| 1378 | + * @return bool |
|
| 1379 | + * @throws EE_Error |
|
| 1380 | + * @throws RuntimeException |
|
| 1381 | + */ |
|
| 1382 | + public function set_deleted($deleted) |
|
| 1383 | + { |
|
| 1384 | + if ($deleted) { |
|
| 1385 | + $this->delete(); |
|
| 1386 | + } else { |
|
| 1387 | + $this->restore(); |
|
| 1388 | + } |
|
| 1389 | + } |
|
| 1390 | + |
|
| 1391 | + |
|
| 1392 | + /** |
|
| 1393 | + * Get the status object of this object |
|
| 1394 | + * |
|
| 1395 | + * @return EE_Status |
|
| 1396 | + * @throws EE_Error |
|
| 1397 | + */ |
|
| 1398 | + public function status_obj() |
|
| 1399 | + { |
|
| 1400 | + return $this->get_first_related('Status'); |
|
| 1401 | + } |
|
| 1402 | + |
|
| 1403 | + |
|
| 1404 | + /** |
|
| 1405 | + * Returns the number of times this registration has checked into any of the datetimes |
|
| 1406 | + * its available for |
|
| 1407 | + * |
|
| 1408 | + * @return int |
|
| 1409 | + * @throws EE_Error |
|
| 1410 | + */ |
|
| 1411 | + public function count_checkins() |
|
| 1412 | + { |
|
| 1413 | + return $this->get_model()->count_related($this, 'Checkin'); |
|
| 1414 | + } |
|
| 1415 | + |
|
| 1416 | + |
|
| 1417 | + /** |
|
| 1418 | + * Returns the number of current Check-ins this registration is checked into for any of the datetimes the |
|
| 1419 | + * registration is for. Note, this is ONLY checked in (does not include checkedout) |
|
| 1420 | + * |
|
| 1421 | + * @return int |
|
| 1422 | + * @throws EE_Error |
|
| 1423 | + */ |
|
| 1424 | + public function count_checkins_not_checkedout() |
|
| 1425 | + { |
|
| 1426 | + return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1))); |
|
| 1427 | + } |
|
| 1428 | + |
|
| 1429 | + |
|
| 1430 | + /** |
|
| 1431 | + * The purpose of this method is simply to check whether this registration can checkin to the given datetime. |
|
| 1432 | + * |
|
| 1433 | + * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
| 1434 | + * @param bool $check_approved This is used to indicate whether the caller wants can_checkin to also |
|
| 1435 | + * consider registration status as well as datetime access. |
|
| 1436 | + * @return bool |
|
| 1437 | + * @throws EE_Error |
|
| 1438 | + */ |
|
| 1439 | + public function can_checkin($DTT_OR_ID, $check_approved = true) |
|
| 1440 | + { |
|
| 1441 | + $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
| 1442 | + |
|
| 1443 | + // first check registration status |
|
| 1444 | + if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) { |
|
| 1445 | + return false; |
|
| 1446 | + } |
|
| 1447 | + // is there a datetime ticket that matches this dtt_ID? |
|
| 1448 | + if ( |
|
| 1449 | + ! (EEM_Datetime_Ticket::instance()->exists( |
|
| 1450 | + array( |
|
| 1451 | + array( |
|
| 1452 | + 'TKT_ID' => $this->get('TKT_ID'), |
|
| 1453 | + 'DTT_ID' => $DTT_ID, |
|
| 1454 | + ), |
|
| 1455 | + ) |
|
| 1456 | + )) |
|
| 1457 | + ) { |
|
| 1458 | + return false; |
|
| 1459 | + } |
|
| 1460 | + |
|
| 1461 | + // final check is against TKT_uses |
|
| 1462 | + return $this->verify_can_checkin_against_TKT_uses($DTT_ID); |
|
| 1463 | + } |
|
| 1464 | + |
|
| 1465 | + |
|
| 1466 | + /** |
|
| 1467 | + * This method verifies whether the user can checkin for the given datetime considering the max uses value set on |
|
| 1468 | + * the ticket. To do this, a query is done to get the count of the datetime records already checked into. If the |
|
| 1469 | + * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses, |
|
| 1470 | + * then return false. Otherwise return true. |
|
| 1471 | + * |
|
| 1472 | + * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against |
|
| 1473 | + * @return bool true means can checkin. false means cannot checkin. |
|
| 1474 | + * @throws EE_Error |
|
| 1475 | + */ |
|
| 1476 | + public function verify_can_checkin_against_TKT_uses($DTT_OR_ID) |
|
| 1477 | + { |
|
| 1478 | + $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID); |
|
| 1479 | + |
|
| 1480 | + if (! $DTT_ID) { |
|
| 1481 | + return false; |
|
| 1482 | + } |
|
| 1483 | + |
|
| 1484 | + $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF; |
|
| 1485 | + |
|
| 1486 | + // if max uses is not set or equals infinity then return true cause its not a factor for whether user can |
|
| 1487 | + // check-in or not. |
|
| 1488 | + if (! $max_uses || $max_uses === EE_INF) { |
|
| 1489 | + return true; |
|
| 1490 | + } |
|
| 1491 | + |
|
| 1492 | + // does this datetime have a checkin record? If so, then the dtt count has already been verified so we can just |
|
| 1493 | + // go ahead and toggle. |
|
| 1494 | + if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) { |
|
| 1495 | + return true; |
|
| 1496 | + } |
|
| 1497 | + |
|
| 1498 | + // made it here so the last check is whether the number of checkins per unique datetime on this registration |
|
| 1499 | + // disallows further check-ins. |
|
| 1500 | + $count_unique_dtt_checkins = EEM_Checkin::instance()->count( |
|
| 1501 | + array( |
|
| 1502 | + array( |
|
| 1503 | + 'REG_ID' => $this->ID(), |
|
| 1504 | + 'CHK_in' => true, |
|
| 1505 | + ), |
|
| 1506 | + ), |
|
| 1507 | + 'DTT_ID', |
|
| 1508 | + true |
|
| 1509 | + ); |
|
| 1510 | + // checkins have already reached their max number of uses |
|
| 1511 | + // so registrant can NOT checkin |
|
| 1512 | + if ($count_unique_dtt_checkins >= $max_uses) { |
|
| 1513 | + EE_Error::add_error( |
|
| 1514 | + esc_html__( |
|
| 1515 | + 'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.', |
|
| 1516 | + 'event_espresso' |
|
| 1517 | + ), |
|
| 1518 | + __FILE__, |
|
| 1519 | + __FUNCTION__, |
|
| 1520 | + __LINE__ |
|
| 1521 | + ); |
|
| 1522 | + return false; |
|
| 1523 | + } |
|
| 1524 | + return true; |
|
| 1525 | + } |
|
| 1526 | + |
|
| 1527 | + |
|
| 1528 | + /** |
|
| 1529 | + * toggle Check-in status for this registration |
|
| 1530 | + * Check-ins are toggled in the following order: |
|
| 1531 | + * never checked in -> checked in |
|
| 1532 | + * checked in -> checked out |
|
| 1533 | + * checked out -> checked in |
|
| 1534 | + * |
|
| 1535 | + * @param int $DTT_ID include specific datetime to toggle Check-in for. |
|
| 1536 | + * If not included or null, then it is assumed latest datetime is being toggled. |
|
| 1537 | + * @param bool $verify If true then can_checkin() is used to verify whether the person |
|
| 1538 | + * can be checked in or not. Otherwise this forces change in checkin status. |
|
| 1539 | + * @return bool|int the chk_in status toggled to OR false if nothing got changed. |
|
| 1540 | + * @throws EE_Error |
|
| 1541 | + */ |
|
| 1542 | + public function toggle_checkin_status($DTT_ID = null, $verify = false) |
|
| 1543 | + { |
|
| 1544 | + if (empty($DTT_ID)) { |
|
| 1545 | + $datetime = $this->get_latest_related_datetime(); |
|
| 1546 | + $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0; |
|
| 1547 | + // verify the registration can checkin for the given DTT_ID |
|
| 1548 | + } elseif (! $this->can_checkin($DTT_ID, $verify)) { |
|
| 1549 | + EE_Error::add_error( |
|
| 1550 | + sprintf( |
|
| 1551 | + esc_html__( |
|
| 1552 | + 'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access', |
|
| 1553 | + 'event_espresso' |
|
| 1554 | + ), |
|
| 1555 | + $this->ID(), |
|
| 1556 | + $DTT_ID |
|
| 1557 | + ), |
|
| 1558 | + __FILE__, |
|
| 1559 | + __FUNCTION__, |
|
| 1560 | + __LINE__ |
|
| 1561 | + ); |
|
| 1562 | + return false; |
|
| 1563 | + } |
|
| 1564 | + $status_paths = array( |
|
| 1565 | + EE_Checkin::status_checked_never => EE_Checkin::status_checked_in, |
|
| 1566 | + EE_Checkin::status_checked_in => EE_Checkin::status_checked_out, |
|
| 1567 | + EE_Checkin::status_checked_out => EE_Checkin::status_checked_in, |
|
| 1568 | + ); |
|
| 1569 | + // start by getting the current status so we know what status we'll be changing to. |
|
| 1570 | + $cur_status = $this->check_in_status_for_datetime($DTT_ID, null); |
|
| 1571 | + $status_to = $status_paths[ $cur_status ]; |
|
| 1572 | + // database only records true for checked IN or false for checked OUT |
|
| 1573 | + // no record ( null ) means checked in NEVER, but we obviously don't save that |
|
| 1574 | + $new_status = $status_to === EE_Checkin::status_checked_in ? true : false; |
|
| 1575 | + // add relation - note Check-ins are always creating new rows |
|
| 1576 | + // because we are keeping track of Check-ins over time. |
|
| 1577 | + // Eventually we'll probably want to show a list table |
|
| 1578 | + // for the individual Check-ins so that they can be managed. |
|
| 1579 | + $checkin = EE_Checkin::new_instance( |
|
| 1580 | + array( |
|
| 1581 | + 'REG_ID' => $this->ID(), |
|
| 1582 | + 'DTT_ID' => $DTT_ID, |
|
| 1583 | + 'CHK_in' => $new_status, |
|
| 1584 | + ) |
|
| 1585 | + ); |
|
| 1586 | + // if the record could not be saved then return false |
|
| 1587 | + if ($checkin->save() === 0) { |
|
| 1588 | + if (WP_DEBUG) { |
|
| 1589 | + global $wpdb; |
|
| 1590 | + $error = sprintf( |
|
| 1591 | + esc_html__( |
|
| 1592 | + 'Registration check in update failed because of the following database error: %1$s%2$s', |
|
| 1593 | + 'event_espresso' |
|
| 1594 | + ), |
|
| 1595 | + '<br />', |
|
| 1596 | + $wpdb->last_error |
|
| 1597 | + ); |
|
| 1598 | + } else { |
|
| 1599 | + $error = esc_html__( |
|
| 1600 | + 'Registration check in update failed because of an unknown database error', |
|
| 1601 | + 'event_espresso' |
|
| 1602 | + ); |
|
| 1603 | + } |
|
| 1604 | + EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__); |
|
| 1605 | + return false; |
|
| 1606 | + } |
|
| 1607 | + // Fire a checked_in and checkout_out action. |
|
| 1608 | + $checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out'; |
|
| 1609 | + do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID); |
|
| 1610 | + return $status_to; |
|
| 1611 | + } |
|
| 1612 | + |
|
| 1613 | + |
|
| 1614 | + /** |
|
| 1615 | + * Returns the latest datetime related to this registration (via the ticket attached to the registration). |
|
| 1616 | + * "Latest" is defined by the `DTT_EVT_start` column. |
|
| 1617 | + * |
|
| 1618 | + * @return EE_Datetime|null |
|
| 1619 | + * @throws EE_Error |
|
| 1620 | + */ |
|
| 1621 | + public function get_latest_related_datetime() |
|
| 1622 | + { |
|
| 1623 | + return EEM_Datetime::instance()->get_one( |
|
| 1624 | + array( |
|
| 1625 | + array( |
|
| 1626 | + 'Ticket.Registration.REG_ID' => $this->ID(), |
|
| 1627 | + ), |
|
| 1628 | + 'order_by' => array('DTT_EVT_start' => 'DESC'), |
|
| 1629 | + ) |
|
| 1630 | + ); |
|
| 1631 | + } |
|
| 1632 | + |
|
| 1633 | + |
|
| 1634 | + /** |
|
| 1635 | + * Returns the earliest datetime related to this registration (via the ticket attached to the registration). |
|
| 1636 | + * "Earliest" is defined by the `DTT_EVT_start` column. |
|
| 1637 | + * |
|
| 1638 | + * @throws EE_Error |
|
| 1639 | + */ |
|
| 1640 | + public function get_earliest_related_datetime() |
|
| 1641 | + { |
|
| 1642 | + return EEM_Datetime::instance()->get_one( |
|
| 1643 | + array( |
|
| 1644 | + array( |
|
| 1645 | + 'Ticket.Registration.REG_ID' => $this->ID(), |
|
| 1646 | + ), |
|
| 1647 | + 'order_by' => array('DTT_EVT_start' => 'ASC'), |
|
| 1648 | + ) |
|
| 1649 | + ); |
|
| 1650 | + } |
|
| 1651 | + |
|
| 1652 | + |
|
| 1653 | + /** |
|
| 1654 | + * This method simply returns the check-in status for this registration and the given datetime. |
|
| 1655 | + * If neither the datetime nor the checkin values are provided as arguments, |
|
| 1656 | + * then this will return the LATEST check-in status for the registration across all datetimes it belongs to. |
|
| 1657 | + * |
|
| 1658 | + * @param int $DTT_ID The ID of the datetime we're checking against |
|
| 1659 | + * (if empty we'll get the primary datetime for |
|
| 1660 | + * this registration (via event) and use it's ID); |
|
| 1661 | + * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id. |
|
| 1662 | + * |
|
| 1663 | + * @return int Integer representing Check-in status. |
|
| 1664 | + * @throws EE_Error |
|
| 1665 | + */ |
|
| 1666 | + public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null) |
|
| 1667 | + { |
|
| 1668 | + $checkin_query_params = array( |
|
| 1669 | + 'order_by' => array('CHK_timestamp' => 'DESC'), |
|
| 1670 | + ); |
|
| 1671 | + |
|
| 1672 | + if ($DTT_ID > 0) { |
|
| 1673 | + $checkin_query_params[0] = array('DTT_ID' => $DTT_ID); |
|
| 1674 | + } |
|
| 1675 | + |
|
| 1676 | + // get checkin object (if exists) |
|
| 1677 | + $checkin = $checkin instanceof EE_Checkin |
|
| 1678 | + ? $checkin |
|
| 1679 | + : $this->get_first_related('Checkin', $checkin_query_params); |
|
| 1680 | + if ($checkin instanceof EE_Checkin) { |
|
| 1681 | + if ($checkin->get('CHK_in')) { |
|
| 1682 | + return EE_Checkin::status_checked_in; // checked in |
|
| 1683 | + } |
|
| 1684 | + return EE_Checkin::status_checked_out; // had checked in but is now checked out. |
|
| 1685 | + } |
|
| 1686 | + return EE_Checkin::status_checked_never; // never been checked in |
|
| 1687 | + } |
|
| 1688 | + |
|
| 1689 | + |
|
| 1690 | + /** |
|
| 1691 | + * This method returns a localized message for the toggled Check-in message. |
|
| 1692 | + * |
|
| 1693 | + * @param int $DTT_ID include specific datetime to get the correct Check-in message. If not included or null, |
|
| 1694 | + * then it is assumed Check-in for primary datetime was toggled. |
|
| 1695 | + * @param bool $error This just flags that you want an error message returned. This is put in so that the error |
|
| 1696 | + * message can be customized with the attendee name. |
|
| 1697 | + * @return string internationalized message |
|
| 1698 | + * @throws EE_Error |
|
| 1699 | + */ |
|
| 1700 | + public function get_checkin_msg($DTT_ID, $error = false) |
|
| 1701 | + { |
|
| 1702 | + // let's get the attendee first so we can include the name of the attendee |
|
| 1703 | + $attendee = $this->get_first_related('Attendee'); |
|
| 1704 | + if ($attendee instanceof EE_Attendee) { |
|
| 1705 | + if ($error) { |
|
| 1706 | + return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name()); |
|
| 1707 | + } |
|
| 1708 | + $cur_status = $this->check_in_status_for_datetime($DTT_ID); |
|
| 1709 | + // what is the status message going to be? |
|
| 1710 | + switch ($cur_status) { |
|
| 1711 | + case EE_Checkin::status_checked_never: |
|
| 1712 | + return sprintf( |
|
| 1713 | + __("%s has been removed from Check-in records", "event_espresso"), |
|
| 1714 | + $attendee->full_name() |
|
| 1715 | + ); |
|
| 1716 | + break; |
|
| 1717 | + case EE_Checkin::status_checked_in: |
|
| 1718 | + return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name()); |
|
| 1719 | + break; |
|
| 1720 | + case EE_Checkin::status_checked_out: |
|
| 1721 | + return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name()); |
|
| 1722 | + break; |
|
| 1723 | + } |
|
| 1724 | + } |
|
| 1725 | + return esc_html__("The check-in status could not be determined.", "event_espresso"); |
|
| 1726 | + } |
|
| 1727 | + |
|
| 1728 | + |
|
| 1729 | + /** |
|
| 1730 | + * Returns the related EE_Transaction to this registration |
|
| 1731 | + * |
|
| 1732 | + * @return EE_Transaction |
|
| 1733 | + * @throws EE_Error |
|
| 1734 | + * @throws EntityNotFoundException |
|
| 1735 | + */ |
|
| 1736 | + public function transaction() |
|
| 1737 | + { |
|
| 1738 | + $transaction = $this->get_first_related('Transaction'); |
|
| 1739 | + if (! $transaction instanceof \EE_Transaction) { |
|
| 1740 | + throw new EntityNotFoundException('Transaction ID', $this->transaction_ID()); |
|
| 1741 | + } |
|
| 1742 | + return $transaction; |
|
| 1743 | + } |
|
| 1744 | + |
|
| 1745 | + |
|
| 1746 | + /** |
|
| 1747 | + * get Registration Code |
|
| 1748 | + */ |
|
| 1749 | + public function reg_code() |
|
| 1750 | + { |
|
| 1751 | + return $this->get('REG_code'); |
|
| 1752 | + } |
|
| 1753 | + |
|
| 1754 | + |
|
| 1755 | + /** |
|
| 1756 | + * get Transaction ID |
|
| 1757 | + */ |
|
| 1758 | + public function transaction_ID() |
|
| 1759 | + { |
|
| 1760 | + return $this->get('TXN_ID'); |
|
| 1761 | + } |
|
| 1762 | + |
|
| 1763 | + |
|
| 1764 | + /** |
|
| 1765 | + * @return int |
|
| 1766 | + * @throws EE_Error |
|
| 1767 | + */ |
|
| 1768 | + public function ticket_ID() |
|
| 1769 | + { |
|
| 1770 | + return $this->get('TKT_ID'); |
|
| 1771 | + } |
|
| 1772 | + |
|
| 1773 | + |
|
| 1774 | + /** |
|
| 1775 | + * Set Registration Code |
|
| 1776 | + * |
|
| 1777 | + * @access public |
|
| 1778 | + * @param string $REG_code Registration Code |
|
| 1779 | + * @param boolean $use_default |
|
| 1780 | + * @throws EE_Error |
|
| 1781 | + */ |
|
| 1782 | + public function set_reg_code($REG_code, $use_default = false) |
|
| 1783 | + { |
|
| 1784 | + if (empty($REG_code)) { |
|
| 1785 | + EE_Error::add_error( |
|
| 1786 | + esc_html__('REG_code can not be empty.', 'event_espresso'), |
|
| 1787 | + __FILE__, |
|
| 1788 | + __FUNCTION__, |
|
| 1789 | + __LINE__ |
|
| 1790 | + ); |
|
| 1791 | + return; |
|
| 1792 | + } |
|
| 1793 | + if (! $this->reg_code()) { |
|
| 1794 | + parent::set('REG_code', $REG_code, $use_default); |
|
| 1795 | + } else { |
|
| 1796 | + EE_Error::doing_it_wrong( |
|
| 1797 | + __CLASS__ . '::' . __FUNCTION__, |
|
| 1798 | + esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'), |
|
| 1799 | + '4.6.0' |
|
| 1800 | + ); |
|
| 1801 | + } |
|
| 1802 | + } |
|
| 1803 | + |
|
| 1804 | + |
|
| 1805 | + /** |
|
| 1806 | + * Returns all other registrations in the same group as this registrant who have the same ticket option. |
|
| 1807 | + * Note, if you want to just get all registrations in the same transaction (group), use: |
|
| 1808 | + * $registration->transaction()->registrations(); |
|
| 1809 | + * |
|
| 1810 | + * @since 4.5.0 |
|
| 1811 | + * @return EE_Registration[] or empty array if this isn't a group registration. |
|
| 1812 | + * @throws EE_Error |
|
| 1813 | + */ |
|
| 1814 | + public function get_all_other_registrations_in_group() |
|
| 1815 | + { |
|
| 1816 | + if ($this->group_size() < 2) { |
|
| 1817 | + return array(); |
|
| 1818 | + } |
|
| 1819 | + |
|
| 1820 | + $query[0] = array( |
|
| 1821 | + 'TXN_ID' => $this->transaction_ID(), |
|
| 1822 | + 'REG_ID' => array('!=', $this->ID()), |
|
| 1823 | + 'TKT_ID' => $this->ticket_ID(), |
|
| 1824 | + ); |
|
| 1825 | + /** @var EE_Registration[] $registrations */ |
|
| 1826 | + $registrations = $this->get_model()->get_all($query); |
|
| 1827 | + return $registrations; |
|
| 1828 | + } |
|
| 1829 | + |
|
| 1830 | + /** |
|
| 1831 | + * Return the link to the admin details for the object. |
|
| 1832 | + * |
|
| 1833 | + * @return string |
|
| 1834 | + * @throws EE_Error |
|
| 1835 | + */ |
|
| 1836 | + public function get_admin_details_link() |
|
| 1837 | + { |
|
| 1838 | + EE_Registry::instance()->load_helper('URL'); |
|
| 1839 | + return EEH_URL::add_query_args_and_nonce( |
|
| 1840 | + array( |
|
| 1841 | + 'page' => 'espresso_registrations', |
|
| 1842 | + 'action' => 'view_registration', |
|
| 1843 | + '_REG_ID' => $this->ID(), |
|
| 1844 | + ), |
|
| 1845 | + admin_url('admin.php') |
|
| 1846 | + ); |
|
| 1847 | + } |
|
| 1848 | + |
|
| 1849 | + /** |
|
| 1850 | + * Returns the link to the editor for the object. Sometimes this is the same as the details. |
|
| 1851 | + * |
|
| 1852 | + * @return string |
|
| 1853 | + * @throws EE_Error |
|
| 1854 | + */ |
|
| 1855 | + public function get_admin_edit_link() |
|
| 1856 | + { |
|
| 1857 | + return $this->get_admin_details_link(); |
|
| 1858 | + } |
|
| 1859 | + |
|
| 1860 | + /** |
|
| 1861 | + * Returns the link to a settings page for the object. |
|
| 1862 | + * |
|
| 1863 | + * @return string |
|
| 1864 | + * @throws EE_Error |
|
| 1865 | + */ |
|
| 1866 | + public function get_admin_settings_link() |
|
| 1867 | + { |
|
| 1868 | + return $this->get_admin_details_link(); |
|
| 1869 | + } |
|
| 1870 | + |
|
| 1871 | + /** |
|
| 1872 | + * Returns the link to the "overview" for the object (typically the "list table" view). |
|
| 1873 | + * |
|
| 1874 | + * @return string |
|
| 1875 | + */ |
|
| 1876 | + public function get_admin_overview_link() |
|
| 1877 | + { |
|
| 1878 | + EE_Registry::instance()->load_helper('URL'); |
|
| 1879 | + return EEH_URL::add_query_args_and_nonce( |
|
| 1880 | + array( |
|
| 1881 | + 'page' => 'espresso_registrations', |
|
| 1882 | + ), |
|
| 1883 | + admin_url('admin.php') |
|
| 1884 | + ); |
|
| 1885 | + } |
|
| 1886 | + |
|
| 1887 | + |
|
| 1888 | + /** |
|
| 1889 | + * @param array $query_params |
|
| 1890 | + * |
|
| 1891 | + * @return \EE_Registration[] |
|
| 1892 | + * @throws EE_Error |
|
| 1893 | + */ |
|
| 1894 | + public function payments($query_params = array()) |
|
| 1895 | + { |
|
| 1896 | + return $this->get_many_related('Payment', $query_params); |
|
| 1897 | + } |
|
| 1898 | + |
|
| 1899 | + |
|
| 1900 | + /** |
|
| 1901 | + * @param array $query_params |
|
| 1902 | + * |
|
| 1903 | + * @return \EE_Registration_Payment[] |
|
| 1904 | + * @throws EE_Error |
|
| 1905 | + */ |
|
| 1906 | + public function registration_payments($query_params = array()) |
|
| 1907 | + { |
|
| 1908 | + return $this->get_many_related('Registration_Payment', $query_params); |
|
| 1909 | + } |
|
| 1910 | + |
|
| 1911 | + |
|
| 1912 | + /** |
|
| 1913 | + * This grabs the payment method corresponding to the last payment made for the amount owing on the registration. |
|
| 1914 | + * Note: if there are no payments on the registration there will be no payment method returned. |
|
| 1915 | + * |
|
| 1916 | + * @return EE_Payment_Method|null |
|
| 1917 | + */ |
|
| 1918 | + public function payment_method() |
|
| 1919 | + { |
|
| 1920 | + return EEM_Payment_Method::instance()->get_last_used_for_registration($this); |
|
| 1921 | + } |
|
| 1922 | + |
|
| 1923 | + |
|
| 1924 | + /** |
|
| 1925 | + * @return \EE_Line_Item |
|
| 1926 | + * @throws EntityNotFoundException |
|
| 1927 | + * @throws EE_Error |
|
| 1928 | + */ |
|
| 1929 | + public function ticket_line_item() |
|
| 1930 | + { |
|
| 1931 | + $ticket = $this->ticket(); |
|
| 1932 | + $transaction = $this->transaction(); |
|
| 1933 | + $line_item = null; |
|
| 1934 | + $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs( |
|
| 1935 | + $transaction->total_line_item(), |
|
| 1936 | + 'Ticket', |
|
| 1937 | + array($ticket->ID()) |
|
| 1938 | + ); |
|
| 1939 | + foreach ($ticket_line_items as $ticket_line_item) { |
|
| 1940 | + if ( |
|
| 1941 | + $ticket_line_item instanceof \EE_Line_Item |
|
| 1942 | + && $ticket_line_item->OBJ_type() === 'Ticket' |
|
| 1943 | + && $ticket_line_item->OBJ_ID() === $ticket->ID() |
|
| 1944 | + ) { |
|
| 1945 | + $line_item = $ticket_line_item; |
|
| 1946 | + break; |
|
| 1947 | + } |
|
| 1948 | + } |
|
| 1949 | + if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) { |
|
| 1950 | + throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID()); |
|
| 1951 | + } |
|
| 1952 | + return $line_item; |
|
| 1953 | + } |
|
| 1954 | + |
|
| 1955 | + |
|
| 1956 | + /** |
|
| 1957 | + * Soft Deletes this model object. |
|
| 1958 | + * |
|
| 1959 | + * @return boolean | int |
|
| 1960 | + * @throws RuntimeException |
|
| 1961 | + * @throws EE_Error |
|
| 1962 | + */ |
|
| 1963 | + public function delete() |
|
| 1964 | + { |
|
| 1965 | + if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) { |
|
| 1966 | + $this->set_status(EEM_Registration::status_id_cancelled); |
|
| 1967 | + } |
|
| 1968 | + return parent::delete(); |
|
| 1969 | + } |
|
| 1970 | + |
|
| 1971 | + |
|
| 1972 | + /** |
|
| 1973 | + * Restores whatever the previous status was on a registration before it was trashed (if possible) |
|
| 1974 | + * |
|
| 1975 | + * @throws EE_Error |
|
| 1976 | + * @throws RuntimeException |
|
| 1977 | + */ |
|
| 1978 | + public function restore() |
|
| 1979 | + { |
|
| 1980 | + $previous_status = $this->get_extra_meta( |
|
| 1981 | + EE_Registration::PRE_TRASH_REG_STATUS_KEY, |
|
| 1982 | + true, |
|
| 1983 | + EEM_Registration::status_id_cancelled |
|
| 1984 | + ); |
|
| 1985 | + if ($previous_status) { |
|
| 1986 | + $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY); |
|
| 1987 | + $this->set_status($previous_status); |
|
| 1988 | + } |
|
| 1989 | + return parent::restore(); |
|
| 1990 | + } |
|
| 1991 | + |
|
| 1992 | + |
|
| 1993 | + /** |
|
| 1994 | + * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price |
|
| 1995 | + * |
|
| 1996 | + * @param boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic |
|
| 1997 | + * depending on whether the reg status changes to or from "Approved" |
|
| 1998 | + * @return boolean whether the Registration status was updated |
|
| 1999 | + * @throws EE_Error |
|
| 2000 | + * @throws RuntimeException |
|
| 2001 | + */ |
|
| 2002 | + public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true) |
|
| 2003 | + { |
|
| 2004 | + $paid = $this->paid(); |
|
| 2005 | + $price = $this->final_price(); |
|
| 2006 | + switch (true) { |
|
| 2007 | + // overpaid or paid |
|
| 2008 | + case EEH_Money::compare_floats($paid, $price, '>'): |
|
| 2009 | + case EEH_Money::compare_floats($paid, $price): |
|
| 2010 | + $new_status = EEM_Registration::status_id_approved; |
|
| 2011 | + break; |
|
| 2012 | + // underpaid |
|
| 2013 | + case EEH_Money::compare_floats($paid, $price, '<'): |
|
| 2014 | + $new_status = EEM_Registration::status_id_pending_payment; |
|
| 2015 | + break; |
|
| 2016 | + // uhhh Houston... |
|
| 2017 | + default: |
|
| 2018 | + throw new RuntimeException( |
|
| 2019 | + esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso') |
|
| 2020 | + ); |
|
| 2021 | + } |
|
| 2022 | + if ($new_status !== $this->status_ID()) { |
|
| 2023 | + if ($trigger_set_status_logic) { |
|
| 2024 | + return $this->set_status($new_status); |
|
| 2025 | + } |
|
| 2026 | + parent::set('STS_ID', $new_status); |
|
| 2027 | + return true; |
|
| 2028 | + } |
|
| 2029 | + return false; |
|
| 2030 | + } |
|
| 2031 | + |
|
| 2032 | + |
|
| 2033 | + /*************************** DEPRECATED ***************************/ |
|
| 2034 | + |
|
| 2035 | + |
|
| 2036 | + /** |
|
| 2037 | + * @deprecated |
|
| 2038 | + * @since 4.7.0 |
|
| 2039 | + * @access public |
|
| 2040 | + */ |
|
| 2041 | + public function price_paid() |
|
| 2042 | + { |
|
| 2043 | + EE_Error::doing_it_wrong( |
|
| 2044 | + 'EE_Registration::price_paid()', |
|
| 2045 | + esc_html__( |
|
| 2046 | + 'This method is deprecated, please use EE_Registration::final_price() instead.', |
|
| 2047 | + 'event_espresso' |
|
| 2048 | + ), |
|
| 2049 | + '4.7.0' |
|
| 2050 | + ); |
|
| 2051 | + return $this->final_price(); |
|
| 2052 | + } |
|
| 2053 | + |
|
| 2054 | + |
|
| 2055 | + /** |
|
| 2056 | + * @deprecated |
|
| 2057 | + * @since 4.7.0 |
|
| 2058 | + * @access public |
|
| 2059 | + * @param float $REG_final_price |
|
| 2060 | + * @throws EE_Error |
|
| 2061 | + * @throws RuntimeException |
|
| 2062 | + */ |
|
| 2063 | + public function set_price_paid($REG_final_price = 0.00) |
|
| 2064 | + { |
|
| 2065 | + EE_Error::doing_it_wrong( |
|
| 2066 | + 'EE_Registration::set_price_paid()', |
|
| 2067 | + esc_html__( |
|
| 2068 | + 'This method is deprecated, please use EE_Registration::set_final_price() instead.', |
|
| 2069 | + 'event_espresso' |
|
| 2070 | + ), |
|
| 2071 | + '4.7.0' |
|
| 2072 | + ); |
|
| 2073 | + $this->set_final_price($REG_final_price); |
|
| 2074 | + } |
|
| 2075 | + |
|
| 2076 | + |
|
| 2077 | + /** |
|
| 2078 | + * @deprecated |
|
| 2079 | + * @since 4.7.0 |
|
| 2080 | + * @return string |
|
| 2081 | + * @throws EE_Error |
|
| 2082 | + */ |
|
| 2083 | + public function pretty_price_paid() |
|
| 2084 | + { |
|
| 2085 | + EE_Error::doing_it_wrong( |
|
| 2086 | + 'EE_Registration::pretty_price_paid()', |
|
| 2087 | + esc_html__( |
|
| 2088 | + 'This method is deprecated, please use EE_Registration::pretty_final_price() instead.', |
|
| 2089 | + 'event_espresso' |
|
| 2090 | + ), |
|
| 2091 | + '4.7.0' |
|
| 2092 | + ); |
|
| 2093 | + return $this->pretty_final_price(); |
|
| 2094 | + } |
|
| 2095 | + |
|
| 2096 | + |
|
| 2097 | + /** |
|
| 2098 | + * Gets the primary datetime related to this registration via the related Event to this registration |
|
| 2099 | + * |
|
| 2100 | + * @deprecated 4.9.17 |
|
| 2101 | + * @return EE_Datetime |
|
| 2102 | + * @throws EE_Error |
|
| 2103 | + * @throws EntityNotFoundException |
|
| 2104 | + */ |
|
| 2105 | + public function get_related_primary_datetime() |
|
| 2106 | + { |
|
| 2107 | + EE_Error::doing_it_wrong( |
|
| 2108 | + __METHOD__, |
|
| 2109 | + esc_html__( |
|
| 2110 | + 'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()', |
|
| 2111 | + 'event_espresso' |
|
| 2112 | + ), |
|
| 2113 | + '4.9.17', |
|
| 2114 | + '5.0.0' |
|
| 2115 | + ); |
|
| 2116 | + return $this->event()->primary_datetime(); |
|
| 2117 | + } |
|
| 2118 | + |
|
| 2119 | + /** |
|
| 2120 | + * Returns the contact's name (or "Unknown" if there is no contact.) |
|
| 2121 | + * @since $VID:$ |
|
| 2122 | + * @return string |
|
| 2123 | + * @throws EE_Error |
|
| 2124 | + * @throws InvalidArgumentException |
|
| 2125 | + * @throws InvalidDataTypeException |
|
| 2126 | + * @throws InvalidInterfaceException |
|
| 2127 | + * @throws ReflectionException |
|
| 2128 | + */ |
|
| 2129 | + public function name() |
|
| 2130 | + { |
|
| 2131 | + return $this->attendeeName(); |
|
| 2132 | + } |
|
| 2133 | 2133 | } |
@@ -14,2006 +14,2006 @@ |
||
| 14 | 14 | class EE_Ticket extends EE_Soft_Delete_Base_Class implements EEI_Line_Item_Object, EEI_Event_Relation, EEI_Has_Icon |
| 15 | 15 | { |
| 16 | 16 | |
| 17 | - /** |
|
| 18 | - * TicKet Sold out: |
|
| 19 | - * constant used by ticket_status() to indicate that a ticket is sold out |
|
| 20 | - * and no longer available for purchases |
|
| 21 | - */ |
|
| 22 | - const sold_out = 'TKS'; |
|
| 23 | - |
|
| 24 | - /** |
|
| 25 | - * TicKet Expired: |
|
| 26 | - * constant used by ticket_status() to indicate that a ticket is expired |
|
| 27 | - * and no longer available for purchase |
|
| 28 | - */ |
|
| 29 | - const expired = 'TKE'; |
|
| 30 | - |
|
| 31 | - /** |
|
| 32 | - * TicKet Archived: |
|
| 33 | - * constant used by ticket_status() to indicate that a ticket is archived |
|
| 34 | - * and no longer available for purchase |
|
| 35 | - */ |
|
| 36 | - const archived = 'TKA'; |
|
| 37 | - |
|
| 38 | - /** |
|
| 39 | - * TicKet Pending: |
|
| 40 | - * constant used by ticket_status() to indicate that a ticket is pending |
|
| 41 | - * and is NOT YET available for purchase |
|
| 42 | - */ |
|
| 43 | - const pending = 'TKP'; |
|
| 44 | - |
|
| 45 | - /** |
|
| 46 | - * TicKet On sale: |
|
| 47 | - * constant used by ticket_status() to indicate that a ticket is On Sale |
|
| 48 | - * and IS available for purchase |
|
| 49 | - */ |
|
| 50 | - const onsale = 'TKO'; |
|
| 51 | - |
|
| 52 | - /** |
|
| 53 | - * extra meta key for tracking ticket reservations |
|
| 54 | - * |
|
| 55 | - * @type string |
|
| 56 | - */ |
|
| 57 | - const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations'; |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * override of parent property |
|
| 61 | - * |
|
| 62 | - * @var EEM_Ticket |
|
| 63 | - */ |
|
| 64 | - protected $_model; |
|
| 65 | - |
|
| 66 | - /** |
|
| 67 | - * cached result from method of the same name |
|
| 68 | - * |
|
| 69 | - * @var float $_ticket_total_with_taxes |
|
| 70 | - */ |
|
| 71 | - private $_ticket_total_with_taxes; |
|
| 72 | - |
|
| 73 | - |
|
| 74 | - /** |
|
| 75 | - * @param array $props_n_values incoming values |
|
| 76 | - * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 77 | - * used.) |
|
| 78 | - * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 79 | - * date_format and the second value is the time format |
|
| 80 | - * @return EE_Ticket |
|
| 81 | - * @throws EE_Error |
|
| 82 | - * @throws ReflectionException |
|
| 83 | - */ |
|
| 84 | - public static function new_instance($props_n_values = [], $timezone = '', $date_formats = []) |
|
| 85 | - { |
|
| 86 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 87 | - return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
| 88 | - } |
|
| 89 | - |
|
| 90 | - |
|
| 91 | - /** |
|
| 92 | - * @param array $props_n_values incoming values from the database |
|
| 93 | - * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 94 | - * the website will be used. |
|
| 95 | - * @return EE_Ticket |
|
| 96 | - * @throws EE_Error |
|
| 97 | - * @throws ReflectionException |
|
| 98 | - */ |
|
| 99 | - public static function new_instance_from_db($props_n_values = [], $timezone = '') |
|
| 100 | - { |
|
| 101 | - return new self($props_n_values, true, $timezone); |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - |
|
| 105 | - /** |
|
| 106 | - * @return bool |
|
| 107 | - * @throws EE_Error |
|
| 108 | - * @throws ReflectionException |
|
| 109 | - */ |
|
| 110 | - public function parent() |
|
| 111 | - { |
|
| 112 | - return $this->get('TKT_parent'); |
|
| 113 | - } |
|
| 114 | - |
|
| 115 | - |
|
| 116 | - /** |
|
| 117 | - * return if a ticket has quantities available for purchase |
|
| 118 | - * |
|
| 119 | - * @param int $DTT_ID the primary key for a particular datetime |
|
| 120 | - * @return boolean |
|
| 121 | - * @throws EE_Error |
|
| 122 | - * @throws ReflectionException |
|
| 123 | - */ |
|
| 124 | - public function available($DTT_ID = 0) |
|
| 125 | - { |
|
| 126 | - // are we checking availability for a particular datetime ? |
|
| 127 | - if ($DTT_ID) { |
|
| 128 | - // get that datetime object |
|
| 129 | - $datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]); |
|
| 130 | - // if ticket sales for this datetime have exceeded the reg limit... |
|
| 131 | - if ($datetime instanceof EE_Datetime && $datetime->sold_out()) { |
|
| 132 | - return false; |
|
| 133 | - } |
|
| 134 | - } |
|
| 135 | - // datetime is still open for registration, but is this ticket sold out ? |
|
| 136 | - return $this->qty() < 1 || $this->qty() > $this->sold(); |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - |
|
| 140 | - /** |
|
| 141 | - * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired |
|
| 142 | - * |
|
| 143 | - * @param bool $display true = we'll return a localized string, otherwise we just return the value of the |
|
| 144 | - * relevant status const |
|
| 145 | - * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save |
|
| 146 | - * further processing |
|
| 147 | - * @return mixed status int if the display string isn't requested |
|
| 148 | - * @throws EE_Error |
|
| 149 | - * @throws ReflectionException |
|
| 150 | - */ |
|
| 151 | - public function ticket_status($display = false, $remaining = null) |
|
| 152 | - { |
|
| 153 | - $remaining = is_bool($remaining) ? $remaining : $this->is_remaining(); |
|
| 154 | - if (! $remaining) { |
|
| 155 | - return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out; |
|
| 156 | - } |
|
| 157 | - if ($this->get('TKT_deleted')) { |
|
| 158 | - return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived; |
|
| 159 | - } |
|
| 160 | - if ($this->is_expired()) { |
|
| 161 | - return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired; |
|
| 162 | - } |
|
| 163 | - if ($this->is_pending()) { |
|
| 164 | - return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending; |
|
| 165 | - } |
|
| 166 | - if ($this->is_on_sale()) { |
|
| 167 | - return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale; |
|
| 168 | - } |
|
| 169 | - return ''; |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - |
|
| 173 | - /** |
|
| 174 | - * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale |
|
| 175 | - * considering ALL the factors used for figuring that out. |
|
| 176 | - * |
|
| 177 | - * @access public |
|
| 178 | - * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt. |
|
| 179 | - * @return boolean true = tickets remaining, false not. |
|
| 180 | - * @throws EE_Error |
|
| 181 | - * @throws ReflectionException |
|
| 182 | - */ |
|
| 183 | - public function is_remaining($DTT_ID = 0) |
|
| 184 | - { |
|
| 185 | - $num_remaining = $this->remaining($DTT_ID); |
|
| 186 | - if ($num_remaining === 0) { |
|
| 187 | - return false; |
|
| 188 | - } |
|
| 189 | - if ($num_remaining > 0 && $num_remaining < $this->min()) { |
|
| 190 | - return false; |
|
| 191 | - } |
|
| 192 | - return true; |
|
| 193 | - } |
|
| 194 | - |
|
| 195 | - |
|
| 196 | - /** |
|
| 197 | - * return the total number of tickets available for purchase |
|
| 198 | - * |
|
| 199 | - * @param int $DTT_ID the primary key for a particular datetime. |
|
| 200 | - * set to 0 for all related datetimes |
|
| 201 | - * @return int |
|
| 202 | - * @throws EE_Error |
|
| 203 | - * @throws ReflectionException |
|
| 204 | - */ |
|
| 205 | - public function remaining($DTT_ID = 0) |
|
| 206 | - { |
|
| 207 | - return $this->real_quantity_on_ticket('saleable', $DTT_ID); |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - |
|
| 211 | - /** |
|
| 212 | - * Gets min |
|
| 213 | - * |
|
| 214 | - * @return int |
|
| 215 | - * @throws EE_Error |
|
| 216 | - * @throws ReflectionException |
|
| 217 | - */ |
|
| 218 | - public function min() |
|
| 219 | - { |
|
| 220 | - return $this->get('TKT_min'); |
|
| 221 | - } |
|
| 222 | - |
|
| 223 | - |
|
| 224 | - /** |
|
| 225 | - * return if a ticket is no longer available cause its available dates have expired. |
|
| 226 | - * |
|
| 227 | - * @return boolean |
|
| 228 | - * @throws EE_Error |
|
| 229 | - * @throws ReflectionException |
|
| 230 | - */ |
|
| 231 | - public function is_expired() |
|
| 232 | - { |
|
| 233 | - return ($this->get_raw('TKT_end_date') < time()); |
|
| 234 | - } |
|
| 235 | - |
|
| 236 | - |
|
| 237 | - /** |
|
| 238 | - * Return if a ticket is yet to go on sale or not |
|
| 239 | - * |
|
| 240 | - * @return boolean |
|
| 241 | - * @throws EE_Error |
|
| 242 | - * @throws ReflectionException |
|
| 243 | - */ |
|
| 244 | - public function is_pending() |
|
| 245 | - { |
|
| 246 | - return ($this->get_raw('TKT_start_date') >= time()); |
|
| 247 | - } |
|
| 248 | - |
|
| 249 | - |
|
| 250 | - /** |
|
| 251 | - * Return if a ticket is on sale or not |
|
| 252 | - * |
|
| 253 | - * @return boolean |
|
| 254 | - * @throws EE_Error |
|
| 255 | - * @throws ReflectionException |
|
| 256 | - */ |
|
| 257 | - public function is_on_sale() |
|
| 258 | - { |
|
| 259 | - return ($this->get_raw('TKT_start_date') <= time() && $this->get_raw('TKT_end_date') >= time()); |
|
| 260 | - } |
|
| 261 | - |
|
| 262 | - |
|
| 263 | - /** |
|
| 264 | - * This returns the chronologically last datetime that this ticket is associated with |
|
| 265 | - * |
|
| 266 | - * @param string $date_format |
|
| 267 | - * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with |
|
| 268 | - * the end date ie: Jan 01 "to" Dec 31 |
|
| 269 | - * @return string |
|
| 270 | - * @throws EE_Error |
|
| 271 | - * @throws ReflectionException |
|
| 272 | - */ |
|
| 273 | - public function date_range($date_format = '', $conjunction = ' - ') |
|
| 274 | - { |
|
| 275 | - $date_format = ! empty($date_format) ? $date_format : $this->_dt_frmt; |
|
| 276 | - $first_date = $this->first_datetime() instanceof EE_Datetime |
|
| 277 | - ? $this->first_datetime()->get_i18n_datetime('DTT_EVT_start', $date_format) |
|
| 278 | - : ''; |
|
| 279 | - $last_date = $this->last_datetime() instanceof EE_Datetime |
|
| 280 | - ? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format) |
|
| 281 | - : ''; |
|
| 282 | - |
|
| 283 | - return $first_date && $last_date ? $first_date . $conjunction . $last_date : ''; |
|
| 284 | - } |
|
| 285 | - |
|
| 286 | - |
|
| 287 | - /** |
|
| 288 | - * This returns the chronologically first datetime that this ticket is associated with |
|
| 289 | - * |
|
| 290 | - * @return EE_Datetime |
|
| 291 | - * @throws EE_Error |
|
| 292 | - * @throws ReflectionException |
|
| 293 | - */ |
|
| 294 | - public function first_datetime() |
|
| 295 | - { |
|
| 296 | - $datetimes = $this->datetimes(['limit' => 1]); |
|
| 297 | - return reset($datetimes); |
|
| 298 | - } |
|
| 299 | - |
|
| 300 | - |
|
| 301 | - /** |
|
| 302 | - * Gets all the datetimes this ticket can be used for attending. |
|
| 303 | - * Unless otherwise specified, orders datetimes by start date. |
|
| 304 | - * |
|
| 305 | - * @param array $query_params @see |
|
| 306 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 307 | - * @return EE_Datetime[]|EE_Base_Class[] |
|
| 308 | - * @throws EE_Error |
|
| 309 | - * @throws ReflectionException |
|
| 310 | - */ |
|
| 311 | - public function datetimes($query_params = []) |
|
| 312 | - { |
|
| 313 | - if (! isset($query_params['order_by'])) { |
|
| 314 | - $query_params['order_by']['DTT_order'] = 'ASC'; |
|
| 315 | - } |
|
| 316 | - return $this->get_many_related('Datetime', $query_params); |
|
| 317 | - } |
|
| 318 | - |
|
| 319 | - |
|
| 320 | - /** |
|
| 321 | - * This returns the chronologically last datetime that this ticket is associated with |
|
| 322 | - * |
|
| 323 | - * @return EE_Datetime |
|
| 324 | - * @throws EE_Error |
|
| 325 | - * @throws ReflectionException |
|
| 326 | - */ |
|
| 327 | - public function last_datetime() |
|
| 328 | - { |
|
| 329 | - $datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]); |
|
| 330 | - return end($datetimes); |
|
| 331 | - } |
|
| 332 | - |
|
| 333 | - |
|
| 334 | - /** |
|
| 335 | - * This returns the total tickets sold depending on the given parameters. |
|
| 336 | - * |
|
| 337 | - * @param string $what Can be one of two options: 'ticket', 'datetime'. |
|
| 338 | - * 'ticket' = total ticket sales for all datetimes this ticket is related to |
|
| 339 | - * 'datetime' = total ticket sales for a specified datetime (required $dtt_id) |
|
| 340 | - * 'datetime' = total ticket sales in the datetime_ticket table. |
|
| 341 | - * If $dtt_id is not given then we return an array of sales indexed by datetime. |
|
| 342 | - * If $dtt_id IS given then we return the tickets sold for that given datetime. |
|
| 343 | - * @param int $dtt_id [optional] include the dtt_id with $what = 'datetime'. |
|
| 344 | - * @return mixed (array|int) how many tickets have sold |
|
| 345 | - * @throws EE_Error |
|
| 346 | - * @throws ReflectionException |
|
| 347 | - */ |
|
| 348 | - public function tickets_sold($what = 'ticket', $dtt_id = null) |
|
| 349 | - { |
|
| 350 | - $total = 0; |
|
| 351 | - $tickets_sold = $this->_all_tickets_sold(); |
|
| 352 | - switch ($what) { |
|
| 353 | - case 'ticket': |
|
| 354 | - return $tickets_sold['ticket']; |
|
| 355 | - break; |
|
| 356 | - case 'datetime': |
|
| 357 | - if (empty($tickets_sold['datetime'])) { |
|
| 358 | - return $total; |
|
| 359 | - } |
|
| 360 | - if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) { |
|
| 361 | - EE_Error::add_error( |
|
| 362 | - __( |
|
| 363 | - 'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included. Are you SURE that is a datetime related to this ticket?', |
|
| 364 | - 'event_espresso' |
|
| 365 | - ), |
|
| 366 | - __FILE__, |
|
| 367 | - __FUNCTION__, |
|
| 368 | - __LINE__ |
|
| 369 | - ); |
|
| 370 | - return $total; |
|
| 371 | - } |
|
| 372 | - return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ]; |
|
| 373 | - break; |
|
| 374 | - default: |
|
| 375 | - return $total; |
|
| 376 | - } |
|
| 377 | - } |
|
| 378 | - |
|
| 379 | - |
|
| 380 | - /** |
|
| 381 | - * This returns an array indexed by datetime_id for tickets sold with this ticket. |
|
| 382 | - * |
|
| 383 | - * @return EE_Ticket[] |
|
| 384 | - * @throws EE_Error |
|
| 385 | - * @throws ReflectionException |
|
| 386 | - */ |
|
| 387 | - protected function _all_tickets_sold() |
|
| 388 | - { |
|
| 389 | - $datetimes = $this->get_many_related('Datetime'); |
|
| 390 | - $tickets_sold = []; |
|
| 391 | - if (! empty($datetimes)) { |
|
| 392 | - foreach ($datetimes as $datetime) { |
|
| 393 | - $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold'); |
|
| 394 | - } |
|
| 395 | - } |
|
| 396 | - // Tickets sold |
|
| 397 | - $tickets_sold['ticket'] = $this->sold(); |
|
| 398 | - return $tickets_sold; |
|
| 399 | - } |
|
| 400 | - |
|
| 401 | - |
|
| 402 | - /** |
|
| 403 | - * This returns the base price object for the ticket. |
|
| 404 | - * |
|
| 405 | - * @param bool $return_array whether to return as an array indexed by price id or just the object. |
|
| 406 | - * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[] |
|
| 407 | - * @throws EE_Error |
|
| 408 | - * @throws ReflectionException |
|
| 409 | - */ |
|
| 410 | - public function base_price($return_array = false) |
|
| 411 | - { |
|
| 412 | - $_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price]; |
|
| 413 | - return $return_array |
|
| 414 | - ? $this->get_many_related('Price', [$_where]) |
|
| 415 | - : $this->get_first_related('Price', [$_where]); |
|
| 416 | - } |
|
| 417 | - |
|
| 418 | - |
|
| 419 | - /** |
|
| 420 | - * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price) |
|
| 421 | - * |
|
| 422 | - * @access public |
|
| 423 | - * @return EE_Price[] |
|
| 424 | - * @throws EE_Error |
|
| 425 | - * @throws ReflectionException |
|
| 426 | - */ |
|
| 427 | - public function price_modifiers() |
|
| 428 | - { |
|
| 429 | - $query_params = [ |
|
| 430 | - 0 => [ |
|
| 431 | - 'Price_Type.PBT_ID' => [ |
|
| 432 | - 'NOT IN', |
|
| 433 | - [EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax], |
|
| 434 | - ], |
|
| 435 | - ], |
|
| 436 | - ]; |
|
| 437 | - return $this->prices($query_params); |
|
| 438 | - } |
|
| 439 | - |
|
| 440 | - |
|
| 441 | - /** |
|
| 442 | - * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price) |
|
| 443 | - * |
|
| 444 | - * @access public |
|
| 445 | - * @return EE_Price[] |
|
| 446 | - * @throws EE_Error |
|
| 447 | - * @throws ReflectionException |
|
| 448 | - */ |
|
| 449 | - public function tax_price_modifiers() |
|
| 450 | - { |
|
| 451 | - $query_params = [ |
|
| 452 | - 0 => [ |
|
| 453 | - 'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax, |
|
| 454 | - ], |
|
| 455 | - ]; |
|
| 456 | - return $this->prices($query_params); |
|
| 457 | - } |
|
| 458 | - |
|
| 459 | - |
|
| 460 | - /** |
|
| 461 | - * Gets all the prices that combine to form the final price of this ticket |
|
| 462 | - * |
|
| 463 | - * @param array $query_params @see |
|
| 464 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 465 | - * @return EE_Price[]|EE_Base_Class[] |
|
| 466 | - * @throws EE_Error |
|
| 467 | - * @throws ReflectionException |
|
| 468 | - */ |
|
| 469 | - public function prices($query_params = []) |
|
| 470 | - { |
|
| 471 | - return $this->get_many_related('Price', $query_params); |
|
| 472 | - } |
|
| 473 | - |
|
| 474 | - |
|
| 475 | - /** |
|
| 476 | - * Gets all the ticket datetimes (ie, relations between datetimes and tickets) |
|
| 477 | - * |
|
| 478 | - * @param array $query_params @see |
|
| 479 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 480 | - * @return EE_Datetime_Ticket|EE_Base_Class[] |
|
| 481 | - * @throws EE_Error |
|
| 482 | - * @throws ReflectionException |
|
| 483 | - */ |
|
| 484 | - public function datetime_tickets($query_params = []) |
|
| 485 | - { |
|
| 486 | - return $this->get_many_related('Datetime_Ticket', $query_params); |
|
| 487 | - } |
|
| 488 | - |
|
| 489 | - |
|
| 490 | - /** |
|
| 491 | - * Gets all the datetimes from the db ordered by DTT_order |
|
| 492 | - * |
|
| 493 | - * @param boolean $show_expired |
|
| 494 | - * @param boolean $show_deleted |
|
| 495 | - * @return EE_Datetime[] |
|
| 496 | - * @throws EE_Error |
|
| 497 | - * @throws ReflectionException |
|
| 498 | - */ |
|
| 499 | - public function datetimes_ordered($show_expired = true, $show_deleted = false) |
|
| 500 | - { |
|
| 501 | - return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order( |
|
| 502 | - $this->ID(), |
|
| 503 | - $show_expired, |
|
| 504 | - $show_deleted |
|
| 505 | - ); |
|
| 506 | - } |
|
| 507 | - |
|
| 508 | - |
|
| 509 | - /** |
|
| 510 | - * Gets ID |
|
| 511 | - * |
|
| 512 | - * @return string |
|
| 513 | - * @throws EE_Error |
|
| 514 | - * @throws ReflectionException |
|
| 515 | - */ |
|
| 516 | - public function ID() |
|
| 517 | - { |
|
| 518 | - return $this->get('TKT_ID'); |
|
| 519 | - } |
|
| 520 | - |
|
| 521 | - |
|
| 522 | - /** |
|
| 523 | - * get the author of the ticket. |
|
| 524 | - * |
|
| 525 | - * @return int |
|
| 526 | - * @throws EE_Error |
|
| 527 | - * @throws ReflectionException |
|
| 528 | - * @since 4.5.0 |
|
| 529 | - */ |
|
| 530 | - public function wp_user() |
|
| 531 | - { |
|
| 532 | - return $this->get('TKT_wp_user'); |
|
| 533 | - } |
|
| 534 | - |
|
| 535 | - |
|
| 536 | - /** |
|
| 537 | - * Gets the template for the ticket |
|
| 538 | - * |
|
| 539 | - * @return EE_Ticket_Template|EE_Base_Class |
|
| 540 | - * @throws EE_Error |
|
| 541 | - * @throws ReflectionException |
|
| 542 | - */ |
|
| 543 | - public function template() |
|
| 544 | - { |
|
| 545 | - return $this->get_first_related('Ticket_Template'); |
|
| 546 | - } |
|
| 547 | - |
|
| 548 | - |
|
| 549 | - /** |
|
| 550 | - * Simply returns an array of EE_Price objects that are taxes. |
|
| 551 | - * |
|
| 552 | - * @return EE_Price[] |
|
| 553 | - * @throws EE_Error |
|
| 554 | - */ |
|
| 555 | - public function get_ticket_taxes_for_admin() |
|
| 556 | - { |
|
| 557 | - return EE_Taxes::get_taxes_for_admin(); |
|
| 558 | - } |
|
| 559 | - |
|
| 560 | - |
|
| 561 | - /** |
|
| 562 | - * @return float |
|
| 563 | - * @throws EE_Error |
|
| 564 | - * @throws ReflectionException |
|
| 565 | - */ |
|
| 566 | - public function ticket_price() |
|
| 567 | - { |
|
| 568 | - return $this->get('TKT_price'); |
|
| 569 | - } |
|
| 570 | - |
|
| 571 | - |
|
| 572 | - /** |
|
| 573 | - * @return mixed |
|
| 574 | - * @throws EE_Error |
|
| 575 | - * @throws ReflectionException |
|
| 576 | - */ |
|
| 577 | - public function pretty_price() |
|
| 578 | - { |
|
| 579 | - return $this->get_pretty('TKT_price'); |
|
| 580 | - } |
|
| 581 | - |
|
| 582 | - |
|
| 583 | - /** |
|
| 584 | - * @return bool |
|
| 585 | - * @throws EE_Error |
|
| 586 | - * @throws ReflectionException |
|
| 587 | - */ |
|
| 588 | - public function is_free() |
|
| 589 | - { |
|
| 590 | - return $this->get_ticket_total_with_taxes() === (float) 0; |
|
| 591 | - } |
|
| 592 | - |
|
| 593 | - |
|
| 594 | - /** |
|
| 595 | - * get_ticket_total_with_taxes |
|
| 596 | - * |
|
| 597 | - * @param bool $no_cache |
|
| 598 | - * @return float |
|
| 599 | - * @throws EE_Error |
|
| 600 | - * @throws ReflectionException |
|
| 601 | - */ |
|
| 602 | - public function get_ticket_total_with_taxes($no_cache = false) |
|
| 603 | - { |
|
| 604 | - if ($this->_ticket_total_with_taxes === null || $no_cache) { |
|
| 605 | - $this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin(); |
|
| 606 | - } |
|
| 607 | - return (float) $this->_ticket_total_with_taxes; |
|
| 608 | - } |
|
| 609 | - |
|
| 610 | - |
|
| 611 | - /** |
|
| 612 | - * @throws EE_Error |
|
| 613 | - * @throws ReflectionException |
|
| 614 | - */ |
|
| 615 | - public function ensure_TKT_Price_correct() |
|
| 616 | - { |
|
| 617 | - $this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this)); |
|
| 618 | - $this->save(); |
|
| 619 | - } |
|
| 620 | - |
|
| 621 | - |
|
| 622 | - /** |
|
| 623 | - * @return float |
|
| 624 | - * @throws EE_Error |
|
| 625 | - * @throws ReflectionException |
|
| 626 | - */ |
|
| 627 | - public function get_ticket_subtotal() |
|
| 628 | - { |
|
| 629 | - return EE_Taxes::get_subtotal_for_admin($this); |
|
| 630 | - } |
|
| 631 | - |
|
| 632 | - |
|
| 633 | - /** |
|
| 634 | - * Returns the total taxes applied to this ticket |
|
| 635 | - * |
|
| 636 | - * @return float |
|
| 637 | - * @throws EE_Error |
|
| 638 | - * @throws ReflectionException |
|
| 639 | - */ |
|
| 640 | - public function get_ticket_taxes_total_for_admin() |
|
| 641 | - { |
|
| 642 | - return EE_Taxes::get_total_taxes_for_admin($this); |
|
| 643 | - } |
|
| 644 | - |
|
| 645 | - |
|
| 646 | - /** |
|
| 647 | - * Sets name |
|
| 648 | - * |
|
| 649 | - * @param string $name |
|
| 650 | - * @throws EE_Error |
|
| 651 | - * @throws ReflectionException |
|
| 652 | - */ |
|
| 653 | - public function set_name($name) |
|
| 654 | - { |
|
| 655 | - $this->set('TKT_name', $name); |
|
| 656 | - } |
|
| 657 | - |
|
| 658 | - |
|
| 659 | - /** |
|
| 660 | - * Gets description |
|
| 661 | - * |
|
| 662 | - * @return string |
|
| 663 | - * @throws EE_Error |
|
| 664 | - * @throws ReflectionException |
|
| 665 | - */ |
|
| 666 | - public function description() |
|
| 667 | - { |
|
| 668 | - return $this->get('TKT_description'); |
|
| 669 | - } |
|
| 670 | - |
|
| 671 | - |
|
| 672 | - /** |
|
| 673 | - * Sets description |
|
| 674 | - * |
|
| 675 | - * @param string $description |
|
| 676 | - * @throws EE_Error |
|
| 677 | - * @throws ReflectionException |
|
| 678 | - */ |
|
| 679 | - public function set_description($description) |
|
| 680 | - { |
|
| 681 | - $this->set('TKT_description', $description); |
|
| 682 | - } |
|
| 683 | - |
|
| 684 | - |
|
| 685 | - /** |
|
| 686 | - * Gets start_date |
|
| 687 | - * |
|
| 688 | - * @param string $date_format |
|
| 689 | - * @param string $time_format |
|
| 690 | - * @return string |
|
| 691 | - * @throws EE_Error |
|
| 692 | - * @throws ReflectionException |
|
| 693 | - */ |
|
| 694 | - public function start_date($date_format = '', $time_format = '') |
|
| 695 | - { |
|
| 696 | - return $this->_get_datetime('TKT_start_date', $date_format, $time_format); |
|
| 697 | - } |
|
| 698 | - |
|
| 699 | - |
|
| 700 | - /** |
|
| 701 | - * Sets start_date |
|
| 702 | - * |
|
| 703 | - * @param string $start_date |
|
| 704 | - * @return void |
|
| 705 | - * @throws EE_Error |
|
| 706 | - * @throws ReflectionException |
|
| 707 | - */ |
|
| 708 | - public function set_start_date($start_date) |
|
| 709 | - { |
|
| 710 | - $this->_set_date_time('B', $start_date, 'TKT_start_date'); |
|
| 711 | - } |
|
| 712 | - |
|
| 713 | - |
|
| 714 | - /** |
|
| 715 | - * Gets end_date |
|
| 716 | - * |
|
| 717 | - * @param string $date_format |
|
| 718 | - * @param string $time_format |
|
| 719 | - * @return string |
|
| 720 | - * @throws EE_Error |
|
| 721 | - * @throws ReflectionException |
|
| 722 | - */ |
|
| 723 | - public function end_date($date_format = '', $time_format = '') |
|
| 724 | - { |
|
| 725 | - return $this->_get_datetime('TKT_end_date', $date_format, $time_format); |
|
| 726 | - } |
|
| 727 | - |
|
| 728 | - |
|
| 729 | - /** |
|
| 730 | - * Sets end_date |
|
| 731 | - * |
|
| 732 | - * @param string $end_date |
|
| 733 | - * @return void |
|
| 734 | - * @throws EE_Error |
|
| 735 | - * @throws ReflectionException |
|
| 736 | - */ |
|
| 737 | - public function set_end_date($end_date) |
|
| 738 | - { |
|
| 739 | - $this->_set_date_time('B', $end_date, 'TKT_end_date'); |
|
| 740 | - } |
|
| 741 | - |
|
| 742 | - |
|
| 743 | - /** |
|
| 744 | - * Sets sell until time |
|
| 745 | - * |
|
| 746 | - * @param string $time a string representation of the sell until time (ex 9am or 7:30pm) |
|
| 747 | - * @throws EE_Error |
|
| 748 | - * @throws ReflectionException |
|
| 749 | - * @since 4.5.0 |
|
| 750 | - */ |
|
| 751 | - public function set_end_time($time) |
|
| 752 | - { |
|
| 753 | - $this->_set_time_for($time, 'TKT_end_date'); |
|
| 754 | - } |
|
| 755 | - |
|
| 756 | - |
|
| 757 | - /** |
|
| 758 | - * Sets min |
|
| 759 | - * |
|
| 760 | - * @param int $min |
|
| 761 | - * @return void |
|
| 762 | - * @throws EE_Error |
|
| 763 | - * @throws ReflectionException |
|
| 764 | - */ |
|
| 765 | - public function set_min($min) |
|
| 766 | - { |
|
| 767 | - $this->set('TKT_min', $min); |
|
| 768 | - } |
|
| 769 | - |
|
| 770 | - |
|
| 771 | - /** |
|
| 772 | - * Gets max |
|
| 773 | - * |
|
| 774 | - * @return int |
|
| 775 | - * @throws EE_Error |
|
| 776 | - * @throws ReflectionException |
|
| 777 | - */ |
|
| 778 | - public function max() |
|
| 779 | - { |
|
| 780 | - return $this->get('TKT_max'); |
|
| 781 | - } |
|
| 782 | - |
|
| 783 | - |
|
| 784 | - /** |
|
| 785 | - * Sets max |
|
| 786 | - * |
|
| 787 | - * @param int $max |
|
| 788 | - * @return void |
|
| 789 | - * @throws EE_Error |
|
| 790 | - * @throws ReflectionException |
|
| 791 | - */ |
|
| 792 | - public function set_max($max) |
|
| 793 | - { |
|
| 794 | - $this->set('TKT_max', $max); |
|
| 795 | - } |
|
| 796 | - |
|
| 797 | - |
|
| 798 | - /** |
|
| 799 | - * Sets price |
|
| 800 | - * |
|
| 801 | - * @param float $price |
|
| 802 | - * @return void |
|
| 803 | - * @throws EE_Error |
|
| 804 | - * @throws ReflectionException |
|
| 805 | - */ |
|
| 806 | - public function set_price($price) |
|
| 807 | - { |
|
| 808 | - $this->set('TKT_price', $price); |
|
| 809 | - } |
|
| 810 | - |
|
| 811 | - |
|
| 812 | - /** |
|
| 813 | - * Gets sold |
|
| 814 | - * |
|
| 815 | - * @return int |
|
| 816 | - * @throws EE_Error |
|
| 817 | - * @throws ReflectionException |
|
| 818 | - */ |
|
| 819 | - public function sold() |
|
| 820 | - { |
|
| 821 | - return $this->get_raw('TKT_sold'); |
|
| 822 | - } |
|
| 823 | - |
|
| 824 | - |
|
| 825 | - /** |
|
| 826 | - * Sets sold |
|
| 827 | - * |
|
| 828 | - * @param int $sold |
|
| 829 | - * @return void |
|
| 830 | - * @throws EE_Error |
|
| 831 | - * @throws ReflectionException |
|
| 832 | - */ |
|
| 833 | - public function set_sold($sold) |
|
| 834 | - { |
|
| 835 | - // sold can not go below zero |
|
| 836 | - $sold = max(0, $sold); |
|
| 837 | - $this->set('TKT_sold', $sold); |
|
| 838 | - } |
|
| 839 | - |
|
| 840 | - |
|
| 841 | - /** |
|
| 842 | - * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its |
|
| 843 | - * associated datetimes. |
|
| 844 | - * |
|
| 845 | - * @param int $qty |
|
| 846 | - * @return boolean |
|
| 847 | - * @throws EE_Error |
|
| 848 | - * @throws InvalidArgumentException |
|
| 849 | - * @throws InvalidDataTypeException |
|
| 850 | - * @throws InvalidInterfaceException |
|
| 851 | - * @throws ReflectionException |
|
| 852 | - * @since 4.9.80.p |
|
| 853 | - */ |
|
| 854 | - public function increaseSold($qty = 1) |
|
| 855 | - { |
|
| 856 | - $qty = absint($qty); |
|
| 857 | - // increment sold and decrement reserved datetime quantities simultaneously |
|
| 858 | - // don't worry about failures, because they must have already had a spot reserved |
|
| 859 | - $this->increaseSoldForDatetimes($qty); |
|
| 860 | - // Increment and decrement ticket quantities simultaneously |
|
| 861 | - $success = $this->adjustNumericFieldsInDb( |
|
| 862 | - [ |
|
| 863 | - 'TKT_reserved' => $qty * -1, |
|
| 864 | - 'TKT_sold' => $qty, |
|
| 865 | - ] |
|
| 866 | - ); |
|
| 867 | - do_action( |
|
| 868 | - 'AHEE__EE_Ticket__increase_sold', |
|
| 869 | - $this, |
|
| 870 | - $qty, |
|
| 871 | - $this->sold(), |
|
| 872 | - $success |
|
| 873 | - ); |
|
| 874 | - return $success; |
|
| 875 | - } |
|
| 876 | - |
|
| 877 | - |
|
| 878 | - /** |
|
| 879 | - * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty. |
|
| 880 | - * |
|
| 881 | - * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved |
|
| 882 | - * counts), Negative means to decreases old counts (and increase reserved counts). |
|
| 883 | - * @param EE_Datetime[] $datetimes |
|
| 884 | - * @throws EE_Error |
|
| 885 | - * @throws InvalidArgumentException |
|
| 886 | - * @throws InvalidDataTypeException |
|
| 887 | - * @throws InvalidInterfaceException |
|
| 888 | - * @throws ReflectionException |
|
| 889 | - * @since 4.9.80.p |
|
| 890 | - */ |
|
| 891 | - protected function increaseSoldForDatetimes($qty, array $datetimes = []) |
|
| 892 | - { |
|
| 893 | - $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 894 | - foreach ($datetimes as $datetime) { |
|
| 895 | - $datetime->increaseSold($qty); |
|
| 896 | - } |
|
| 897 | - } |
|
| 898 | - |
|
| 899 | - |
|
| 900 | - /** |
|
| 901 | - * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the |
|
| 902 | - * DB and then updates the model objects. |
|
| 903 | - * Does not affect the reserved counts. |
|
| 904 | - * |
|
| 905 | - * @param int $qty |
|
| 906 | - * @return boolean |
|
| 907 | - * @throws EE_Error |
|
| 908 | - * @throws InvalidArgumentException |
|
| 909 | - * @throws InvalidDataTypeException |
|
| 910 | - * @throws InvalidInterfaceException |
|
| 911 | - * @throws ReflectionException |
|
| 912 | - * @since 4.9.80.p |
|
| 913 | - */ |
|
| 914 | - public function decreaseSold($qty = 1) |
|
| 915 | - { |
|
| 916 | - $qty = absint($qty); |
|
| 917 | - $this->decreaseSoldForDatetimes($qty); |
|
| 918 | - $success = $this->adjustNumericFieldsInDb( |
|
| 919 | - [ |
|
| 920 | - 'TKT_sold' => $qty * -1, |
|
| 921 | - ] |
|
| 922 | - ); |
|
| 923 | - do_action( |
|
| 924 | - 'AHEE__EE_Ticket__decrease_sold', |
|
| 925 | - $this, |
|
| 926 | - $qty, |
|
| 927 | - $this->sold(), |
|
| 928 | - $success |
|
| 929 | - ); |
|
| 930 | - return $success; |
|
| 931 | - } |
|
| 932 | - |
|
| 933 | - |
|
| 934 | - /** |
|
| 935 | - * Decreases sold on related datetimes |
|
| 936 | - * |
|
| 937 | - * @param int $qty |
|
| 938 | - * @param EE_Datetime[] $datetimes |
|
| 939 | - * @return void |
|
| 940 | - * @throws EE_Error |
|
| 941 | - * @throws InvalidArgumentException |
|
| 942 | - * @throws InvalidDataTypeException |
|
| 943 | - * @throws InvalidInterfaceException |
|
| 944 | - * @throws ReflectionException |
|
| 945 | - * @since 4.9.80.p |
|
| 946 | - */ |
|
| 947 | - protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = []) |
|
| 948 | - { |
|
| 949 | - $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 950 | - if (is_array($datetimes)) { |
|
| 951 | - foreach ($datetimes as $datetime) { |
|
| 952 | - if ($datetime instanceof EE_Datetime) { |
|
| 953 | - $datetime->decreaseSold($qty); |
|
| 954 | - } |
|
| 955 | - } |
|
| 956 | - } |
|
| 957 | - } |
|
| 958 | - |
|
| 959 | - |
|
| 960 | - /** |
|
| 961 | - * Gets qty of reserved tickets |
|
| 962 | - * |
|
| 963 | - * @return int |
|
| 964 | - * @throws EE_Error |
|
| 965 | - * @throws ReflectionException |
|
| 966 | - */ |
|
| 967 | - public function reserved() |
|
| 968 | - { |
|
| 969 | - return $this->get_raw('TKT_reserved'); |
|
| 970 | - } |
|
| 971 | - |
|
| 972 | - |
|
| 973 | - /** |
|
| 974 | - * Sets reserved |
|
| 975 | - * |
|
| 976 | - * @param int $reserved |
|
| 977 | - * @return void |
|
| 978 | - * @throws EE_Error |
|
| 979 | - * @throws ReflectionException |
|
| 980 | - */ |
|
| 981 | - public function set_reserved($reserved) |
|
| 982 | - { |
|
| 983 | - // reserved can not go below zero |
|
| 984 | - $reserved = max(0, (int) $reserved); |
|
| 985 | - $this->set('TKT_reserved', $reserved); |
|
| 986 | - } |
|
| 987 | - |
|
| 988 | - |
|
| 989 | - /** |
|
| 990 | - * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 991 | - * |
|
| 992 | - * @param int $qty |
|
| 993 | - * @param string $source |
|
| 994 | - * @return bool whether we successfully reserved the ticket or not. |
|
| 995 | - * @throws EE_Error |
|
| 996 | - * @throws InvalidArgumentException |
|
| 997 | - * @throws ReflectionException |
|
| 998 | - * @throws InvalidDataTypeException |
|
| 999 | - * @throws InvalidInterfaceException |
|
| 1000 | - * @since 4.9.80.p |
|
| 1001 | - */ |
|
| 1002 | - public function increaseReserved($qty = 1, $source = 'unknown') |
|
| 1003 | - { |
|
| 1004 | - $qty = absint($qty); |
|
| 1005 | - do_action( |
|
| 1006 | - 'AHEE__EE_Ticket__increase_reserved__begin', |
|
| 1007 | - $this, |
|
| 1008 | - $qty, |
|
| 1009 | - $source |
|
| 1010 | - ); |
|
| 1011 | - $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}"); |
|
| 1012 | - $success = false; |
|
| 1013 | - $datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty); |
|
| 1014 | - if ($datetimes_adjusted_successfully) { |
|
| 1015 | - $success = $this->incrementFieldConditionallyInDb( |
|
| 1016 | - 'TKT_reserved', |
|
| 1017 | - 'TKT_sold', |
|
| 1018 | - 'TKT_qty', |
|
| 1019 | - $qty |
|
| 1020 | - ); |
|
| 1021 | - if (! $success) { |
|
| 1022 | - // The datetimes were successfully bumped, but not the |
|
| 1023 | - // ticket. So we need to manually rollback the datetimes. |
|
| 1024 | - $this->decreaseReservedForDatetimes($qty); |
|
| 1025 | - } |
|
| 1026 | - } |
|
| 1027 | - do_action( |
|
| 1028 | - 'AHEE__EE_Ticket__increase_reserved', |
|
| 1029 | - $this, |
|
| 1030 | - $qty, |
|
| 1031 | - $this->reserved(), |
|
| 1032 | - $success |
|
| 1033 | - ); |
|
| 1034 | - return $success; |
|
| 1035 | - } |
|
| 1036 | - |
|
| 1037 | - |
|
| 1038 | - /** |
|
| 1039 | - * Increases reserved counts on related datetimes |
|
| 1040 | - * |
|
| 1041 | - * @param int $qty |
|
| 1042 | - * @param EE_Datetime[] $datetimes |
|
| 1043 | - * @return boolean indicating success |
|
| 1044 | - * @throws EE_Error |
|
| 1045 | - * @throws InvalidArgumentException |
|
| 1046 | - * @throws InvalidDataTypeException |
|
| 1047 | - * @throws InvalidInterfaceException |
|
| 1048 | - * @throws ReflectionException |
|
| 1049 | - * @since 4.9.80.p |
|
| 1050 | - */ |
|
| 1051 | - protected function increaseReservedForDatetimes($qty = 1, array $datetimes = []) |
|
| 1052 | - { |
|
| 1053 | - $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 1054 | - $datetimes_updated = []; |
|
| 1055 | - $limit_exceeded = false; |
|
| 1056 | - if (is_array($datetimes)) { |
|
| 1057 | - foreach ($datetimes as $datetime) { |
|
| 1058 | - if ($datetime instanceof EE_Datetime) { |
|
| 1059 | - if ($datetime->increaseReserved($qty)) { |
|
| 1060 | - $datetimes_updated[] = $datetime; |
|
| 1061 | - } else { |
|
| 1062 | - $limit_exceeded = true; |
|
| 1063 | - break; |
|
| 1064 | - } |
|
| 1065 | - } |
|
| 1066 | - } |
|
| 1067 | - // If somewhere along the way we detected a datetime whose |
|
| 1068 | - // limit was exceeded, do a manual rollback. |
|
| 1069 | - if ($limit_exceeded) { |
|
| 1070 | - $this->decreaseReservedForDatetimes($qty, $datetimes_updated); |
|
| 1071 | - return false; |
|
| 1072 | - } |
|
| 1073 | - } |
|
| 1074 | - return true; |
|
| 1075 | - } |
|
| 1076 | - |
|
| 1077 | - |
|
| 1078 | - /** |
|
| 1079 | - * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 1080 | - * |
|
| 1081 | - * @param int $qty |
|
| 1082 | - * @param bool $adjust_datetimes |
|
| 1083 | - * @param string $source |
|
| 1084 | - * @return boolean |
|
| 1085 | - * @throws EE_Error |
|
| 1086 | - * @throws InvalidArgumentException |
|
| 1087 | - * @throws ReflectionException |
|
| 1088 | - * @throws InvalidDataTypeException |
|
| 1089 | - * @throws InvalidInterfaceException |
|
| 1090 | - * @since 4.9.80.p |
|
| 1091 | - */ |
|
| 1092 | - public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown') |
|
| 1093 | - { |
|
| 1094 | - $qty = absint($qty); |
|
| 1095 | - $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}"); |
|
| 1096 | - if ($adjust_datetimes) { |
|
| 1097 | - $this->decreaseReservedForDatetimes($qty); |
|
| 1098 | - } |
|
| 1099 | - $success = $this->adjustNumericFieldsInDb( |
|
| 1100 | - [ |
|
| 1101 | - 'TKT_reserved' => $qty * -1, |
|
| 1102 | - ] |
|
| 1103 | - ); |
|
| 1104 | - do_action( |
|
| 1105 | - 'AHEE__EE_Ticket__decrease_reserved', |
|
| 1106 | - $this, |
|
| 1107 | - $qty, |
|
| 1108 | - $this->reserved(), |
|
| 1109 | - $success |
|
| 1110 | - ); |
|
| 1111 | - return $success; |
|
| 1112 | - } |
|
| 1113 | - |
|
| 1114 | - |
|
| 1115 | - /** |
|
| 1116 | - * Decreases the reserved count on the specified datetimes. |
|
| 1117 | - * |
|
| 1118 | - * @param int $qty |
|
| 1119 | - * @param EE_Datetime[] $datetimes |
|
| 1120 | - * @throws EE_Error |
|
| 1121 | - * @throws InvalidArgumentException |
|
| 1122 | - * @throws ReflectionException |
|
| 1123 | - * @throws InvalidDataTypeException |
|
| 1124 | - * @throws InvalidInterfaceException |
|
| 1125 | - * @since 4.9.80.p |
|
| 1126 | - */ |
|
| 1127 | - protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = []) |
|
| 1128 | - { |
|
| 1129 | - $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 1130 | - foreach ($datetimes as $datetime) { |
|
| 1131 | - if ($datetime instanceof EE_Datetime) { |
|
| 1132 | - $datetime->decreaseReserved($qty); |
|
| 1133 | - } |
|
| 1134 | - } |
|
| 1135 | - } |
|
| 1136 | - |
|
| 1137 | - |
|
| 1138 | - /** |
|
| 1139 | - * Gets ticket quantity |
|
| 1140 | - * |
|
| 1141 | - * @param string $context ticket quantity is somewhat subjective depending on the exact information sought |
|
| 1142 | - * therefore $context can be one of three values: '', 'reg_limit', or 'saleable' |
|
| 1143 | - * '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects |
|
| 1144 | - * REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes |
|
| 1145 | - * SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and |
|
| 1146 | - * is therefore the truest measure of tickets that can be purchased at the moment |
|
| 1147 | - * @return int |
|
| 1148 | - * @throws EE_Error |
|
| 1149 | - * @throws ReflectionException |
|
| 1150 | - */ |
|
| 1151 | - public function qty($context = '') |
|
| 1152 | - { |
|
| 1153 | - switch ($context) { |
|
| 1154 | - case 'reg_limit': |
|
| 1155 | - return $this->real_quantity_on_ticket(); |
|
| 1156 | - case 'saleable': |
|
| 1157 | - return $this->real_quantity_on_ticket('saleable'); |
|
| 1158 | - default: |
|
| 1159 | - return $this->get_raw('TKT_qty'); |
|
| 1160 | - } |
|
| 1161 | - } |
|
| 1162 | - |
|
| 1163 | - |
|
| 1164 | - /** |
|
| 1165 | - * Gets ticket quantity |
|
| 1166 | - * |
|
| 1167 | - * @param string $context ticket quantity is somewhat subjective depending on the exact information sought |
|
| 1168 | - * therefore $context can be one of two values: 'reg_limit', or 'saleable' |
|
| 1169 | - * REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes |
|
| 1170 | - * SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and |
|
| 1171 | - * is therefore the truest measure of tickets that can be purchased at the moment |
|
| 1172 | - * @param int $DTT_ID the primary key for a particular datetime. |
|
| 1173 | - * set to 0 for all related datetimes |
|
| 1174 | - * @return int |
|
| 1175 | - * @throws EE_Error |
|
| 1176 | - * @throws ReflectionException |
|
| 1177 | - */ |
|
| 1178 | - public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0) |
|
| 1179 | - { |
|
| 1180 | - $raw = $this->get_raw('TKT_qty'); |
|
| 1181 | - // return immediately if it's zero |
|
| 1182 | - if ($raw === 0) { |
|
| 1183 | - return $raw; |
|
| 1184 | - } |
|
| 1185 | - // echo "\n\n<br />Ticket: " . $this->name() . '<br />'; |
|
| 1186 | - // ensure qty doesn't exceed raw value for THIS ticket |
|
| 1187 | - $qty = min(EE_INF, $raw); |
|
| 1188 | - // echo "\n . qty: " . $qty . '<br />'; |
|
| 1189 | - // calculate this ticket's total sales and reservations |
|
| 1190 | - $sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved(); |
|
| 1191 | - // echo "\n . sold: " . $this->sold() . '<br />'; |
|
| 1192 | - // echo "\n . reserved: " . $this->reserved() . '<br />'; |
|
| 1193 | - // echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />'; |
|
| 1194 | - // first we need to calculate the maximum number of tickets available for the datetime |
|
| 1195 | - // do we want data for one datetime or all of them ? |
|
| 1196 | - $query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : []; |
|
| 1197 | - $datetimes = $this->datetimes($query_params); |
|
| 1198 | - if (is_array($datetimes) && ! empty($datetimes)) { |
|
| 1199 | - foreach ($datetimes as $datetime) { |
|
| 1200 | - if ($datetime instanceof EE_Datetime) { |
|
| 1201 | - $datetime->refresh_from_db(); |
|
| 1202 | - // echo "\n . . datetime name: " . $datetime->name() . '<br />'; |
|
| 1203 | - // echo "\n . . datetime ID: " . $datetime->ID() . '<br />'; |
|
| 1204 | - // initialize with no restrictions for each datetime |
|
| 1205 | - // but adjust datetime qty based on datetime reg limit |
|
| 1206 | - $datetime_qty = min(EE_INF, $datetime->reg_limit()); |
|
| 1207 | - // echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />'; |
|
| 1208 | - // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />'; |
|
| 1209 | - // if we want the actual saleable amount, then we need to consider OTHER ticket sales |
|
| 1210 | - // and reservations for this datetime, that do NOT include sales and reservations |
|
| 1211 | - // for this ticket (so we add $this->sold() and $this->reserved() back in) |
|
| 1212 | - if ($context === 'saleable') { |
|
| 1213 | - $datetime_qty = max( |
|
| 1214 | - $datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket, |
|
| 1215 | - 0 |
|
| 1216 | - ); |
|
| 1217 | - // echo "\n . . . datetime sold: " . $datetime->sold() . '<br />'; |
|
| 1218 | - // echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />'; |
|
| 1219 | - // echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />'; |
|
| 1220 | - // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />'; |
|
| 1221 | - $datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0; |
|
| 1222 | - // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />'; |
|
| 1223 | - } |
|
| 1224 | - $qty = min($datetime_qty, $qty); |
|
| 1225 | - // echo "\n . . qty: " . $qty . '<br />'; |
|
| 1226 | - } |
|
| 1227 | - } |
|
| 1228 | - } |
|
| 1229 | - // NOW that we know the maximum number of tickets available for the datetime |
|
| 1230 | - // we can finally factor in the details for this specific ticket |
|
| 1231 | - if ($qty > 0 && $context === 'saleable') { |
|
| 1232 | - // and subtract the sales for THIS ticket |
|
| 1233 | - $qty = max($qty - $sold_and_reserved_for_this_ticket, 0); |
|
| 1234 | - // echo "\n . qty: " . $qty . '<br />'; |
|
| 1235 | - } |
|
| 1236 | - // echo "\nFINAL QTY: " . $qty . "<br /><br />"; |
|
| 1237 | - return $qty; |
|
| 1238 | - } |
|
| 1239 | - |
|
| 1240 | - |
|
| 1241 | - /** |
|
| 1242 | - * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes |
|
| 1243 | - * |
|
| 1244 | - * @param int $qty |
|
| 1245 | - * @return void |
|
| 1246 | - * @throws EE_Error |
|
| 1247 | - * @throws ReflectionException |
|
| 1248 | - */ |
|
| 1249 | - public function set_qty($qty) |
|
| 1250 | - { |
|
| 1251 | - $datetimes = $this->datetimes(); |
|
| 1252 | - foreach ($datetimes as $datetime) { |
|
| 1253 | - if ($datetime instanceof EE_Datetime) { |
|
| 1254 | - $qty = min($qty, $datetime->reg_limit()); |
|
| 1255 | - } |
|
| 1256 | - } |
|
| 1257 | - $this->set('TKT_qty', $qty); |
|
| 1258 | - } |
|
| 1259 | - |
|
| 1260 | - |
|
| 1261 | - /** |
|
| 1262 | - * Gets uses |
|
| 1263 | - * |
|
| 1264 | - * @return int |
|
| 1265 | - * @throws EE_Error |
|
| 1266 | - * @throws ReflectionException |
|
| 1267 | - */ |
|
| 1268 | - public function uses() |
|
| 1269 | - { |
|
| 1270 | - return $this->get('TKT_uses'); |
|
| 1271 | - } |
|
| 1272 | - |
|
| 1273 | - |
|
| 1274 | - /** |
|
| 1275 | - * Sets uses |
|
| 1276 | - * |
|
| 1277 | - * @param int $uses |
|
| 1278 | - * @return void |
|
| 1279 | - * @throws EE_Error |
|
| 1280 | - * @throws ReflectionException |
|
| 1281 | - */ |
|
| 1282 | - public function set_uses($uses) |
|
| 1283 | - { |
|
| 1284 | - $this->set('TKT_uses', $uses); |
|
| 1285 | - } |
|
| 1286 | - |
|
| 1287 | - |
|
| 1288 | - /** |
|
| 1289 | - * returns whether ticket is required or not. |
|
| 1290 | - * |
|
| 1291 | - * @return boolean |
|
| 1292 | - * @throws EE_Error |
|
| 1293 | - * @throws ReflectionException |
|
| 1294 | - */ |
|
| 1295 | - public function required() |
|
| 1296 | - { |
|
| 1297 | - return $this->get('TKT_required'); |
|
| 1298 | - } |
|
| 1299 | - |
|
| 1300 | - |
|
| 1301 | - /** |
|
| 1302 | - * sets the TKT_required property |
|
| 1303 | - * |
|
| 1304 | - * @param boolean $required |
|
| 1305 | - * @return void |
|
| 1306 | - * @throws EE_Error |
|
| 1307 | - * @throws ReflectionException |
|
| 1308 | - */ |
|
| 1309 | - public function set_required($required) |
|
| 1310 | - { |
|
| 1311 | - $this->set('TKT_required', $required); |
|
| 1312 | - } |
|
| 1313 | - |
|
| 1314 | - |
|
| 1315 | - /** |
|
| 1316 | - * Gets taxable |
|
| 1317 | - * |
|
| 1318 | - * @return boolean |
|
| 1319 | - * @throws EE_Error |
|
| 1320 | - * @throws ReflectionException |
|
| 1321 | - */ |
|
| 1322 | - public function taxable() |
|
| 1323 | - { |
|
| 1324 | - return $this->get('TKT_taxable'); |
|
| 1325 | - } |
|
| 1326 | - |
|
| 1327 | - |
|
| 1328 | - /** |
|
| 1329 | - * Sets taxable |
|
| 1330 | - * |
|
| 1331 | - * @param boolean $taxable |
|
| 1332 | - * @return void |
|
| 1333 | - * @throws EE_Error |
|
| 1334 | - * @throws ReflectionException |
|
| 1335 | - */ |
|
| 1336 | - public function set_taxable($taxable) |
|
| 1337 | - { |
|
| 1338 | - $this->set('TKT_taxable', $taxable); |
|
| 1339 | - } |
|
| 1340 | - |
|
| 1341 | - |
|
| 1342 | - /** |
|
| 1343 | - * Gets is_default |
|
| 1344 | - * |
|
| 1345 | - * @return boolean |
|
| 1346 | - * @throws EE_Error |
|
| 1347 | - * @throws ReflectionException |
|
| 1348 | - */ |
|
| 1349 | - public function is_default() |
|
| 1350 | - { |
|
| 1351 | - return $this->get('TKT_is_default'); |
|
| 1352 | - } |
|
| 1353 | - |
|
| 1354 | - |
|
| 1355 | - /** |
|
| 1356 | - * Sets is_default |
|
| 1357 | - * |
|
| 1358 | - * @param boolean $is_default |
|
| 1359 | - * @return void |
|
| 1360 | - * @throws EE_Error |
|
| 1361 | - * @throws ReflectionException |
|
| 1362 | - */ |
|
| 1363 | - public function set_is_default($is_default) |
|
| 1364 | - { |
|
| 1365 | - $this->set('TKT_is_default', $is_default); |
|
| 1366 | - } |
|
| 1367 | - |
|
| 1368 | - |
|
| 1369 | - /** |
|
| 1370 | - * Gets order |
|
| 1371 | - * |
|
| 1372 | - * @return int |
|
| 1373 | - * @throws EE_Error |
|
| 1374 | - * @throws ReflectionException |
|
| 1375 | - */ |
|
| 1376 | - public function order() |
|
| 1377 | - { |
|
| 1378 | - return $this->get('TKT_order'); |
|
| 1379 | - } |
|
| 1380 | - |
|
| 1381 | - |
|
| 1382 | - /** |
|
| 1383 | - * Sets order |
|
| 1384 | - * |
|
| 1385 | - * @param int $order |
|
| 1386 | - * @return void |
|
| 1387 | - * @throws EE_Error |
|
| 1388 | - * @throws ReflectionException |
|
| 1389 | - */ |
|
| 1390 | - public function set_order($order) |
|
| 1391 | - { |
|
| 1392 | - $this->set('TKT_order', $order); |
|
| 1393 | - } |
|
| 1394 | - |
|
| 1395 | - |
|
| 1396 | - /** |
|
| 1397 | - * Gets row |
|
| 1398 | - * |
|
| 1399 | - * @return int |
|
| 1400 | - * @throws EE_Error |
|
| 1401 | - * @throws ReflectionException |
|
| 1402 | - */ |
|
| 1403 | - public function row() |
|
| 1404 | - { |
|
| 1405 | - return $this->get('TKT_row'); |
|
| 1406 | - } |
|
| 1407 | - |
|
| 1408 | - |
|
| 1409 | - /** |
|
| 1410 | - * Sets row |
|
| 1411 | - * |
|
| 1412 | - * @param int $row |
|
| 1413 | - * @return void |
|
| 1414 | - * @throws EE_Error |
|
| 1415 | - * @throws ReflectionException |
|
| 1416 | - */ |
|
| 1417 | - public function set_row($row) |
|
| 1418 | - { |
|
| 1419 | - $this->set('TKT_row', $row); |
|
| 1420 | - } |
|
| 1421 | - |
|
| 1422 | - |
|
| 1423 | - /** |
|
| 1424 | - * Gets deleted |
|
| 1425 | - * |
|
| 1426 | - * @return boolean |
|
| 1427 | - * @throws EE_Error |
|
| 1428 | - * @throws ReflectionException |
|
| 1429 | - */ |
|
| 1430 | - public function deleted() |
|
| 1431 | - { |
|
| 1432 | - return $this->get('TKT_deleted'); |
|
| 1433 | - } |
|
| 1434 | - |
|
| 1435 | - |
|
| 1436 | - /** |
|
| 1437 | - * Sets deleted |
|
| 1438 | - * |
|
| 1439 | - * @param boolean $deleted |
|
| 1440 | - * @return void |
|
| 1441 | - * @throws EE_Error |
|
| 1442 | - * @throws ReflectionException |
|
| 1443 | - */ |
|
| 1444 | - public function set_deleted($deleted) |
|
| 1445 | - { |
|
| 1446 | - $this->set('TKT_deleted', $deleted); |
|
| 1447 | - } |
|
| 1448 | - |
|
| 1449 | - |
|
| 1450 | - /** |
|
| 1451 | - * Gets parent |
|
| 1452 | - * |
|
| 1453 | - * @return int |
|
| 1454 | - * @throws EE_Error |
|
| 1455 | - * @throws ReflectionException |
|
| 1456 | - */ |
|
| 1457 | - public function parent_ID() |
|
| 1458 | - { |
|
| 1459 | - return $this->get('TKT_parent'); |
|
| 1460 | - } |
|
| 1461 | - |
|
| 1462 | - |
|
| 1463 | - /** |
|
| 1464 | - * Sets parent |
|
| 1465 | - * |
|
| 1466 | - * @param int $parent |
|
| 1467 | - * @return void |
|
| 1468 | - * @throws EE_Error |
|
| 1469 | - * @throws ReflectionException |
|
| 1470 | - */ |
|
| 1471 | - public function set_parent_ID($parent) |
|
| 1472 | - { |
|
| 1473 | - $this->set('TKT_parent', $parent); |
|
| 1474 | - } |
|
| 1475 | - |
|
| 1476 | - |
|
| 1477 | - /** |
|
| 1478 | - * @return boolean |
|
| 1479 | - * @throws EE_Error |
|
| 1480 | - * @throws InvalidArgumentException |
|
| 1481 | - * @throws InvalidDataTypeException |
|
| 1482 | - * @throws InvalidInterfaceException |
|
| 1483 | - * @throws ReflectionException |
|
| 1484 | - */ |
|
| 1485 | - public function reverse_calculate() |
|
| 1486 | - { |
|
| 1487 | - return $this->get('TKT_reverse_calculate'); |
|
| 1488 | - } |
|
| 1489 | - |
|
| 1490 | - |
|
| 1491 | - /** |
|
| 1492 | - * @param boolean $reverse_calculate |
|
| 1493 | - * @throws EE_Error |
|
| 1494 | - * @throws InvalidArgumentException |
|
| 1495 | - * @throws InvalidDataTypeException |
|
| 1496 | - * @throws InvalidInterfaceException |
|
| 1497 | - * @throws ReflectionException |
|
| 1498 | - */ |
|
| 1499 | - public function set_reverse_calculate($reverse_calculate) |
|
| 1500 | - { |
|
| 1501 | - $this->set('TKT_reverse_calculate', $reverse_calculate); |
|
| 1502 | - } |
|
| 1503 | - |
|
| 1504 | - |
|
| 1505 | - /** |
|
| 1506 | - * Gets a string which is handy for showing in gateways etc that describes the ticket. |
|
| 1507 | - * |
|
| 1508 | - * @return string |
|
| 1509 | - * @throws EE_Error |
|
| 1510 | - * @throws ReflectionException |
|
| 1511 | - */ |
|
| 1512 | - public function name_and_info() |
|
| 1513 | - { |
|
| 1514 | - $times = []; |
|
| 1515 | - foreach ($this->datetimes() as $datetime) { |
|
| 1516 | - $times[] = $datetime->start_date_and_time(); |
|
| 1517 | - } |
|
| 1518 | - return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price(); |
|
| 1519 | - } |
|
| 1520 | - |
|
| 1521 | - |
|
| 1522 | - /** |
|
| 1523 | - * Gets name |
|
| 1524 | - * |
|
| 1525 | - * @return string |
|
| 1526 | - * @throws EE_Error |
|
| 1527 | - * @throws ReflectionException |
|
| 1528 | - */ |
|
| 1529 | - public function name() |
|
| 1530 | - { |
|
| 1531 | - return $this->get('TKT_name'); |
|
| 1532 | - } |
|
| 1533 | - |
|
| 1534 | - |
|
| 1535 | - /** |
|
| 1536 | - * Gets price |
|
| 1537 | - * |
|
| 1538 | - * @return float |
|
| 1539 | - * @throws EE_Error |
|
| 1540 | - * @throws ReflectionException |
|
| 1541 | - */ |
|
| 1542 | - public function price() |
|
| 1543 | - { |
|
| 1544 | - return $this->get('TKT_price'); |
|
| 1545 | - } |
|
| 1546 | - |
|
| 1547 | - |
|
| 1548 | - /** |
|
| 1549 | - * Gets all the registrations for this ticket |
|
| 1550 | - * |
|
| 1551 | - * @param array $query_params @see |
|
| 1552 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1553 | - * @return EE_Registration[]|EE_Base_Class[] |
|
| 1554 | - * @throws EE_Error |
|
| 1555 | - * @throws ReflectionException |
|
| 1556 | - */ |
|
| 1557 | - public function registrations($query_params = []) |
|
| 1558 | - { |
|
| 1559 | - return $this->get_many_related('Registration', $query_params); |
|
| 1560 | - } |
|
| 1561 | - |
|
| 1562 | - |
|
| 1563 | - /** |
|
| 1564 | - * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket. |
|
| 1565 | - * |
|
| 1566 | - * @return int |
|
| 1567 | - * @throws EE_Error |
|
| 1568 | - * @throws ReflectionException |
|
| 1569 | - */ |
|
| 1570 | - public function update_tickets_sold() |
|
| 1571 | - { |
|
| 1572 | - $count_regs_for_this_ticket = $this->count_registrations( |
|
| 1573 | - [ |
|
| 1574 | - [ |
|
| 1575 | - 'STS_ID' => EEM_Registration::status_id_approved, |
|
| 1576 | - 'REG_deleted' => 0, |
|
| 1577 | - ], |
|
| 1578 | - ] |
|
| 1579 | - ); |
|
| 1580 | - $this->set_sold($count_regs_for_this_ticket); |
|
| 1581 | - $this->save(); |
|
| 1582 | - return $count_regs_for_this_ticket; |
|
| 1583 | - } |
|
| 1584 | - |
|
| 1585 | - |
|
| 1586 | - /** |
|
| 1587 | - * Counts the registrations for this ticket |
|
| 1588 | - * |
|
| 1589 | - * @param array $query_params @see |
|
| 1590 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1591 | - * @return int |
|
| 1592 | - * @throws EE_Error |
|
| 1593 | - * @throws ReflectionException |
|
| 1594 | - */ |
|
| 1595 | - public function count_registrations($query_params = []) |
|
| 1596 | - { |
|
| 1597 | - return $this->count_related('Registration', $query_params); |
|
| 1598 | - } |
|
| 1599 | - |
|
| 1600 | - |
|
| 1601 | - /** |
|
| 1602 | - * Implementation for EEI_Has_Icon interface method. |
|
| 1603 | - * |
|
| 1604 | - * @return string |
|
| 1605 | - * @see EEI_Visual_Representation for comments |
|
| 1606 | - */ |
|
| 1607 | - public function get_icon() |
|
| 1608 | - { |
|
| 1609 | - return '<span class="dashicons dashicons-tickets-alt"/>'; |
|
| 1610 | - } |
|
| 1611 | - |
|
| 1612 | - |
|
| 1613 | - /** |
|
| 1614 | - * Implementation of the EEI_Event_Relation interface method |
|
| 1615 | - * |
|
| 1616 | - * @return EE_Event |
|
| 1617 | - * @throws EE_Error |
|
| 1618 | - * @throws UnexpectedEntityException |
|
| 1619 | - * @throws ReflectionException |
|
| 1620 | - * @see EEI_Event_Relation for comments |
|
| 1621 | - */ |
|
| 1622 | - public function get_related_event() |
|
| 1623 | - { |
|
| 1624 | - // get one datetime to use for getting the event |
|
| 1625 | - $datetime = $this->first_datetime(); |
|
| 1626 | - if (! $datetime instanceof EE_Datetime) { |
|
| 1627 | - throw new UnexpectedEntityException( |
|
| 1628 | - $datetime, |
|
| 1629 | - 'EE_Datetime', |
|
| 1630 | - sprintf( |
|
| 1631 | - __('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'), |
|
| 1632 | - $this->name() |
|
| 1633 | - ) |
|
| 1634 | - ); |
|
| 1635 | - } |
|
| 1636 | - $event = $datetime->event(); |
|
| 1637 | - if (! $event instanceof EE_Event) { |
|
| 1638 | - throw new UnexpectedEntityException( |
|
| 1639 | - $event, |
|
| 1640 | - 'EE_Event', |
|
| 1641 | - sprintf( |
|
| 1642 | - __('The ticket (%s) is not associated with a valid event.', 'event_espresso'), |
|
| 1643 | - $this->name() |
|
| 1644 | - ) |
|
| 1645 | - ); |
|
| 1646 | - } |
|
| 1647 | - return $event; |
|
| 1648 | - } |
|
| 1649 | - |
|
| 1650 | - |
|
| 1651 | - /** |
|
| 1652 | - * Implementation of the EEI_Event_Relation interface method |
|
| 1653 | - * |
|
| 1654 | - * @return string |
|
| 1655 | - * @throws UnexpectedEntityException |
|
| 1656 | - * @throws EE_Error |
|
| 1657 | - * @throws ReflectionException |
|
| 1658 | - * @see EEI_Event_Relation for comments |
|
| 1659 | - */ |
|
| 1660 | - public function get_event_name() |
|
| 1661 | - { |
|
| 1662 | - $event = $this->get_related_event(); |
|
| 1663 | - return $event instanceof EE_Event ? $event->name() : ''; |
|
| 1664 | - } |
|
| 1665 | - |
|
| 1666 | - |
|
| 1667 | - /** |
|
| 1668 | - * Implementation of the EEI_Event_Relation interface method |
|
| 1669 | - * |
|
| 1670 | - * @return int |
|
| 1671 | - * @throws UnexpectedEntityException |
|
| 1672 | - * @throws EE_Error |
|
| 1673 | - * @throws ReflectionException |
|
| 1674 | - * @see EEI_Event_Relation for comments |
|
| 1675 | - */ |
|
| 1676 | - public function get_event_ID() |
|
| 1677 | - { |
|
| 1678 | - $event = $this->get_related_event(); |
|
| 1679 | - return $event instanceof EE_Event ? $event->ID() : 0; |
|
| 1680 | - } |
|
| 1681 | - |
|
| 1682 | - |
|
| 1683 | - /** |
|
| 1684 | - * This simply returns whether a ticket can be permanently deleted or not. |
|
| 1685 | - * The criteria for determining this is whether the ticket has any related registrations. |
|
| 1686 | - * If there are none then it can be permanently deleted. |
|
| 1687 | - * |
|
| 1688 | - * @return bool |
|
| 1689 | - * @throws EE_Error |
|
| 1690 | - * @throws ReflectionException |
|
| 1691 | - */ |
|
| 1692 | - public function is_permanently_deleteable() |
|
| 1693 | - { |
|
| 1694 | - return $this->count_registrations() === 0; |
|
| 1695 | - } |
|
| 1696 | - |
|
| 1697 | - |
|
| 1698 | - /** |
|
| 1699 | - * @return int |
|
| 1700 | - * @throws EE_Error |
|
| 1701 | - * @throws ReflectionException |
|
| 1702 | - * @since $VID:$ |
|
| 1703 | - */ |
|
| 1704 | - public function visibility(): int |
|
| 1705 | - { |
|
| 1706 | - return $this->get('TKT_visibility'); |
|
| 1707 | - } |
|
| 1708 | - |
|
| 1709 | - |
|
| 1710 | - /** |
|
| 1711 | - * @return int |
|
| 1712 | - * @throws EE_Error |
|
| 1713 | - * @throws ReflectionException |
|
| 1714 | - * @since $VID:$ |
|
| 1715 | - */ |
|
| 1716 | - public function isHidden(): int |
|
| 1717 | - { |
|
| 1718 | - return $this->visibility() === EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE; |
|
| 1719 | - } |
|
| 1720 | - |
|
| 1721 | - |
|
| 1722 | - /** |
|
| 1723 | - * @return int |
|
| 1724 | - * @throws EE_Error |
|
| 1725 | - * @throws ReflectionException |
|
| 1726 | - * @since $VID:$ |
|
| 1727 | - */ |
|
| 1728 | - public function isNotHidden(): int |
|
| 1729 | - { |
|
| 1730 | - return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE; |
|
| 1731 | - } |
|
| 1732 | - |
|
| 1733 | - |
|
| 1734 | - /** |
|
| 1735 | - * @return int |
|
| 1736 | - * @throws EE_Error |
|
| 1737 | - * @throws ReflectionException |
|
| 1738 | - * @since $VID:$ |
|
| 1739 | - */ |
|
| 1740 | - public function isPublicOnly(): int |
|
| 1741 | - { |
|
| 1742 | - return $this->isNotHidden() && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE; |
|
| 1743 | - } |
|
| 1744 | - |
|
| 1745 | - |
|
| 1746 | - /** |
|
| 1747 | - * @return int |
|
| 1748 | - * @throws EE_Error |
|
| 1749 | - * @throws ReflectionException |
|
| 1750 | - * @since $VID:$ |
|
| 1751 | - */ |
|
| 1752 | - public function isMembersOnly(): int |
|
| 1753 | - { |
|
| 1754 | - return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE |
|
| 1755 | - && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE; |
|
| 1756 | - } |
|
| 1757 | - |
|
| 1758 | - |
|
| 1759 | - /** |
|
| 1760 | - * @return int |
|
| 1761 | - * @throws EE_Error |
|
| 1762 | - * @throws ReflectionException |
|
| 1763 | - * @since $VID:$ |
|
| 1764 | - */ |
|
| 1765 | - public function isAdminsOnly(): int |
|
| 1766 | - { |
|
| 1767 | - return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE |
|
| 1768 | - && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE; |
|
| 1769 | - } |
|
| 1770 | - |
|
| 1771 | - |
|
| 1772 | - /** |
|
| 1773 | - * @return int |
|
| 1774 | - * @throws EE_Error |
|
| 1775 | - * @throws ReflectionException |
|
| 1776 | - * @since $VID:$ |
|
| 1777 | - */ |
|
| 1778 | - public function isAdminUiOnly(): int |
|
| 1779 | - { |
|
| 1780 | - return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE |
|
| 1781 | - && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMIN_UI_ONLY_VALUE; |
|
| 1782 | - } |
|
| 1783 | - |
|
| 1784 | - |
|
| 1785 | - /** |
|
| 1786 | - * @param int $visibility |
|
| 1787 | - * @throws EE_Error |
|
| 1788 | - * @throws ReflectionException |
|
| 1789 | - * @since $VID:$ |
|
| 1790 | - */ |
|
| 1791 | - public function set_visibility(int $visibility) |
|
| 1792 | - { |
|
| 1793 | - |
|
| 1794 | - $ticket_visibility_options = $this->_model->ticketVisibilityOptions(); |
|
| 1795 | - $ticket_visibility = -1; |
|
| 1796 | - foreach ($ticket_visibility_options as $ticket_visibility_option) { |
|
| 1797 | - if ($visibility === $ticket_visibility_option) { |
|
| 1798 | - $ticket_visibility = $visibility; |
|
| 1799 | - } |
|
| 1800 | - } |
|
| 1801 | - if ($ticket_visibility === -1) { |
|
| 1802 | - throw new DomainException( |
|
| 1803 | - sprintf( |
|
| 1804 | - esc_html__( |
|
| 1805 | - 'The supplied ticket visibility setting of "%1$s" is not valid. It needs to match one of the keys in the following array:%2$s %3$s ', |
|
| 1806 | - 'event_espresso' |
|
| 1807 | - ), |
|
| 1808 | - $visibility, |
|
| 1809 | - '<br />', |
|
| 1810 | - var_export($ticket_visibility_options, true) |
|
| 1811 | - ) |
|
| 1812 | - ); |
|
| 1813 | - } |
|
| 1814 | - $this->set('TKT_visibility', $ticket_visibility); |
|
| 1815 | - } |
|
| 1816 | - |
|
| 1817 | - |
|
| 1818 | - /******************************************************************* |
|
| 17 | + /** |
|
| 18 | + * TicKet Sold out: |
|
| 19 | + * constant used by ticket_status() to indicate that a ticket is sold out |
|
| 20 | + * and no longer available for purchases |
|
| 21 | + */ |
|
| 22 | + const sold_out = 'TKS'; |
|
| 23 | + |
|
| 24 | + /** |
|
| 25 | + * TicKet Expired: |
|
| 26 | + * constant used by ticket_status() to indicate that a ticket is expired |
|
| 27 | + * and no longer available for purchase |
|
| 28 | + */ |
|
| 29 | + const expired = 'TKE'; |
|
| 30 | + |
|
| 31 | + /** |
|
| 32 | + * TicKet Archived: |
|
| 33 | + * constant used by ticket_status() to indicate that a ticket is archived |
|
| 34 | + * and no longer available for purchase |
|
| 35 | + */ |
|
| 36 | + const archived = 'TKA'; |
|
| 37 | + |
|
| 38 | + /** |
|
| 39 | + * TicKet Pending: |
|
| 40 | + * constant used by ticket_status() to indicate that a ticket is pending |
|
| 41 | + * and is NOT YET available for purchase |
|
| 42 | + */ |
|
| 43 | + const pending = 'TKP'; |
|
| 44 | + |
|
| 45 | + /** |
|
| 46 | + * TicKet On sale: |
|
| 47 | + * constant used by ticket_status() to indicate that a ticket is On Sale |
|
| 48 | + * and IS available for purchase |
|
| 49 | + */ |
|
| 50 | + const onsale = 'TKO'; |
|
| 51 | + |
|
| 52 | + /** |
|
| 53 | + * extra meta key for tracking ticket reservations |
|
| 54 | + * |
|
| 55 | + * @type string |
|
| 56 | + */ |
|
| 57 | + const META_KEY_TICKET_RESERVATIONS = 'ticket_reservations'; |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * override of parent property |
|
| 61 | + * |
|
| 62 | + * @var EEM_Ticket |
|
| 63 | + */ |
|
| 64 | + protected $_model; |
|
| 65 | + |
|
| 66 | + /** |
|
| 67 | + * cached result from method of the same name |
|
| 68 | + * |
|
| 69 | + * @var float $_ticket_total_with_taxes |
|
| 70 | + */ |
|
| 71 | + private $_ticket_total_with_taxes; |
|
| 72 | + |
|
| 73 | + |
|
| 74 | + /** |
|
| 75 | + * @param array $props_n_values incoming values |
|
| 76 | + * @param string $timezone incoming timezone (if not set the timezone set for the website will be |
|
| 77 | + * used.) |
|
| 78 | + * @param array $date_formats incoming date_formats in an array where the first value is the |
|
| 79 | + * date_format and the second value is the time format |
|
| 80 | + * @return EE_Ticket |
|
| 81 | + * @throws EE_Error |
|
| 82 | + * @throws ReflectionException |
|
| 83 | + */ |
|
| 84 | + public static function new_instance($props_n_values = [], $timezone = '', $date_formats = []) |
|
| 85 | + { |
|
| 86 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats); |
|
| 87 | + return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats); |
|
| 88 | + } |
|
| 89 | + |
|
| 90 | + |
|
| 91 | + /** |
|
| 92 | + * @param array $props_n_values incoming values from the database |
|
| 93 | + * @param string $timezone incoming timezone as set by the model. If not set the timezone for |
|
| 94 | + * the website will be used. |
|
| 95 | + * @return EE_Ticket |
|
| 96 | + * @throws EE_Error |
|
| 97 | + * @throws ReflectionException |
|
| 98 | + */ |
|
| 99 | + public static function new_instance_from_db($props_n_values = [], $timezone = '') |
|
| 100 | + { |
|
| 101 | + return new self($props_n_values, true, $timezone); |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + |
|
| 105 | + /** |
|
| 106 | + * @return bool |
|
| 107 | + * @throws EE_Error |
|
| 108 | + * @throws ReflectionException |
|
| 109 | + */ |
|
| 110 | + public function parent() |
|
| 111 | + { |
|
| 112 | + return $this->get('TKT_parent'); |
|
| 113 | + } |
|
| 114 | + |
|
| 115 | + |
|
| 116 | + /** |
|
| 117 | + * return if a ticket has quantities available for purchase |
|
| 118 | + * |
|
| 119 | + * @param int $DTT_ID the primary key for a particular datetime |
|
| 120 | + * @return boolean |
|
| 121 | + * @throws EE_Error |
|
| 122 | + * @throws ReflectionException |
|
| 123 | + */ |
|
| 124 | + public function available($DTT_ID = 0) |
|
| 125 | + { |
|
| 126 | + // are we checking availability for a particular datetime ? |
|
| 127 | + if ($DTT_ID) { |
|
| 128 | + // get that datetime object |
|
| 129 | + $datetime = $this->get_first_related('Datetime', [['DTT_ID' => $DTT_ID]]); |
|
| 130 | + // if ticket sales for this datetime have exceeded the reg limit... |
|
| 131 | + if ($datetime instanceof EE_Datetime && $datetime->sold_out()) { |
|
| 132 | + return false; |
|
| 133 | + } |
|
| 134 | + } |
|
| 135 | + // datetime is still open for registration, but is this ticket sold out ? |
|
| 136 | + return $this->qty() < 1 || $this->qty() > $this->sold(); |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + |
|
| 140 | + /** |
|
| 141 | + * Using the start date and end date this method calculates whether the ticket is On Sale, Pending, or Expired |
|
| 142 | + * |
|
| 143 | + * @param bool $display true = we'll return a localized string, otherwise we just return the value of the |
|
| 144 | + * relevant status const |
|
| 145 | + * @param bool | null $remaining if it is already known that tickets are available, then simply pass a bool to save |
|
| 146 | + * further processing |
|
| 147 | + * @return mixed status int if the display string isn't requested |
|
| 148 | + * @throws EE_Error |
|
| 149 | + * @throws ReflectionException |
|
| 150 | + */ |
|
| 151 | + public function ticket_status($display = false, $remaining = null) |
|
| 152 | + { |
|
| 153 | + $remaining = is_bool($remaining) ? $remaining : $this->is_remaining(); |
|
| 154 | + if (! $remaining) { |
|
| 155 | + return $display ? EEH_Template::pretty_status(EE_Ticket::sold_out, false, 'sentence') : EE_Ticket::sold_out; |
|
| 156 | + } |
|
| 157 | + if ($this->get('TKT_deleted')) { |
|
| 158 | + return $display ? EEH_Template::pretty_status(EE_Ticket::archived, false, 'sentence') : EE_Ticket::archived; |
|
| 159 | + } |
|
| 160 | + if ($this->is_expired()) { |
|
| 161 | + return $display ? EEH_Template::pretty_status(EE_Ticket::expired, false, 'sentence') : EE_Ticket::expired; |
|
| 162 | + } |
|
| 163 | + if ($this->is_pending()) { |
|
| 164 | + return $display ? EEH_Template::pretty_status(EE_Ticket::pending, false, 'sentence') : EE_Ticket::pending; |
|
| 165 | + } |
|
| 166 | + if ($this->is_on_sale()) { |
|
| 167 | + return $display ? EEH_Template::pretty_status(EE_Ticket::onsale, false, 'sentence') : EE_Ticket::onsale; |
|
| 168 | + } |
|
| 169 | + return ''; |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + |
|
| 173 | + /** |
|
| 174 | + * The purpose of this method is to simply return a boolean for whether there are any tickets remaining for sale |
|
| 175 | + * considering ALL the factors used for figuring that out. |
|
| 176 | + * |
|
| 177 | + * @access public |
|
| 178 | + * @param int $DTT_ID if an int above 0 is included here then we get a specific dtt. |
|
| 179 | + * @return boolean true = tickets remaining, false not. |
|
| 180 | + * @throws EE_Error |
|
| 181 | + * @throws ReflectionException |
|
| 182 | + */ |
|
| 183 | + public function is_remaining($DTT_ID = 0) |
|
| 184 | + { |
|
| 185 | + $num_remaining = $this->remaining($DTT_ID); |
|
| 186 | + if ($num_remaining === 0) { |
|
| 187 | + return false; |
|
| 188 | + } |
|
| 189 | + if ($num_remaining > 0 && $num_remaining < $this->min()) { |
|
| 190 | + return false; |
|
| 191 | + } |
|
| 192 | + return true; |
|
| 193 | + } |
|
| 194 | + |
|
| 195 | + |
|
| 196 | + /** |
|
| 197 | + * return the total number of tickets available for purchase |
|
| 198 | + * |
|
| 199 | + * @param int $DTT_ID the primary key for a particular datetime. |
|
| 200 | + * set to 0 for all related datetimes |
|
| 201 | + * @return int |
|
| 202 | + * @throws EE_Error |
|
| 203 | + * @throws ReflectionException |
|
| 204 | + */ |
|
| 205 | + public function remaining($DTT_ID = 0) |
|
| 206 | + { |
|
| 207 | + return $this->real_quantity_on_ticket('saleable', $DTT_ID); |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + |
|
| 211 | + /** |
|
| 212 | + * Gets min |
|
| 213 | + * |
|
| 214 | + * @return int |
|
| 215 | + * @throws EE_Error |
|
| 216 | + * @throws ReflectionException |
|
| 217 | + */ |
|
| 218 | + public function min() |
|
| 219 | + { |
|
| 220 | + return $this->get('TKT_min'); |
|
| 221 | + } |
|
| 222 | + |
|
| 223 | + |
|
| 224 | + /** |
|
| 225 | + * return if a ticket is no longer available cause its available dates have expired. |
|
| 226 | + * |
|
| 227 | + * @return boolean |
|
| 228 | + * @throws EE_Error |
|
| 229 | + * @throws ReflectionException |
|
| 230 | + */ |
|
| 231 | + public function is_expired() |
|
| 232 | + { |
|
| 233 | + return ($this->get_raw('TKT_end_date') < time()); |
|
| 234 | + } |
|
| 235 | + |
|
| 236 | + |
|
| 237 | + /** |
|
| 238 | + * Return if a ticket is yet to go on sale or not |
|
| 239 | + * |
|
| 240 | + * @return boolean |
|
| 241 | + * @throws EE_Error |
|
| 242 | + * @throws ReflectionException |
|
| 243 | + */ |
|
| 244 | + public function is_pending() |
|
| 245 | + { |
|
| 246 | + return ($this->get_raw('TKT_start_date') >= time()); |
|
| 247 | + } |
|
| 248 | + |
|
| 249 | + |
|
| 250 | + /** |
|
| 251 | + * Return if a ticket is on sale or not |
|
| 252 | + * |
|
| 253 | + * @return boolean |
|
| 254 | + * @throws EE_Error |
|
| 255 | + * @throws ReflectionException |
|
| 256 | + */ |
|
| 257 | + public function is_on_sale() |
|
| 258 | + { |
|
| 259 | + return ($this->get_raw('TKT_start_date') <= time() && $this->get_raw('TKT_end_date') >= time()); |
|
| 260 | + } |
|
| 261 | + |
|
| 262 | + |
|
| 263 | + /** |
|
| 264 | + * This returns the chronologically last datetime that this ticket is associated with |
|
| 265 | + * |
|
| 266 | + * @param string $date_format |
|
| 267 | + * @param string $conjunction - conjunction junction what's your function ? this string joins the start date with |
|
| 268 | + * the end date ie: Jan 01 "to" Dec 31 |
|
| 269 | + * @return string |
|
| 270 | + * @throws EE_Error |
|
| 271 | + * @throws ReflectionException |
|
| 272 | + */ |
|
| 273 | + public function date_range($date_format = '', $conjunction = ' - ') |
|
| 274 | + { |
|
| 275 | + $date_format = ! empty($date_format) ? $date_format : $this->_dt_frmt; |
|
| 276 | + $first_date = $this->first_datetime() instanceof EE_Datetime |
|
| 277 | + ? $this->first_datetime()->get_i18n_datetime('DTT_EVT_start', $date_format) |
|
| 278 | + : ''; |
|
| 279 | + $last_date = $this->last_datetime() instanceof EE_Datetime |
|
| 280 | + ? $this->last_datetime()->get_i18n_datetime('DTT_EVT_end', $date_format) |
|
| 281 | + : ''; |
|
| 282 | + |
|
| 283 | + return $first_date && $last_date ? $first_date . $conjunction . $last_date : ''; |
|
| 284 | + } |
|
| 285 | + |
|
| 286 | + |
|
| 287 | + /** |
|
| 288 | + * This returns the chronologically first datetime that this ticket is associated with |
|
| 289 | + * |
|
| 290 | + * @return EE_Datetime |
|
| 291 | + * @throws EE_Error |
|
| 292 | + * @throws ReflectionException |
|
| 293 | + */ |
|
| 294 | + public function first_datetime() |
|
| 295 | + { |
|
| 296 | + $datetimes = $this->datetimes(['limit' => 1]); |
|
| 297 | + return reset($datetimes); |
|
| 298 | + } |
|
| 299 | + |
|
| 300 | + |
|
| 301 | + /** |
|
| 302 | + * Gets all the datetimes this ticket can be used for attending. |
|
| 303 | + * Unless otherwise specified, orders datetimes by start date. |
|
| 304 | + * |
|
| 305 | + * @param array $query_params @see |
|
| 306 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 307 | + * @return EE_Datetime[]|EE_Base_Class[] |
|
| 308 | + * @throws EE_Error |
|
| 309 | + * @throws ReflectionException |
|
| 310 | + */ |
|
| 311 | + public function datetimes($query_params = []) |
|
| 312 | + { |
|
| 313 | + if (! isset($query_params['order_by'])) { |
|
| 314 | + $query_params['order_by']['DTT_order'] = 'ASC'; |
|
| 315 | + } |
|
| 316 | + return $this->get_many_related('Datetime', $query_params); |
|
| 317 | + } |
|
| 318 | + |
|
| 319 | + |
|
| 320 | + /** |
|
| 321 | + * This returns the chronologically last datetime that this ticket is associated with |
|
| 322 | + * |
|
| 323 | + * @return EE_Datetime |
|
| 324 | + * @throws EE_Error |
|
| 325 | + * @throws ReflectionException |
|
| 326 | + */ |
|
| 327 | + public function last_datetime() |
|
| 328 | + { |
|
| 329 | + $datetimes = $this->datetimes(['limit' => 1, 'order_by' => ['DTT_EVT_start' => 'DESC']]); |
|
| 330 | + return end($datetimes); |
|
| 331 | + } |
|
| 332 | + |
|
| 333 | + |
|
| 334 | + /** |
|
| 335 | + * This returns the total tickets sold depending on the given parameters. |
|
| 336 | + * |
|
| 337 | + * @param string $what Can be one of two options: 'ticket', 'datetime'. |
|
| 338 | + * 'ticket' = total ticket sales for all datetimes this ticket is related to |
|
| 339 | + * 'datetime' = total ticket sales for a specified datetime (required $dtt_id) |
|
| 340 | + * 'datetime' = total ticket sales in the datetime_ticket table. |
|
| 341 | + * If $dtt_id is not given then we return an array of sales indexed by datetime. |
|
| 342 | + * If $dtt_id IS given then we return the tickets sold for that given datetime. |
|
| 343 | + * @param int $dtt_id [optional] include the dtt_id with $what = 'datetime'. |
|
| 344 | + * @return mixed (array|int) how many tickets have sold |
|
| 345 | + * @throws EE_Error |
|
| 346 | + * @throws ReflectionException |
|
| 347 | + */ |
|
| 348 | + public function tickets_sold($what = 'ticket', $dtt_id = null) |
|
| 349 | + { |
|
| 350 | + $total = 0; |
|
| 351 | + $tickets_sold = $this->_all_tickets_sold(); |
|
| 352 | + switch ($what) { |
|
| 353 | + case 'ticket': |
|
| 354 | + return $tickets_sold['ticket']; |
|
| 355 | + break; |
|
| 356 | + case 'datetime': |
|
| 357 | + if (empty($tickets_sold['datetime'])) { |
|
| 358 | + return $total; |
|
| 359 | + } |
|
| 360 | + if (! empty($dtt_id) && ! isset($tickets_sold['datetime'][ $dtt_id ])) { |
|
| 361 | + EE_Error::add_error( |
|
| 362 | + __( |
|
| 363 | + 'You\'ve requested the amount of tickets sold for a given ticket and datetime, however there are no records for the datetime id you included. Are you SURE that is a datetime related to this ticket?', |
|
| 364 | + 'event_espresso' |
|
| 365 | + ), |
|
| 366 | + __FILE__, |
|
| 367 | + __FUNCTION__, |
|
| 368 | + __LINE__ |
|
| 369 | + ); |
|
| 370 | + return $total; |
|
| 371 | + } |
|
| 372 | + return empty($dtt_id) ? $tickets_sold['datetime'] : $tickets_sold['datetime'][ $dtt_id ]; |
|
| 373 | + break; |
|
| 374 | + default: |
|
| 375 | + return $total; |
|
| 376 | + } |
|
| 377 | + } |
|
| 378 | + |
|
| 379 | + |
|
| 380 | + /** |
|
| 381 | + * This returns an array indexed by datetime_id for tickets sold with this ticket. |
|
| 382 | + * |
|
| 383 | + * @return EE_Ticket[] |
|
| 384 | + * @throws EE_Error |
|
| 385 | + * @throws ReflectionException |
|
| 386 | + */ |
|
| 387 | + protected function _all_tickets_sold() |
|
| 388 | + { |
|
| 389 | + $datetimes = $this->get_many_related('Datetime'); |
|
| 390 | + $tickets_sold = []; |
|
| 391 | + if (! empty($datetimes)) { |
|
| 392 | + foreach ($datetimes as $datetime) { |
|
| 393 | + $tickets_sold['datetime'][ $datetime->ID() ] = $datetime->get('DTT_sold'); |
|
| 394 | + } |
|
| 395 | + } |
|
| 396 | + // Tickets sold |
|
| 397 | + $tickets_sold['ticket'] = $this->sold(); |
|
| 398 | + return $tickets_sold; |
|
| 399 | + } |
|
| 400 | + |
|
| 401 | + |
|
| 402 | + /** |
|
| 403 | + * This returns the base price object for the ticket. |
|
| 404 | + * |
|
| 405 | + * @param bool $return_array whether to return as an array indexed by price id or just the object. |
|
| 406 | + * @return EE_Price|EE_Base_Class|EE_Price[]|EE_Base_Class[] |
|
| 407 | + * @throws EE_Error |
|
| 408 | + * @throws ReflectionException |
|
| 409 | + */ |
|
| 410 | + public function base_price($return_array = false) |
|
| 411 | + { |
|
| 412 | + $_where = ['Price_Type.PBT_ID' => EEM_Price_Type::base_type_base_price]; |
|
| 413 | + return $return_array |
|
| 414 | + ? $this->get_many_related('Price', [$_where]) |
|
| 415 | + : $this->get_first_related('Price', [$_where]); |
|
| 416 | + } |
|
| 417 | + |
|
| 418 | + |
|
| 419 | + /** |
|
| 420 | + * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price) |
|
| 421 | + * |
|
| 422 | + * @access public |
|
| 423 | + * @return EE_Price[] |
|
| 424 | + * @throws EE_Error |
|
| 425 | + * @throws ReflectionException |
|
| 426 | + */ |
|
| 427 | + public function price_modifiers() |
|
| 428 | + { |
|
| 429 | + $query_params = [ |
|
| 430 | + 0 => [ |
|
| 431 | + 'Price_Type.PBT_ID' => [ |
|
| 432 | + 'NOT IN', |
|
| 433 | + [EEM_Price_Type::base_type_base_price, EEM_Price_Type::base_type_tax], |
|
| 434 | + ], |
|
| 435 | + ], |
|
| 436 | + ]; |
|
| 437 | + return $this->prices($query_params); |
|
| 438 | + } |
|
| 439 | + |
|
| 440 | + |
|
| 441 | + /** |
|
| 442 | + * This returns ONLY the price modifiers for the ticket (i.e. no taxes or base price) |
|
| 443 | + * |
|
| 444 | + * @access public |
|
| 445 | + * @return EE_Price[] |
|
| 446 | + * @throws EE_Error |
|
| 447 | + * @throws ReflectionException |
|
| 448 | + */ |
|
| 449 | + public function tax_price_modifiers() |
|
| 450 | + { |
|
| 451 | + $query_params = [ |
|
| 452 | + 0 => [ |
|
| 453 | + 'Price_Type.PBT_ID' => EEM_Price_Type::base_type_tax, |
|
| 454 | + ], |
|
| 455 | + ]; |
|
| 456 | + return $this->prices($query_params); |
|
| 457 | + } |
|
| 458 | + |
|
| 459 | + |
|
| 460 | + /** |
|
| 461 | + * Gets all the prices that combine to form the final price of this ticket |
|
| 462 | + * |
|
| 463 | + * @param array $query_params @see |
|
| 464 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 465 | + * @return EE_Price[]|EE_Base_Class[] |
|
| 466 | + * @throws EE_Error |
|
| 467 | + * @throws ReflectionException |
|
| 468 | + */ |
|
| 469 | + public function prices($query_params = []) |
|
| 470 | + { |
|
| 471 | + return $this->get_many_related('Price', $query_params); |
|
| 472 | + } |
|
| 473 | + |
|
| 474 | + |
|
| 475 | + /** |
|
| 476 | + * Gets all the ticket datetimes (ie, relations between datetimes and tickets) |
|
| 477 | + * |
|
| 478 | + * @param array $query_params @see |
|
| 479 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 480 | + * @return EE_Datetime_Ticket|EE_Base_Class[] |
|
| 481 | + * @throws EE_Error |
|
| 482 | + * @throws ReflectionException |
|
| 483 | + */ |
|
| 484 | + public function datetime_tickets($query_params = []) |
|
| 485 | + { |
|
| 486 | + return $this->get_many_related('Datetime_Ticket', $query_params); |
|
| 487 | + } |
|
| 488 | + |
|
| 489 | + |
|
| 490 | + /** |
|
| 491 | + * Gets all the datetimes from the db ordered by DTT_order |
|
| 492 | + * |
|
| 493 | + * @param boolean $show_expired |
|
| 494 | + * @param boolean $show_deleted |
|
| 495 | + * @return EE_Datetime[] |
|
| 496 | + * @throws EE_Error |
|
| 497 | + * @throws ReflectionException |
|
| 498 | + */ |
|
| 499 | + public function datetimes_ordered($show_expired = true, $show_deleted = false) |
|
| 500 | + { |
|
| 501 | + return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_ticket_ordered_by_DTT_order( |
|
| 502 | + $this->ID(), |
|
| 503 | + $show_expired, |
|
| 504 | + $show_deleted |
|
| 505 | + ); |
|
| 506 | + } |
|
| 507 | + |
|
| 508 | + |
|
| 509 | + /** |
|
| 510 | + * Gets ID |
|
| 511 | + * |
|
| 512 | + * @return string |
|
| 513 | + * @throws EE_Error |
|
| 514 | + * @throws ReflectionException |
|
| 515 | + */ |
|
| 516 | + public function ID() |
|
| 517 | + { |
|
| 518 | + return $this->get('TKT_ID'); |
|
| 519 | + } |
|
| 520 | + |
|
| 521 | + |
|
| 522 | + /** |
|
| 523 | + * get the author of the ticket. |
|
| 524 | + * |
|
| 525 | + * @return int |
|
| 526 | + * @throws EE_Error |
|
| 527 | + * @throws ReflectionException |
|
| 528 | + * @since 4.5.0 |
|
| 529 | + */ |
|
| 530 | + public function wp_user() |
|
| 531 | + { |
|
| 532 | + return $this->get('TKT_wp_user'); |
|
| 533 | + } |
|
| 534 | + |
|
| 535 | + |
|
| 536 | + /** |
|
| 537 | + * Gets the template for the ticket |
|
| 538 | + * |
|
| 539 | + * @return EE_Ticket_Template|EE_Base_Class |
|
| 540 | + * @throws EE_Error |
|
| 541 | + * @throws ReflectionException |
|
| 542 | + */ |
|
| 543 | + public function template() |
|
| 544 | + { |
|
| 545 | + return $this->get_first_related('Ticket_Template'); |
|
| 546 | + } |
|
| 547 | + |
|
| 548 | + |
|
| 549 | + /** |
|
| 550 | + * Simply returns an array of EE_Price objects that are taxes. |
|
| 551 | + * |
|
| 552 | + * @return EE_Price[] |
|
| 553 | + * @throws EE_Error |
|
| 554 | + */ |
|
| 555 | + public function get_ticket_taxes_for_admin() |
|
| 556 | + { |
|
| 557 | + return EE_Taxes::get_taxes_for_admin(); |
|
| 558 | + } |
|
| 559 | + |
|
| 560 | + |
|
| 561 | + /** |
|
| 562 | + * @return float |
|
| 563 | + * @throws EE_Error |
|
| 564 | + * @throws ReflectionException |
|
| 565 | + */ |
|
| 566 | + public function ticket_price() |
|
| 567 | + { |
|
| 568 | + return $this->get('TKT_price'); |
|
| 569 | + } |
|
| 570 | + |
|
| 571 | + |
|
| 572 | + /** |
|
| 573 | + * @return mixed |
|
| 574 | + * @throws EE_Error |
|
| 575 | + * @throws ReflectionException |
|
| 576 | + */ |
|
| 577 | + public function pretty_price() |
|
| 578 | + { |
|
| 579 | + return $this->get_pretty('TKT_price'); |
|
| 580 | + } |
|
| 581 | + |
|
| 582 | + |
|
| 583 | + /** |
|
| 584 | + * @return bool |
|
| 585 | + * @throws EE_Error |
|
| 586 | + * @throws ReflectionException |
|
| 587 | + */ |
|
| 588 | + public function is_free() |
|
| 589 | + { |
|
| 590 | + return $this->get_ticket_total_with_taxes() === (float) 0; |
|
| 591 | + } |
|
| 592 | + |
|
| 593 | + |
|
| 594 | + /** |
|
| 595 | + * get_ticket_total_with_taxes |
|
| 596 | + * |
|
| 597 | + * @param bool $no_cache |
|
| 598 | + * @return float |
|
| 599 | + * @throws EE_Error |
|
| 600 | + * @throws ReflectionException |
|
| 601 | + */ |
|
| 602 | + public function get_ticket_total_with_taxes($no_cache = false) |
|
| 603 | + { |
|
| 604 | + if ($this->_ticket_total_with_taxes === null || $no_cache) { |
|
| 605 | + $this->_ticket_total_with_taxes = $this->get_ticket_subtotal() + $this->get_ticket_taxes_total_for_admin(); |
|
| 606 | + } |
|
| 607 | + return (float) $this->_ticket_total_with_taxes; |
|
| 608 | + } |
|
| 609 | + |
|
| 610 | + |
|
| 611 | + /** |
|
| 612 | + * @throws EE_Error |
|
| 613 | + * @throws ReflectionException |
|
| 614 | + */ |
|
| 615 | + public function ensure_TKT_Price_correct() |
|
| 616 | + { |
|
| 617 | + $this->set('TKT_price', EE_Taxes::get_subtotal_for_admin($this)); |
|
| 618 | + $this->save(); |
|
| 619 | + } |
|
| 620 | + |
|
| 621 | + |
|
| 622 | + /** |
|
| 623 | + * @return float |
|
| 624 | + * @throws EE_Error |
|
| 625 | + * @throws ReflectionException |
|
| 626 | + */ |
|
| 627 | + public function get_ticket_subtotal() |
|
| 628 | + { |
|
| 629 | + return EE_Taxes::get_subtotal_for_admin($this); |
|
| 630 | + } |
|
| 631 | + |
|
| 632 | + |
|
| 633 | + /** |
|
| 634 | + * Returns the total taxes applied to this ticket |
|
| 635 | + * |
|
| 636 | + * @return float |
|
| 637 | + * @throws EE_Error |
|
| 638 | + * @throws ReflectionException |
|
| 639 | + */ |
|
| 640 | + public function get_ticket_taxes_total_for_admin() |
|
| 641 | + { |
|
| 642 | + return EE_Taxes::get_total_taxes_for_admin($this); |
|
| 643 | + } |
|
| 644 | + |
|
| 645 | + |
|
| 646 | + /** |
|
| 647 | + * Sets name |
|
| 648 | + * |
|
| 649 | + * @param string $name |
|
| 650 | + * @throws EE_Error |
|
| 651 | + * @throws ReflectionException |
|
| 652 | + */ |
|
| 653 | + public function set_name($name) |
|
| 654 | + { |
|
| 655 | + $this->set('TKT_name', $name); |
|
| 656 | + } |
|
| 657 | + |
|
| 658 | + |
|
| 659 | + /** |
|
| 660 | + * Gets description |
|
| 661 | + * |
|
| 662 | + * @return string |
|
| 663 | + * @throws EE_Error |
|
| 664 | + * @throws ReflectionException |
|
| 665 | + */ |
|
| 666 | + public function description() |
|
| 667 | + { |
|
| 668 | + return $this->get('TKT_description'); |
|
| 669 | + } |
|
| 670 | + |
|
| 671 | + |
|
| 672 | + /** |
|
| 673 | + * Sets description |
|
| 674 | + * |
|
| 675 | + * @param string $description |
|
| 676 | + * @throws EE_Error |
|
| 677 | + * @throws ReflectionException |
|
| 678 | + */ |
|
| 679 | + public function set_description($description) |
|
| 680 | + { |
|
| 681 | + $this->set('TKT_description', $description); |
|
| 682 | + } |
|
| 683 | + |
|
| 684 | + |
|
| 685 | + /** |
|
| 686 | + * Gets start_date |
|
| 687 | + * |
|
| 688 | + * @param string $date_format |
|
| 689 | + * @param string $time_format |
|
| 690 | + * @return string |
|
| 691 | + * @throws EE_Error |
|
| 692 | + * @throws ReflectionException |
|
| 693 | + */ |
|
| 694 | + public function start_date($date_format = '', $time_format = '') |
|
| 695 | + { |
|
| 696 | + return $this->_get_datetime('TKT_start_date', $date_format, $time_format); |
|
| 697 | + } |
|
| 698 | + |
|
| 699 | + |
|
| 700 | + /** |
|
| 701 | + * Sets start_date |
|
| 702 | + * |
|
| 703 | + * @param string $start_date |
|
| 704 | + * @return void |
|
| 705 | + * @throws EE_Error |
|
| 706 | + * @throws ReflectionException |
|
| 707 | + */ |
|
| 708 | + public function set_start_date($start_date) |
|
| 709 | + { |
|
| 710 | + $this->_set_date_time('B', $start_date, 'TKT_start_date'); |
|
| 711 | + } |
|
| 712 | + |
|
| 713 | + |
|
| 714 | + /** |
|
| 715 | + * Gets end_date |
|
| 716 | + * |
|
| 717 | + * @param string $date_format |
|
| 718 | + * @param string $time_format |
|
| 719 | + * @return string |
|
| 720 | + * @throws EE_Error |
|
| 721 | + * @throws ReflectionException |
|
| 722 | + */ |
|
| 723 | + public function end_date($date_format = '', $time_format = '') |
|
| 724 | + { |
|
| 725 | + return $this->_get_datetime('TKT_end_date', $date_format, $time_format); |
|
| 726 | + } |
|
| 727 | + |
|
| 728 | + |
|
| 729 | + /** |
|
| 730 | + * Sets end_date |
|
| 731 | + * |
|
| 732 | + * @param string $end_date |
|
| 733 | + * @return void |
|
| 734 | + * @throws EE_Error |
|
| 735 | + * @throws ReflectionException |
|
| 736 | + */ |
|
| 737 | + public function set_end_date($end_date) |
|
| 738 | + { |
|
| 739 | + $this->_set_date_time('B', $end_date, 'TKT_end_date'); |
|
| 740 | + } |
|
| 741 | + |
|
| 742 | + |
|
| 743 | + /** |
|
| 744 | + * Sets sell until time |
|
| 745 | + * |
|
| 746 | + * @param string $time a string representation of the sell until time (ex 9am or 7:30pm) |
|
| 747 | + * @throws EE_Error |
|
| 748 | + * @throws ReflectionException |
|
| 749 | + * @since 4.5.0 |
|
| 750 | + */ |
|
| 751 | + public function set_end_time($time) |
|
| 752 | + { |
|
| 753 | + $this->_set_time_for($time, 'TKT_end_date'); |
|
| 754 | + } |
|
| 755 | + |
|
| 756 | + |
|
| 757 | + /** |
|
| 758 | + * Sets min |
|
| 759 | + * |
|
| 760 | + * @param int $min |
|
| 761 | + * @return void |
|
| 762 | + * @throws EE_Error |
|
| 763 | + * @throws ReflectionException |
|
| 764 | + */ |
|
| 765 | + public function set_min($min) |
|
| 766 | + { |
|
| 767 | + $this->set('TKT_min', $min); |
|
| 768 | + } |
|
| 769 | + |
|
| 770 | + |
|
| 771 | + /** |
|
| 772 | + * Gets max |
|
| 773 | + * |
|
| 774 | + * @return int |
|
| 775 | + * @throws EE_Error |
|
| 776 | + * @throws ReflectionException |
|
| 777 | + */ |
|
| 778 | + public function max() |
|
| 779 | + { |
|
| 780 | + return $this->get('TKT_max'); |
|
| 781 | + } |
|
| 782 | + |
|
| 783 | + |
|
| 784 | + /** |
|
| 785 | + * Sets max |
|
| 786 | + * |
|
| 787 | + * @param int $max |
|
| 788 | + * @return void |
|
| 789 | + * @throws EE_Error |
|
| 790 | + * @throws ReflectionException |
|
| 791 | + */ |
|
| 792 | + public function set_max($max) |
|
| 793 | + { |
|
| 794 | + $this->set('TKT_max', $max); |
|
| 795 | + } |
|
| 796 | + |
|
| 797 | + |
|
| 798 | + /** |
|
| 799 | + * Sets price |
|
| 800 | + * |
|
| 801 | + * @param float $price |
|
| 802 | + * @return void |
|
| 803 | + * @throws EE_Error |
|
| 804 | + * @throws ReflectionException |
|
| 805 | + */ |
|
| 806 | + public function set_price($price) |
|
| 807 | + { |
|
| 808 | + $this->set('TKT_price', $price); |
|
| 809 | + } |
|
| 810 | + |
|
| 811 | + |
|
| 812 | + /** |
|
| 813 | + * Gets sold |
|
| 814 | + * |
|
| 815 | + * @return int |
|
| 816 | + * @throws EE_Error |
|
| 817 | + * @throws ReflectionException |
|
| 818 | + */ |
|
| 819 | + public function sold() |
|
| 820 | + { |
|
| 821 | + return $this->get_raw('TKT_sold'); |
|
| 822 | + } |
|
| 823 | + |
|
| 824 | + |
|
| 825 | + /** |
|
| 826 | + * Sets sold |
|
| 827 | + * |
|
| 828 | + * @param int $sold |
|
| 829 | + * @return void |
|
| 830 | + * @throws EE_Error |
|
| 831 | + * @throws ReflectionException |
|
| 832 | + */ |
|
| 833 | + public function set_sold($sold) |
|
| 834 | + { |
|
| 835 | + // sold can not go below zero |
|
| 836 | + $sold = max(0, $sold); |
|
| 837 | + $this->set('TKT_sold', $sold); |
|
| 838 | + } |
|
| 839 | + |
|
| 840 | + |
|
| 841 | + /** |
|
| 842 | + * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its |
|
| 843 | + * associated datetimes. |
|
| 844 | + * |
|
| 845 | + * @param int $qty |
|
| 846 | + * @return boolean |
|
| 847 | + * @throws EE_Error |
|
| 848 | + * @throws InvalidArgumentException |
|
| 849 | + * @throws InvalidDataTypeException |
|
| 850 | + * @throws InvalidInterfaceException |
|
| 851 | + * @throws ReflectionException |
|
| 852 | + * @since 4.9.80.p |
|
| 853 | + */ |
|
| 854 | + public function increaseSold($qty = 1) |
|
| 855 | + { |
|
| 856 | + $qty = absint($qty); |
|
| 857 | + // increment sold and decrement reserved datetime quantities simultaneously |
|
| 858 | + // don't worry about failures, because they must have already had a spot reserved |
|
| 859 | + $this->increaseSoldForDatetimes($qty); |
|
| 860 | + // Increment and decrement ticket quantities simultaneously |
|
| 861 | + $success = $this->adjustNumericFieldsInDb( |
|
| 862 | + [ |
|
| 863 | + 'TKT_reserved' => $qty * -1, |
|
| 864 | + 'TKT_sold' => $qty, |
|
| 865 | + ] |
|
| 866 | + ); |
|
| 867 | + do_action( |
|
| 868 | + 'AHEE__EE_Ticket__increase_sold', |
|
| 869 | + $this, |
|
| 870 | + $qty, |
|
| 871 | + $this->sold(), |
|
| 872 | + $success |
|
| 873 | + ); |
|
| 874 | + return $success; |
|
| 875 | + } |
|
| 876 | + |
|
| 877 | + |
|
| 878 | + /** |
|
| 879 | + * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty. |
|
| 880 | + * |
|
| 881 | + * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved |
|
| 882 | + * counts), Negative means to decreases old counts (and increase reserved counts). |
|
| 883 | + * @param EE_Datetime[] $datetimes |
|
| 884 | + * @throws EE_Error |
|
| 885 | + * @throws InvalidArgumentException |
|
| 886 | + * @throws InvalidDataTypeException |
|
| 887 | + * @throws InvalidInterfaceException |
|
| 888 | + * @throws ReflectionException |
|
| 889 | + * @since 4.9.80.p |
|
| 890 | + */ |
|
| 891 | + protected function increaseSoldForDatetimes($qty, array $datetimes = []) |
|
| 892 | + { |
|
| 893 | + $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 894 | + foreach ($datetimes as $datetime) { |
|
| 895 | + $datetime->increaseSold($qty); |
|
| 896 | + } |
|
| 897 | + } |
|
| 898 | + |
|
| 899 | + |
|
| 900 | + /** |
|
| 901 | + * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the |
|
| 902 | + * DB and then updates the model objects. |
|
| 903 | + * Does not affect the reserved counts. |
|
| 904 | + * |
|
| 905 | + * @param int $qty |
|
| 906 | + * @return boolean |
|
| 907 | + * @throws EE_Error |
|
| 908 | + * @throws InvalidArgumentException |
|
| 909 | + * @throws InvalidDataTypeException |
|
| 910 | + * @throws InvalidInterfaceException |
|
| 911 | + * @throws ReflectionException |
|
| 912 | + * @since 4.9.80.p |
|
| 913 | + */ |
|
| 914 | + public function decreaseSold($qty = 1) |
|
| 915 | + { |
|
| 916 | + $qty = absint($qty); |
|
| 917 | + $this->decreaseSoldForDatetimes($qty); |
|
| 918 | + $success = $this->adjustNumericFieldsInDb( |
|
| 919 | + [ |
|
| 920 | + 'TKT_sold' => $qty * -1, |
|
| 921 | + ] |
|
| 922 | + ); |
|
| 923 | + do_action( |
|
| 924 | + 'AHEE__EE_Ticket__decrease_sold', |
|
| 925 | + $this, |
|
| 926 | + $qty, |
|
| 927 | + $this->sold(), |
|
| 928 | + $success |
|
| 929 | + ); |
|
| 930 | + return $success; |
|
| 931 | + } |
|
| 932 | + |
|
| 933 | + |
|
| 934 | + /** |
|
| 935 | + * Decreases sold on related datetimes |
|
| 936 | + * |
|
| 937 | + * @param int $qty |
|
| 938 | + * @param EE_Datetime[] $datetimes |
|
| 939 | + * @return void |
|
| 940 | + * @throws EE_Error |
|
| 941 | + * @throws InvalidArgumentException |
|
| 942 | + * @throws InvalidDataTypeException |
|
| 943 | + * @throws InvalidInterfaceException |
|
| 944 | + * @throws ReflectionException |
|
| 945 | + * @since 4.9.80.p |
|
| 946 | + */ |
|
| 947 | + protected function decreaseSoldForDatetimes($qty = 1, array $datetimes = []) |
|
| 948 | + { |
|
| 949 | + $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 950 | + if (is_array($datetimes)) { |
|
| 951 | + foreach ($datetimes as $datetime) { |
|
| 952 | + if ($datetime instanceof EE_Datetime) { |
|
| 953 | + $datetime->decreaseSold($qty); |
|
| 954 | + } |
|
| 955 | + } |
|
| 956 | + } |
|
| 957 | + } |
|
| 958 | + |
|
| 959 | + |
|
| 960 | + /** |
|
| 961 | + * Gets qty of reserved tickets |
|
| 962 | + * |
|
| 963 | + * @return int |
|
| 964 | + * @throws EE_Error |
|
| 965 | + * @throws ReflectionException |
|
| 966 | + */ |
|
| 967 | + public function reserved() |
|
| 968 | + { |
|
| 969 | + return $this->get_raw('TKT_reserved'); |
|
| 970 | + } |
|
| 971 | + |
|
| 972 | + |
|
| 973 | + /** |
|
| 974 | + * Sets reserved |
|
| 975 | + * |
|
| 976 | + * @param int $reserved |
|
| 977 | + * @return void |
|
| 978 | + * @throws EE_Error |
|
| 979 | + * @throws ReflectionException |
|
| 980 | + */ |
|
| 981 | + public function set_reserved($reserved) |
|
| 982 | + { |
|
| 983 | + // reserved can not go below zero |
|
| 984 | + $reserved = max(0, (int) $reserved); |
|
| 985 | + $this->set('TKT_reserved', $reserved); |
|
| 986 | + } |
|
| 987 | + |
|
| 988 | + |
|
| 989 | + /** |
|
| 990 | + * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 991 | + * |
|
| 992 | + * @param int $qty |
|
| 993 | + * @param string $source |
|
| 994 | + * @return bool whether we successfully reserved the ticket or not. |
|
| 995 | + * @throws EE_Error |
|
| 996 | + * @throws InvalidArgumentException |
|
| 997 | + * @throws ReflectionException |
|
| 998 | + * @throws InvalidDataTypeException |
|
| 999 | + * @throws InvalidInterfaceException |
|
| 1000 | + * @since 4.9.80.p |
|
| 1001 | + */ |
|
| 1002 | + public function increaseReserved($qty = 1, $source = 'unknown') |
|
| 1003 | + { |
|
| 1004 | + $qty = absint($qty); |
|
| 1005 | + do_action( |
|
| 1006 | + 'AHEE__EE_Ticket__increase_reserved__begin', |
|
| 1007 | + $this, |
|
| 1008 | + $qty, |
|
| 1009 | + $source |
|
| 1010 | + ); |
|
| 1011 | + $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "{$qty} from {$source}"); |
|
| 1012 | + $success = false; |
|
| 1013 | + $datetimes_adjusted_successfully = $this->increaseReservedForDatetimes($qty); |
|
| 1014 | + if ($datetimes_adjusted_successfully) { |
|
| 1015 | + $success = $this->incrementFieldConditionallyInDb( |
|
| 1016 | + 'TKT_reserved', |
|
| 1017 | + 'TKT_sold', |
|
| 1018 | + 'TKT_qty', |
|
| 1019 | + $qty |
|
| 1020 | + ); |
|
| 1021 | + if (! $success) { |
|
| 1022 | + // The datetimes were successfully bumped, but not the |
|
| 1023 | + // ticket. So we need to manually rollback the datetimes. |
|
| 1024 | + $this->decreaseReservedForDatetimes($qty); |
|
| 1025 | + } |
|
| 1026 | + } |
|
| 1027 | + do_action( |
|
| 1028 | + 'AHEE__EE_Ticket__increase_reserved', |
|
| 1029 | + $this, |
|
| 1030 | + $qty, |
|
| 1031 | + $this->reserved(), |
|
| 1032 | + $success |
|
| 1033 | + ); |
|
| 1034 | + return $success; |
|
| 1035 | + } |
|
| 1036 | + |
|
| 1037 | + |
|
| 1038 | + /** |
|
| 1039 | + * Increases reserved counts on related datetimes |
|
| 1040 | + * |
|
| 1041 | + * @param int $qty |
|
| 1042 | + * @param EE_Datetime[] $datetimes |
|
| 1043 | + * @return boolean indicating success |
|
| 1044 | + * @throws EE_Error |
|
| 1045 | + * @throws InvalidArgumentException |
|
| 1046 | + * @throws InvalidDataTypeException |
|
| 1047 | + * @throws InvalidInterfaceException |
|
| 1048 | + * @throws ReflectionException |
|
| 1049 | + * @since 4.9.80.p |
|
| 1050 | + */ |
|
| 1051 | + protected function increaseReservedForDatetimes($qty = 1, array $datetimes = []) |
|
| 1052 | + { |
|
| 1053 | + $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 1054 | + $datetimes_updated = []; |
|
| 1055 | + $limit_exceeded = false; |
|
| 1056 | + if (is_array($datetimes)) { |
|
| 1057 | + foreach ($datetimes as $datetime) { |
|
| 1058 | + if ($datetime instanceof EE_Datetime) { |
|
| 1059 | + if ($datetime->increaseReserved($qty)) { |
|
| 1060 | + $datetimes_updated[] = $datetime; |
|
| 1061 | + } else { |
|
| 1062 | + $limit_exceeded = true; |
|
| 1063 | + break; |
|
| 1064 | + } |
|
| 1065 | + } |
|
| 1066 | + } |
|
| 1067 | + // If somewhere along the way we detected a datetime whose |
|
| 1068 | + // limit was exceeded, do a manual rollback. |
|
| 1069 | + if ($limit_exceeded) { |
|
| 1070 | + $this->decreaseReservedForDatetimes($qty, $datetimes_updated); |
|
| 1071 | + return false; |
|
| 1072 | + } |
|
| 1073 | + } |
|
| 1074 | + return true; |
|
| 1075 | + } |
|
| 1076 | + |
|
| 1077 | + |
|
| 1078 | + /** |
|
| 1079 | + * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 1080 | + * |
|
| 1081 | + * @param int $qty |
|
| 1082 | + * @param bool $adjust_datetimes |
|
| 1083 | + * @param string $source |
|
| 1084 | + * @return boolean |
|
| 1085 | + * @throws EE_Error |
|
| 1086 | + * @throws InvalidArgumentException |
|
| 1087 | + * @throws ReflectionException |
|
| 1088 | + * @throws InvalidDataTypeException |
|
| 1089 | + * @throws InvalidInterfaceException |
|
| 1090 | + * @since 4.9.80.p |
|
| 1091 | + */ |
|
| 1092 | + public function decreaseReserved($qty = 1, $adjust_datetimes = true, $source = 'unknown') |
|
| 1093 | + { |
|
| 1094 | + $qty = absint($qty); |
|
| 1095 | + $this->add_extra_meta(EE_Ticket::META_KEY_TICKET_RESERVATIONS, "-{$qty} from {$source}"); |
|
| 1096 | + if ($adjust_datetimes) { |
|
| 1097 | + $this->decreaseReservedForDatetimes($qty); |
|
| 1098 | + } |
|
| 1099 | + $success = $this->adjustNumericFieldsInDb( |
|
| 1100 | + [ |
|
| 1101 | + 'TKT_reserved' => $qty * -1, |
|
| 1102 | + ] |
|
| 1103 | + ); |
|
| 1104 | + do_action( |
|
| 1105 | + 'AHEE__EE_Ticket__decrease_reserved', |
|
| 1106 | + $this, |
|
| 1107 | + $qty, |
|
| 1108 | + $this->reserved(), |
|
| 1109 | + $success |
|
| 1110 | + ); |
|
| 1111 | + return $success; |
|
| 1112 | + } |
|
| 1113 | + |
|
| 1114 | + |
|
| 1115 | + /** |
|
| 1116 | + * Decreases the reserved count on the specified datetimes. |
|
| 1117 | + * |
|
| 1118 | + * @param int $qty |
|
| 1119 | + * @param EE_Datetime[] $datetimes |
|
| 1120 | + * @throws EE_Error |
|
| 1121 | + * @throws InvalidArgumentException |
|
| 1122 | + * @throws ReflectionException |
|
| 1123 | + * @throws InvalidDataTypeException |
|
| 1124 | + * @throws InvalidInterfaceException |
|
| 1125 | + * @since 4.9.80.p |
|
| 1126 | + */ |
|
| 1127 | + protected function decreaseReservedForDatetimes($qty = 1, array $datetimes = []) |
|
| 1128 | + { |
|
| 1129 | + $datetimes = ! empty($datetimes) ? $datetimes : $this->datetimes(); |
|
| 1130 | + foreach ($datetimes as $datetime) { |
|
| 1131 | + if ($datetime instanceof EE_Datetime) { |
|
| 1132 | + $datetime->decreaseReserved($qty); |
|
| 1133 | + } |
|
| 1134 | + } |
|
| 1135 | + } |
|
| 1136 | + |
|
| 1137 | + |
|
| 1138 | + /** |
|
| 1139 | + * Gets ticket quantity |
|
| 1140 | + * |
|
| 1141 | + * @param string $context ticket quantity is somewhat subjective depending on the exact information sought |
|
| 1142 | + * therefore $context can be one of three values: '', 'reg_limit', or 'saleable' |
|
| 1143 | + * '' (default) quantity is the actual db value for TKT_qty, unaffected by other objects |
|
| 1144 | + * REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes |
|
| 1145 | + * SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and |
|
| 1146 | + * is therefore the truest measure of tickets that can be purchased at the moment |
|
| 1147 | + * @return int |
|
| 1148 | + * @throws EE_Error |
|
| 1149 | + * @throws ReflectionException |
|
| 1150 | + */ |
|
| 1151 | + public function qty($context = '') |
|
| 1152 | + { |
|
| 1153 | + switch ($context) { |
|
| 1154 | + case 'reg_limit': |
|
| 1155 | + return $this->real_quantity_on_ticket(); |
|
| 1156 | + case 'saleable': |
|
| 1157 | + return $this->real_quantity_on_ticket('saleable'); |
|
| 1158 | + default: |
|
| 1159 | + return $this->get_raw('TKT_qty'); |
|
| 1160 | + } |
|
| 1161 | + } |
|
| 1162 | + |
|
| 1163 | + |
|
| 1164 | + /** |
|
| 1165 | + * Gets ticket quantity |
|
| 1166 | + * |
|
| 1167 | + * @param string $context ticket quantity is somewhat subjective depending on the exact information sought |
|
| 1168 | + * therefore $context can be one of two values: 'reg_limit', or 'saleable' |
|
| 1169 | + * REG LIMIT: caps qty based on DTT_reg_limit for ALL related datetimes |
|
| 1170 | + * SALEABLE: also considers datetime sold and returns zero if ANY DTT is sold out, and |
|
| 1171 | + * is therefore the truest measure of tickets that can be purchased at the moment |
|
| 1172 | + * @param int $DTT_ID the primary key for a particular datetime. |
|
| 1173 | + * set to 0 for all related datetimes |
|
| 1174 | + * @return int |
|
| 1175 | + * @throws EE_Error |
|
| 1176 | + * @throws ReflectionException |
|
| 1177 | + */ |
|
| 1178 | + public function real_quantity_on_ticket($context = 'reg_limit', $DTT_ID = 0) |
|
| 1179 | + { |
|
| 1180 | + $raw = $this->get_raw('TKT_qty'); |
|
| 1181 | + // return immediately if it's zero |
|
| 1182 | + if ($raw === 0) { |
|
| 1183 | + return $raw; |
|
| 1184 | + } |
|
| 1185 | + // echo "\n\n<br />Ticket: " . $this->name() . '<br />'; |
|
| 1186 | + // ensure qty doesn't exceed raw value for THIS ticket |
|
| 1187 | + $qty = min(EE_INF, $raw); |
|
| 1188 | + // echo "\n . qty: " . $qty . '<br />'; |
|
| 1189 | + // calculate this ticket's total sales and reservations |
|
| 1190 | + $sold_and_reserved_for_this_ticket = $this->sold() + $this->reserved(); |
|
| 1191 | + // echo "\n . sold: " . $this->sold() . '<br />'; |
|
| 1192 | + // echo "\n . reserved: " . $this->reserved() . '<br />'; |
|
| 1193 | + // echo "\n . sold_and_reserved_for_this_ticket: " . $sold_and_reserved_for_this_ticket . '<br />'; |
|
| 1194 | + // first we need to calculate the maximum number of tickets available for the datetime |
|
| 1195 | + // do we want data for one datetime or all of them ? |
|
| 1196 | + $query_params = $DTT_ID ? [['DTT_ID' => $DTT_ID]] : []; |
|
| 1197 | + $datetimes = $this->datetimes($query_params); |
|
| 1198 | + if (is_array($datetimes) && ! empty($datetimes)) { |
|
| 1199 | + foreach ($datetimes as $datetime) { |
|
| 1200 | + if ($datetime instanceof EE_Datetime) { |
|
| 1201 | + $datetime->refresh_from_db(); |
|
| 1202 | + // echo "\n . . datetime name: " . $datetime->name() . '<br />'; |
|
| 1203 | + // echo "\n . . datetime ID: " . $datetime->ID() . '<br />'; |
|
| 1204 | + // initialize with no restrictions for each datetime |
|
| 1205 | + // but adjust datetime qty based on datetime reg limit |
|
| 1206 | + $datetime_qty = min(EE_INF, $datetime->reg_limit()); |
|
| 1207 | + // echo "\n . . . datetime reg_limit: " . $datetime->reg_limit() . '<br />'; |
|
| 1208 | + // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />'; |
|
| 1209 | + // if we want the actual saleable amount, then we need to consider OTHER ticket sales |
|
| 1210 | + // and reservations for this datetime, that do NOT include sales and reservations |
|
| 1211 | + // for this ticket (so we add $this->sold() and $this->reserved() back in) |
|
| 1212 | + if ($context === 'saleable') { |
|
| 1213 | + $datetime_qty = max( |
|
| 1214 | + $datetime_qty - $datetime->sold_and_reserved() + $sold_and_reserved_for_this_ticket, |
|
| 1215 | + 0 |
|
| 1216 | + ); |
|
| 1217 | + // echo "\n . . . datetime sold: " . $datetime->sold() . '<br />'; |
|
| 1218 | + // echo "\n . . . datetime reserved: " . $datetime->reserved() . '<br />'; |
|
| 1219 | + // echo "\n . . . datetime sold_and_reserved: " . $datetime->sold_and_reserved() . '<br />'; |
|
| 1220 | + // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />'; |
|
| 1221 | + $datetime_qty = ! $datetime->sold_out() ? $datetime_qty : 0; |
|
| 1222 | + // echo "\n . . . datetime_qty: " . $datetime_qty . '<br />'; |
|
| 1223 | + } |
|
| 1224 | + $qty = min($datetime_qty, $qty); |
|
| 1225 | + // echo "\n . . qty: " . $qty . '<br />'; |
|
| 1226 | + } |
|
| 1227 | + } |
|
| 1228 | + } |
|
| 1229 | + // NOW that we know the maximum number of tickets available for the datetime |
|
| 1230 | + // we can finally factor in the details for this specific ticket |
|
| 1231 | + if ($qty > 0 && $context === 'saleable') { |
|
| 1232 | + // and subtract the sales for THIS ticket |
|
| 1233 | + $qty = max($qty - $sold_and_reserved_for_this_ticket, 0); |
|
| 1234 | + // echo "\n . qty: " . $qty . '<br />'; |
|
| 1235 | + } |
|
| 1236 | + // echo "\nFINAL QTY: " . $qty . "<br /><br />"; |
|
| 1237 | + return $qty; |
|
| 1238 | + } |
|
| 1239 | + |
|
| 1240 | + |
|
| 1241 | + /** |
|
| 1242 | + * Sets qty - IMPORTANT!!! Does NOT allow QTY to be set higher than the lowest reg limit of any related datetimes |
|
| 1243 | + * |
|
| 1244 | + * @param int $qty |
|
| 1245 | + * @return void |
|
| 1246 | + * @throws EE_Error |
|
| 1247 | + * @throws ReflectionException |
|
| 1248 | + */ |
|
| 1249 | + public function set_qty($qty) |
|
| 1250 | + { |
|
| 1251 | + $datetimes = $this->datetimes(); |
|
| 1252 | + foreach ($datetimes as $datetime) { |
|
| 1253 | + if ($datetime instanceof EE_Datetime) { |
|
| 1254 | + $qty = min($qty, $datetime->reg_limit()); |
|
| 1255 | + } |
|
| 1256 | + } |
|
| 1257 | + $this->set('TKT_qty', $qty); |
|
| 1258 | + } |
|
| 1259 | + |
|
| 1260 | + |
|
| 1261 | + /** |
|
| 1262 | + * Gets uses |
|
| 1263 | + * |
|
| 1264 | + * @return int |
|
| 1265 | + * @throws EE_Error |
|
| 1266 | + * @throws ReflectionException |
|
| 1267 | + */ |
|
| 1268 | + public function uses() |
|
| 1269 | + { |
|
| 1270 | + return $this->get('TKT_uses'); |
|
| 1271 | + } |
|
| 1272 | + |
|
| 1273 | + |
|
| 1274 | + /** |
|
| 1275 | + * Sets uses |
|
| 1276 | + * |
|
| 1277 | + * @param int $uses |
|
| 1278 | + * @return void |
|
| 1279 | + * @throws EE_Error |
|
| 1280 | + * @throws ReflectionException |
|
| 1281 | + */ |
|
| 1282 | + public function set_uses($uses) |
|
| 1283 | + { |
|
| 1284 | + $this->set('TKT_uses', $uses); |
|
| 1285 | + } |
|
| 1286 | + |
|
| 1287 | + |
|
| 1288 | + /** |
|
| 1289 | + * returns whether ticket is required or not. |
|
| 1290 | + * |
|
| 1291 | + * @return boolean |
|
| 1292 | + * @throws EE_Error |
|
| 1293 | + * @throws ReflectionException |
|
| 1294 | + */ |
|
| 1295 | + public function required() |
|
| 1296 | + { |
|
| 1297 | + return $this->get('TKT_required'); |
|
| 1298 | + } |
|
| 1299 | + |
|
| 1300 | + |
|
| 1301 | + /** |
|
| 1302 | + * sets the TKT_required property |
|
| 1303 | + * |
|
| 1304 | + * @param boolean $required |
|
| 1305 | + * @return void |
|
| 1306 | + * @throws EE_Error |
|
| 1307 | + * @throws ReflectionException |
|
| 1308 | + */ |
|
| 1309 | + public function set_required($required) |
|
| 1310 | + { |
|
| 1311 | + $this->set('TKT_required', $required); |
|
| 1312 | + } |
|
| 1313 | + |
|
| 1314 | + |
|
| 1315 | + /** |
|
| 1316 | + * Gets taxable |
|
| 1317 | + * |
|
| 1318 | + * @return boolean |
|
| 1319 | + * @throws EE_Error |
|
| 1320 | + * @throws ReflectionException |
|
| 1321 | + */ |
|
| 1322 | + public function taxable() |
|
| 1323 | + { |
|
| 1324 | + return $this->get('TKT_taxable'); |
|
| 1325 | + } |
|
| 1326 | + |
|
| 1327 | + |
|
| 1328 | + /** |
|
| 1329 | + * Sets taxable |
|
| 1330 | + * |
|
| 1331 | + * @param boolean $taxable |
|
| 1332 | + * @return void |
|
| 1333 | + * @throws EE_Error |
|
| 1334 | + * @throws ReflectionException |
|
| 1335 | + */ |
|
| 1336 | + public function set_taxable($taxable) |
|
| 1337 | + { |
|
| 1338 | + $this->set('TKT_taxable', $taxable); |
|
| 1339 | + } |
|
| 1340 | + |
|
| 1341 | + |
|
| 1342 | + /** |
|
| 1343 | + * Gets is_default |
|
| 1344 | + * |
|
| 1345 | + * @return boolean |
|
| 1346 | + * @throws EE_Error |
|
| 1347 | + * @throws ReflectionException |
|
| 1348 | + */ |
|
| 1349 | + public function is_default() |
|
| 1350 | + { |
|
| 1351 | + return $this->get('TKT_is_default'); |
|
| 1352 | + } |
|
| 1353 | + |
|
| 1354 | + |
|
| 1355 | + /** |
|
| 1356 | + * Sets is_default |
|
| 1357 | + * |
|
| 1358 | + * @param boolean $is_default |
|
| 1359 | + * @return void |
|
| 1360 | + * @throws EE_Error |
|
| 1361 | + * @throws ReflectionException |
|
| 1362 | + */ |
|
| 1363 | + public function set_is_default($is_default) |
|
| 1364 | + { |
|
| 1365 | + $this->set('TKT_is_default', $is_default); |
|
| 1366 | + } |
|
| 1367 | + |
|
| 1368 | + |
|
| 1369 | + /** |
|
| 1370 | + * Gets order |
|
| 1371 | + * |
|
| 1372 | + * @return int |
|
| 1373 | + * @throws EE_Error |
|
| 1374 | + * @throws ReflectionException |
|
| 1375 | + */ |
|
| 1376 | + public function order() |
|
| 1377 | + { |
|
| 1378 | + return $this->get('TKT_order'); |
|
| 1379 | + } |
|
| 1380 | + |
|
| 1381 | + |
|
| 1382 | + /** |
|
| 1383 | + * Sets order |
|
| 1384 | + * |
|
| 1385 | + * @param int $order |
|
| 1386 | + * @return void |
|
| 1387 | + * @throws EE_Error |
|
| 1388 | + * @throws ReflectionException |
|
| 1389 | + */ |
|
| 1390 | + public function set_order($order) |
|
| 1391 | + { |
|
| 1392 | + $this->set('TKT_order', $order); |
|
| 1393 | + } |
|
| 1394 | + |
|
| 1395 | + |
|
| 1396 | + /** |
|
| 1397 | + * Gets row |
|
| 1398 | + * |
|
| 1399 | + * @return int |
|
| 1400 | + * @throws EE_Error |
|
| 1401 | + * @throws ReflectionException |
|
| 1402 | + */ |
|
| 1403 | + public function row() |
|
| 1404 | + { |
|
| 1405 | + return $this->get('TKT_row'); |
|
| 1406 | + } |
|
| 1407 | + |
|
| 1408 | + |
|
| 1409 | + /** |
|
| 1410 | + * Sets row |
|
| 1411 | + * |
|
| 1412 | + * @param int $row |
|
| 1413 | + * @return void |
|
| 1414 | + * @throws EE_Error |
|
| 1415 | + * @throws ReflectionException |
|
| 1416 | + */ |
|
| 1417 | + public function set_row($row) |
|
| 1418 | + { |
|
| 1419 | + $this->set('TKT_row', $row); |
|
| 1420 | + } |
|
| 1421 | + |
|
| 1422 | + |
|
| 1423 | + /** |
|
| 1424 | + * Gets deleted |
|
| 1425 | + * |
|
| 1426 | + * @return boolean |
|
| 1427 | + * @throws EE_Error |
|
| 1428 | + * @throws ReflectionException |
|
| 1429 | + */ |
|
| 1430 | + public function deleted() |
|
| 1431 | + { |
|
| 1432 | + return $this->get('TKT_deleted'); |
|
| 1433 | + } |
|
| 1434 | + |
|
| 1435 | + |
|
| 1436 | + /** |
|
| 1437 | + * Sets deleted |
|
| 1438 | + * |
|
| 1439 | + * @param boolean $deleted |
|
| 1440 | + * @return void |
|
| 1441 | + * @throws EE_Error |
|
| 1442 | + * @throws ReflectionException |
|
| 1443 | + */ |
|
| 1444 | + public function set_deleted($deleted) |
|
| 1445 | + { |
|
| 1446 | + $this->set('TKT_deleted', $deleted); |
|
| 1447 | + } |
|
| 1448 | + |
|
| 1449 | + |
|
| 1450 | + /** |
|
| 1451 | + * Gets parent |
|
| 1452 | + * |
|
| 1453 | + * @return int |
|
| 1454 | + * @throws EE_Error |
|
| 1455 | + * @throws ReflectionException |
|
| 1456 | + */ |
|
| 1457 | + public function parent_ID() |
|
| 1458 | + { |
|
| 1459 | + return $this->get('TKT_parent'); |
|
| 1460 | + } |
|
| 1461 | + |
|
| 1462 | + |
|
| 1463 | + /** |
|
| 1464 | + * Sets parent |
|
| 1465 | + * |
|
| 1466 | + * @param int $parent |
|
| 1467 | + * @return void |
|
| 1468 | + * @throws EE_Error |
|
| 1469 | + * @throws ReflectionException |
|
| 1470 | + */ |
|
| 1471 | + public function set_parent_ID($parent) |
|
| 1472 | + { |
|
| 1473 | + $this->set('TKT_parent', $parent); |
|
| 1474 | + } |
|
| 1475 | + |
|
| 1476 | + |
|
| 1477 | + /** |
|
| 1478 | + * @return boolean |
|
| 1479 | + * @throws EE_Error |
|
| 1480 | + * @throws InvalidArgumentException |
|
| 1481 | + * @throws InvalidDataTypeException |
|
| 1482 | + * @throws InvalidInterfaceException |
|
| 1483 | + * @throws ReflectionException |
|
| 1484 | + */ |
|
| 1485 | + public function reverse_calculate() |
|
| 1486 | + { |
|
| 1487 | + return $this->get('TKT_reverse_calculate'); |
|
| 1488 | + } |
|
| 1489 | + |
|
| 1490 | + |
|
| 1491 | + /** |
|
| 1492 | + * @param boolean $reverse_calculate |
|
| 1493 | + * @throws EE_Error |
|
| 1494 | + * @throws InvalidArgumentException |
|
| 1495 | + * @throws InvalidDataTypeException |
|
| 1496 | + * @throws InvalidInterfaceException |
|
| 1497 | + * @throws ReflectionException |
|
| 1498 | + */ |
|
| 1499 | + public function set_reverse_calculate($reverse_calculate) |
|
| 1500 | + { |
|
| 1501 | + $this->set('TKT_reverse_calculate', $reverse_calculate); |
|
| 1502 | + } |
|
| 1503 | + |
|
| 1504 | + |
|
| 1505 | + /** |
|
| 1506 | + * Gets a string which is handy for showing in gateways etc that describes the ticket. |
|
| 1507 | + * |
|
| 1508 | + * @return string |
|
| 1509 | + * @throws EE_Error |
|
| 1510 | + * @throws ReflectionException |
|
| 1511 | + */ |
|
| 1512 | + public function name_and_info() |
|
| 1513 | + { |
|
| 1514 | + $times = []; |
|
| 1515 | + foreach ($this->datetimes() as $datetime) { |
|
| 1516 | + $times[] = $datetime->start_date_and_time(); |
|
| 1517 | + } |
|
| 1518 | + return $this->name() . ' @ ' . implode(', ', $times) . ' for ' . $this->pretty_price(); |
|
| 1519 | + } |
|
| 1520 | + |
|
| 1521 | + |
|
| 1522 | + /** |
|
| 1523 | + * Gets name |
|
| 1524 | + * |
|
| 1525 | + * @return string |
|
| 1526 | + * @throws EE_Error |
|
| 1527 | + * @throws ReflectionException |
|
| 1528 | + */ |
|
| 1529 | + public function name() |
|
| 1530 | + { |
|
| 1531 | + return $this->get('TKT_name'); |
|
| 1532 | + } |
|
| 1533 | + |
|
| 1534 | + |
|
| 1535 | + /** |
|
| 1536 | + * Gets price |
|
| 1537 | + * |
|
| 1538 | + * @return float |
|
| 1539 | + * @throws EE_Error |
|
| 1540 | + * @throws ReflectionException |
|
| 1541 | + */ |
|
| 1542 | + public function price() |
|
| 1543 | + { |
|
| 1544 | + return $this->get('TKT_price'); |
|
| 1545 | + } |
|
| 1546 | + |
|
| 1547 | + |
|
| 1548 | + /** |
|
| 1549 | + * Gets all the registrations for this ticket |
|
| 1550 | + * |
|
| 1551 | + * @param array $query_params @see |
|
| 1552 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1553 | + * @return EE_Registration[]|EE_Base_Class[] |
|
| 1554 | + * @throws EE_Error |
|
| 1555 | + * @throws ReflectionException |
|
| 1556 | + */ |
|
| 1557 | + public function registrations($query_params = []) |
|
| 1558 | + { |
|
| 1559 | + return $this->get_many_related('Registration', $query_params); |
|
| 1560 | + } |
|
| 1561 | + |
|
| 1562 | + |
|
| 1563 | + /** |
|
| 1564 | + * Updates the TKT_sold attribute (and saves) based on the number of APPROVED registrations for this ticket. |
|
| 1565 | + * |
|
| 1566 | + * @return int |
|
| 1567 | + * @throws EE_Error |
|
| 1568 | + * @throws ReflectionException |
|
| 1569 | + */ |
|
| 1570 | + public function update_tickets_sold() |
|
| 1571 | + { |
|
| 1572 | + $count_regs_for_this_ticket = $this->count_registrations( |
|
| 1573 | + [ |
|
| 1574 | + [ |
|
| 1575 | + 'STS_ID' => EEM_Registration::status_id_approved, |
|
| 1576 | + 'REG_deleted' => 0, |
|
| 1577 | + ], |
|
| 1578 | + ] |
|
| 1579 | + ); |
|
| 1580 | + $this->set_sold($count_regs_for_this_ticket); |
|
| 1581 | + $this->save(); |
|
| 1582 | + return $count_regs_for_this_ticket; |
|
| 1583 | + } |
|
| 1584 | + |
|
| 1585 | + |
|
| 1586 | + /** |
|
| 1587 | + * Counts the registrations for this ticket |
|
| 1588 | + * |
|
| 1589 | + * @param array $query_params @see |
|
| 1590 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md |
|
| 1591 | + * @return int |
|
| 1592 | + * @throws EE_Error |
|
| 1593 | + * @throws ReflectionException |
|
| 1594 | + */ |
|
| 1595 | + public function count_registrations($query_params = []) |
|
| 1596 | + { |
|
| 1597 | + return $this->count_related('Registration', $query_params); |
|
| 1598 | + } |
|
| 1599 | + |
|
| 1600 | + |
|
| 1601 | + /** |
|
| 1602 | + * Implementation for EEI_Has_Icon interface method. |
|
| 1603 | + * |
|
| 1604 | + * @return string |
|
| 1605 | + * @see EEI_Visual_Representation for comments |
|
| 1606 | + */ |
|
| 1607 | + public function get_icon() |
|
| 1608 | + { |
|
| 1609 | + return '<span class="dashicons dashicons-tickets-alt"/>'; |
|
| 1610 | + } |
|
| 1611 | + |
|
| 1612 | + |
|
| 1613 | + /** |
|
| 1614 | + * Implementation of the EEI_Event_Relation interface method |
|
| 1615 | + * |
|
| 1616 | + * @return EE_Event |
|
| 1617 | + * @throws EE_Error |
|
| 1618 | + * @throws UnexpectedEntityException |
|
| 1619 | + * @throws ReflectionException |
|
| 1620 | + * @see EEI_Event_Relation for comments |
|
| 1621 | + */ |
|
| 1622 | + public function get_related_event() |
|
| 1623 | + { |
|
| 1624 | + // get one datetime to use for getting the event |
|
| 1625 | + $datetime = $this->first_datetime(); |
|
| 1626 | + if (! $datetime instanceof EE_Datetime) { |
|
| 1627 | + throw new UnexpectedEntityException( |
|
| 1628 | + $datetime, |
|
| 1629 | + 'EE_Datetime', |
|
| 1630 | + sprintf( |
|
| 1631 | + __('The ticket (%s) is not associated with any valid datetimes.', 'event_espresso'), |
|
| 1632 | + $this->name() |
|
| 1633 | + ) |
|
| 1634 | + ); |
|
| 1635 | + } |
|
| 1636 | + $event = $datetime->event(); |
|
| 1637 | + if (! $event instanceof EE_Event) { |
|
| 1638 | + throw new UnexpectedEntityException( |
|
| 1639 | + $event, |
|
| 1640 | + 'EE_Event', |
|
| 1641 | + sprintf( |
|
| 1642 | + __('The ticket (%s) is not associated with a valid event.', 'event_espresso'), |
|
| 1643 | + $this->name() |
|
| 1644 | + ) |
|
| 1645 | + ); |
|
| 1646 | + } |
|
| 1647 | + return $event; |
|
| 1648 | + } |
|
| 1649 | + |
|
| 1650 | + |
|
| 1651 | + /** |
|
| 1652 | + * Implementation of the EEI_Event_Relation interface method |
|
| 1653 | + * |
|
| 1654 | + * @return string |
|
| 1655 | + * @throws UnexpectedEntityException |
|
| 1656 | + * @throws EE_Error |
|
| 1657 | + * @throws ReflectionException |
|
| 1658 | + * @see EEI_Event_Relation for comments |
|
| 1659 | + */ |
|
| 1660 | + public function get_event_name() |
|
| 1661 | + { |
|
| 1662 | + $event = $this->get_related_event(); |
|
| 1663 | + return $event instanceof EE_Event ? $event->name() : ''; |
|
| 1664 | + } |
|
| 1665 | + |
|
| 1666 | + |
|
| 1667 | + /** |
|
| 1668 | + * Implementation of the EEI_Event_Relation interface method |
|
| 1669 | + * |
|
| 1670 | + * @return int |
|
| 1671 | + * @throws UnexpectedEntityException |
|
| 1672 | + * @throws EE_Error |
|
| 1673 | + * @throws ReflectionException |
|
| 1674 | + * @see EEI_Event_Relation for comments |
|
| 1675 | + */ |
|
| 1676 | + public function get_event_ID() |
|
| 1677 | + { |
|
| 1678 | + $event = $this->get_related_event(); |
|
| 1679 | + return $event instanceof EE_Event ? $event->ID() : 0; |
|
| 1680 | + } |
|
| 1681 | + |
|
| 1682 | + |
|
| 1683 | + /** |
|
| 1684 | + * This simply returns whether a ticket can be permanently deleted or not. |
|
| 1685 | + * The criteria for determining this is whether the ticket has any related registrations. |
|
| 1686 | + * If there are none then it can be permanently deleted. |
|
| 1687 | + * |
|
| 1688 | + * @return bool |
|
| 1689 | + * @throws EE_Error |
|
| 1690 | + * @throws ReflectionException |
|
| 1691 | + */ |
|
| 1692 | + public function is_permanently_deleteable() |
|
| 1693 | + { |
|
| 1694 | + return $this->count_registrations() === 0; |
|
| 1695 | + } |
|
| 1696 | + |
|
| 1697 | + |
|
| 1698 | + /** |
|
| 1699 | + * @return int |
|
| 1700 | + * @throws EE_Error |
|
| 1701 | + * @throws ReflectionException |
|
| 1702 | + * @since $VID:$ |
|
| 1703 | + */ |
|
| 1704 | + public function visibility(): int |
|
| 1705 | + { |
|
| 1706 | + return $this->get('TKT_visibility'); |
|
| 1707 | + } |
|
| 1708 | + |
|
| 1709 | + |
|
| 1710 | + /** |
|
| 1711 | + * @return int |
|
| 1712 | + * @throws EE_Error |
|
| 1713 | + * @throws ReflectionException |
|
| 1714 | + * @since $VID:$ |
|
| 1715 | + */ |
|
| 1716 | + public function isHidden(): int |
|
| 1717 | + { |
|
| 1718 | + return $this->visibility() === EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE; |
|
| 1719 | + } |
|
| 1720 | + |
|
| 1721 | + |
|
| 1722 | + /** |
|
| 1723 | + * @return int |
|
| 1724 | + * @throws EE_Error |
|
| 1725 | + * @throws ReflectionException |
|
| 1726 | + * @since $VID:$ |
|
| 1727 | + */ |
|
| 1728 | + public function isNotHidden(): int |
|
| 1729 | + { |
|
| 1730 | + return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_NONE_VALUE; |
|
| 1731 | + } |
|
| 1732 | + |
|
| 1733 | + |
|
| 1734 | + /** |
|
| 1735 | + * @return int |
|
| 1736 | + * @throws EE_Error |
|
| 1737 | + * @throws ReflectionException |
|
| 1738 | + * @since $VID:$ |
|
| 1739 | + */ |
|
| 1740 | + public function isPublicOnly(): int |
|
| 1741 | + { |
|
| 1742 | + return $this->isNotHidden() && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE; |
|
| 1743 | + } |
|
| 1744 | + |
|
| 1745 | + |
|
| 1746 | + /** |
|
| 1747 | + * @return int |
|
| 1748 | + * @throws EE_Error |
|
| 1749 | + * @throws ReflectionException |
|
| 1750 | + * @since $VID:$ |
|
| 1751 | + */ |
|
| 1752 | + public function isMembersOnly(): int |
|
| 1753 | + { |
|
| 1754 | + return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_PUBLIC_VALUE |
|
| 1755 | + && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE; |
|
| 1756 | + } |
|
| 1757 | + |
|
| 1758 | + |
|
| 1759 | + /** |
|
| 1760 | + * @return int |
|
| 1761 | + * @throws EE_Error |
|
| 1762 | + * @throws ReflectionException |
|
| 1763 | + * @since $VID:$ |
|
| 1764 | + */ |
|
| 1765 | + public function isAdminsOnly(): int |
|
| 1766 | + { |
|
| 1767 | + return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_MEMBERS_ONLY_VALUE |
|
| 1768 | + && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE; |
|
| 1769 | + } |
|
| 1770 | + |
|
| 1771 | + |
|
| 1772 | + /** |
|
| 1773 | + * @return int |
|
| 1774 | + * @throws EE_Error |
|
| 1775 | + * @throws ReflectionException |
|
| 1776 | + * @since $VID:$ |
|
| 1777 | + */ |
|
| 1778 | + public function isAdminUiOnly(): int |
|
| 1779 | + { |
|
| 1780 | + return $this->visibility() > EEM_Ticket::TICKET_VISIBILITY_ADMINS_ONLY_VALUE |
|
| 1781 | + && $this->visibility() <= EEM_Ticket::TICKET_VISIBILITY_ADMIN_UI_ONLY_VALUE; |
|
| 1782 | + } |
|
| 1783 | + |
|
| 1784 | + |
|
| 1785 | + /** |
|
| 1786 | + * @param int $visibility |
|
| 1787 | + * @throws EE_Error |
|
| 1788 | + * @throws ReflectionException |
|
| 1789 | + * @since $VID:$ |
|
| 1790 | + */ |
|
| 1791 | + public function set_visibility(int $visibility) |
|
| 1792 | + { |
|
| 1793 | + |
|
| 1794 | + $ticket_visibility_options = $this->_model->ticketVisibilityOptions(); |
|
| 1795 | + $ticket_visibility = -1; |
|
| 1796 | + foreach ($ticket_visibility_options as $ticket_visibility_option) { |
|
| 1797 | + if ($visibility === $ticket_visibility_option) { |
|
| 1798 | + $ticket_visibility = $visibility; |
|
| 1799 | + } |
|
| 1800 | + } |
|
| 1801 | + if ($ticket_visibility === -1) { |
|
| 1802 | + throw new DomainException( |
|
| 1803 | + sprintf( |
|
| 1804 | + esc_html__( |
|
| 1805 | + 'The supplied ticket visibility setting of "%1$s" is not valid. It needs to match one of the keys in the following array:%2$s %3$s ', |
|
| 1806 | + 'event_espresso' |
|
| 1807 | + ), |
|
| 1808 | + $visibility, |
|
| 1809 | + '<br />', |
|
| 1810 | + var_export($ticket_visibility_options, true) |
|
| 1811 | + ) |
|
| 1812 | + ); |
|
| 1813 | + } |
|
| 1814 | + $this->set('TKT_visibility', $ticket_visibility); |
|
| 1815 | + } |
|
| 1816 | + |
|
| 1817 | + |
|
| 1818 | + /******************************************************************* |
|
| 1819 | 1819 | *********************** DEPRECATED METHODS ********************** |
| 1820 | 1820 | *******************************************************************/ |
| 1821 | 1821 | |
| 1822 | 1822 | |
| 1823 | - /** |
|
| 1824 | - * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its |
|
| 1825 | - * associated datetimes. |
|
| 1826 | - * |
|
| 1827 | - * @param int $qty |
|
| 1828 | - * @return void |
|
| 1829 | - * @throws EE_Error |
|
| 1830 | - * @throws InvalidArgumentException |
|
| 1831 | - * @throws InvalidDataTypeException |
|
| 1832 | - * @throws InvalidInterfaceException |
|
| 1833 | - * @throws ReflectionException |
|
| 1834 | - * @deprecated 4.9.80.p |
|
| 1835 | - */ |
|
| 1836 | - public function increase_sold($qty = 1) |
|
| 1837 | - { |
|
| 1838 | - EE_Error::doing_it_wrong( |
|
| 1839 | - __FUNCTION__, |
|
| 1840 | - esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'), |
|
| 1841 | - '4.9.80.p', |
|
| 1842 | - '5.0.0.p' |
|
| 1843 | - ); |
|
| 1844 | - $this->increaseSold($qty); |
|
| 1845 | - } |
|
| 1846 | - |
|
| 1847 | - |
|
| 1848 | - /** |
|
| 1849 | - * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty. |
|
| 1850 | - * |
|
| 1851 | - * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts), |
|
| 1852 | - * Negative means to decreases old counts (and increase reserved counts). |
|
| 1853 | - * @throws EE_Error |
|
| 1854 | - * @throws InvalidArgumentException |
|
| 1855 | - * @throws InvalidDataTypeException |
|
| 1856 | - * @throws InvalidInterfaceException |
|
| 1857 | - * @throws ReflectionException |
|
| 1858 | - * @deprecated 4.9.80.p |
|
| 1859 | - */ |
|
| 1860 | - protected function _increase_sold_for_datetimes($qty) |
|
| 1861 | - { |
|
| 1862 | - EE_Error::doing_it_wrong( |
|
| 1863 | - __FUNCTION__, |
|
| 1864 | - esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'), |
|
| 1865 | - '4.9.80.p', |
|
| 1866 | - '5.0.0.p' |
|
| 1867 | - ); |
|
| 1868 | - $this->increaseSoldForDatetimes($qty); |
|
| 1869 | - } |
|
| 1870 | - |
|
| 1871 | - |
|
| 1872 | - /** |
|
| 1873 | - * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the |
|
| 1874 | - * DB and then updates the model objects. |
|
| 1875 | - * Does not affect the reserved counts. |
|
| 1876 | - * |
|
| 1877 | - * @param int $qty |
|
| 1878 | - * @return void |
|
| 1879 | - * @throws EE_Error |
|
| 1880 | - * @throws InvalidArgumentException |
|
| 1881 | - * @throws InvalidDataTypeException |
|
| 1882 | - * @throws InvalidInterfaceException |
|
| 1883 | - * @throws ReflectionException |
|
| 1884 | - * @deprecated 4.9.80.p |
|
| 1885 | - */ |
|
| 1886 | - public function decrease_sold($qty = 1) |
|
| 1887 | - { |
|
| 1888 | - EE_Error::doing_it_wrong( |
|
| 1889 | - __FUNCTION__, |
|
| 1890 | - esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'), |
|
| 1891 | - '4.9.80.p', |
|
| 1892 | - '5.0.0.p' |
|
| 1893 | - ); |
|
| 1894 | - $this->decreaseSold($qty); |
|
| 1895 | - } |
|
| 1896 | - |
|
| 1897 | - |
|
| 1898 | - /** |
|
| 1899 | - * Decreases sold on related datetimes |
|
| 1900 | - * |
|
| 1901 | - * @param int $qty |
|
| 1902 | - * @return void |
|
| 1903 | - * @throws EE_Error |
|
| 1904 | - * @throws InvalidArgumentException |
|
| 1905 | - * @throws InvalidDataTypeException |
|
| 1906 | - * @throws InvalidInterfaceException |
|
| 1907 | - * @throws ReflectionException |
|
| 1908 | - * @deprecated 4.9.80.p |
|
| 1909 | - */ |
|
| 1910 | - protected function _decrease_sold_for_datetimes($qty = 1) |
|
| 1911 | - { |
|
| 1912 | - EE_Error::doing_it_wrong( |
|
| 1913 | - __FUNCTION__, |
|
| 1914 | - esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'), |
|
| 1915 | - '4.9.80.p', |
|
| 1916 | - '5.0.0.p' |
|
| 1917 | - ); |
|
| 1918 | - $this->decreaseSoldForDatetimes($qty); |
|
| 1919 | - } |
|
| 1920 | - |
|
| 1921 | - |
|
| 1922 | - /** |
|
| 1923 | - * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 1924 | - * |
|
| 1925 | - * @param int $qty |
|
| 1926 | - * @param string $source |
|
| 1927 | - * @return bool whether we successfully reserved the ticket or not. |
|
| 1928 | - * @throws EE_Error |
|
| 1929 | - * @throws InvalidArgumentException |
|
| 1930 | - * @throws ReflectionException |
|
| 1931 | - * @throws InvalidDataTypeException |
|
| 1932 | - * @throws InvalidInterfaceException |
|
| 1933 | - * @deprecated 4.9.80.p |
|
| 1934 | - */ |
|
| 1935 | - public function increase_reserved($qty = 1, $source = 'unknown') |
|
| 1936 | - { |
|
| 1937 | - EE_Error::doing_it_wrong( |
|
| 1938 | - __FUNCTION__, |
|
| 1939 | - esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'), |
|
| 1940 | - '4.9.80.p', |
|
| 1941 | - '5.0.0.p' |
|
| 1942 | - ); |
|
| 1943 | - return $this->increaseReserved($qty); |
|
| 1944 | - } |
|
| 1945 | - |
|
| 1946 | - |
|
| 1947 | - /** |
|
| 1948 | - * Increases sold on related datetimes |
|
| 1949 | - * |
|
| 1950 | - * @param int $qty |
|
| 1951 | - * @return boolean indicating success |
|
| 1952 | - * @throws EE_Error |
|
| 1953 | - * @throws InvalidArgumentException |
|
| 1954 | - * @throws InvalidDataTypeException |
|
| 1955 | - * @throws InvalidInterfaceException |
|
| 1956 | - * @throws ReflectionException |
|
| 1957 | - * @deprecated 4.9.80.p |
|
| 1958 | - */ |
|
| 1959 | - protected function _increase_reserved_for_datetimes($qty = 1) |
|
| 1960 | - { |
|
| 1961 | - EE_Error::doing_it_wrong( |
|
| 1962 | - __FUNCTION__, |
|
| 1963 | - esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'), |
|
| 1964 | - '4.9.80.p', |
|
| 1965 | - '5.0.0.p' |
|
| 1966 | - ); |
|
| 1967 | - return $this->increaseReservedForDatetimes($qty); |
|
| 1968 | - } |
|
| 1969 | - |
|
| 1970 | - |
|
| 1971 | - /** |
|
| 1972 | - * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 1973 | - * |
|
| 1974 | - * @param int $qty |
|
| 1975 | - * @param bool $adjust_datetimes |
|
| 1976 | - * @param string $source |
|
| 1977 | - * @return void |
|
| 1978 | - * @throws EE_Error |
|
| 1979 | - * @throws InvalidArgumentException |
|
| 1980 | - * @throws ReflectionException |
|
| 1981 | - * @throws InvalidDataTypeException |
|
| 1982 | - * @throws InvalidInterfaceException |
|
| 1983 | - * @deprecated 4.9.80.p |
|
| 1984 | - */ |
|
| 1985 | - public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown') |
|
| 1986 | - { |
|
| 1987 | - EE_Error::doing_it_wrong( |
|
| 1988 | - __FUNCTION__, |
|
| 1989 | - esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'), |
|
| 1990 | - '4.9.80.p', |
|
| 1991 | - '5.0.0.p' |
|
| 1992 | - ); |
|
| 1993 | - $this->decreaseReserved($qty); |
|
| 1994 | - } |
|
| 1995 | - |
|
| 1996 | - |
|
| 1997 | - /** |
|
| 1998 | - * Decreases reserved on related datetimes |
|
| 1999 | - * |
|
| 2000 | - * @param int $qty |
|
| 2001 | - * @return void |
|
| 2002 | - * @throws EE_Error |
|
| 2003 | - * @throws InvalidArgumentException |
|
| 2004 | - * @throws ReflectionException |
|
| 2005 | - * @throws InvalidDataTypeException |
|
| 2006 | - * @throws InvalidInterfaceException |
|
| 2007 | - * @deprecated 4.9.80.p |
|
| 2008 | - */ |
|
| 2009 | - protected function _decrease_reserved_for_datetimes($qty = 1) |
|
| 2010 | - { |
|
| 2011 | - EE_Error::doing_it_wrong( |
|
| 2012 | - __FUNCTION__, |
|
| 2013 | - esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'), |
|
| 2014 | - '4.9.80.p', |
|
| 2015 | - '5.0.0.p' |
|
| 2016 | - ); |
|
| 2017 | - $this->decreaseReservedForDatetimes($qty); |
|
| 2018 | - } |
|
| 1823 | + /** |
|
| 1824 | + * Increments sold by amount passed by $qty AND decrements the reserved count on both this ticket and its |
|
| 1825 | + * associated datetimes. |
|
| 1826 | + * |
|
| 1827 | + * @param int $qty |
|
| 1828 | + * @return void |
|
| 1829 | + * @throws EE_Error |
|
| 1830 | + * @throws InvalidArgumentException |
|
| 1831 | + * @throws InvalidDataTypeException |
|
| 1832 | + * @throws InvalidInterfaceException |
|
| 1833 | + * @throws ReflectionException |
|
| 1834 | + * @deprecated 4.9.80.p |
|
| 1835 | + */ |
|
| 1836 | + public function increase_sold($qty = 1) |
|
| 1837 | + { |
|
| 1838 | + EE_Error::doing_it_wrong( |
|
| 1839 | + __FUNCTION__, |
|
| 1840 | + esc_html__('Please use EE_Ticket::increaseSold() instead', 'event_espresso'), |
|
| 1841 | + '4.9.80.p', |
|
| 1842 | + '5.0.0.p' |
|
| 1843 | + ); |
|
| 1844 | + $this->increaseSold($qty); |
|
| 1845 | + } |
|
| 1846 | + |
|
| 1847 | + |
|
| 1848 | + /** |
|
| 1849 | + * On each datetime related to this ticket, increases its sold count and decreases its reserved count by $qty. |
|
| 1850 | + * |
|
| 1851 | + * @param int $qty positive or negative. Positive means to increase sold counts (and decrease reserved counts), |
|
| 1852 | + * Negative means to decreases old counts (and increase reserved counts). |
|
| 1853 | + * @throws EE_Error |
|
| 1854 | + * @throws InvalidArgumentException |
|
| 1855 | + * @throws InvalidDataTypeException |
|
| 1856 | + * @throws InvalidInterfaceException |
|
| 1857 | + * @throws ReflectionException |
|
| 1858 | + * @deprecated 4.9.80.p |
|
| 1859 | + */ |
|
| 1860 | + protected function _increase_sold_for_datetimes($qty) |
|
| 1861 | + { |
|
| 1862 | + EE_Error::doing_it_wrong( |
|
| 1863 | + __FUNCTION__, |
|
| 1864 | + esc_html__('Please use EE_Ticket::increaseSoldForDatetimes() instead', 'event_espresso'), |
|
| 1865 | + '4.9.80.p', |
|
| 1866 | + '5.0.0.p' |
|
| 1867 | + ); |
|
| 1868 | + $this->increaseSoldForDatetimes($qty); |
|
| 1869 | + } |
|
| 1870 | + |
|
| 1871 | + |
|
| 1872 | + /** |
|
| 1873 | + * Decrements (subtracts) sold by amount passed by $qty on both the ticket and its related datetimes directly in the |
|
| 1874 | + * DB and then updates the model objects. |
|
| 1875 | + * Does not affect the reserved counts. |
|
| 1876 | + * |
|
| 1877 | + * @param int $qty |
|
| 1878 | + * @return void |
|
| 1879 | + * @throws EE_Error |
|
| 1880 | + * @throws InvalidArgumentException |
|
| 1881 | + * @throws InvalidDataTypeException |
|
| 1882 | + * @throws InvalidInterfaceException |
|
| 1883 | + * @throws ReflectionException |
|
| 1884 | + * @deprecated 4.9.80.p |
|
| 1885 | + */ |
|
| 1886 | + public function decrease_sold($qty = 1) |
|
| 1887 | + { |
|
| 1888 | + EE_Error::doing_it_wrong( |
|
| 1889 | + __FUNCTION__, |
|
| 1890 | + esc_html__('Please use EE_Ticket::decreaseSold() instead', 'event_espresso'), |
|
| 1891 | + '4.9.80.p', |
|
| 1892 | + '5.0.0.p' |
|
| 1893 | + ); |
|
| 1894 | + $this->decreaseSold($qty); |
|
| 1895 | + } |
|
| 1896 | + |
|
| 1897 | + |
|
| 1898 | + /** |
|
| 1899 | + * Decreases sold on related datetimes |
|
| 1900 | + * |
|
| 1901 | + * @param int $qty |
|
| 1902 | + * @return void |
|
| 1903 | + * @throws EE_Error |
|
| 1904 | + * @throws InvalidArgumentException |
|
| 1905 | + * @throws InvalidDataTypeException |
|
| 1906 | + * @throws InvalidInterfaceException |
|
| 1907 | + * @throws ReflectionException |
|
| 1908 | + * @deprecated 4.9.80.p |
|
| 1909 | + */ |
|
| 1910 | + protected function _decrease_sold_for_datetimes($qty = 1) |
|
| 1911 | + { |
|
| 1912 | + EE_Error::doing_it_wrong( |
|
| 1913 | + __FUNCTION__, |
|
| 1914 | + esc_html__('Please use EE_Ticket::decreaseSoldForDatetimes() instead', 'event_espresso'), |
|
| 1915 | + '4.9.80.p', |
|
| 1916 | + '5.0.0.p' |
|
| 1917 | + ); |
|
| 1918 | + $this->decreaseSoldForDatetimes($qty); |
|
| 1919 | + } |
|
| 1920 | + |
|
| 1921 | + |
|
| 1922 | + /** |
|
| 1923 | + * Increments reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 1924 | + * |
|
| 1925 | + * @param int $qty |
|
| 1926 | + * @param string $source |
|
| 1927 | + * @return bool whether we successfully reserved the ticket or not. |
|
| 1928 | + * @throws EE_Error |
|
| 1929 | + * @throws InvalidArgumentException |
|
| 1930 | + * @throws ReflectionException |
|
| 1931 | + * @throws InvalidDataTypeException |
|
| 1932 | + * @throws InvalidInterfaceException |
|
| 1933 | + * @deprecated 4.9.80.p |
|
| 1934 | + */ |
|
| 1935 | + public function increase_reserved($qty = 1, $source = 'unknown') |
|
| 1936 | + { |
|
| 1937 | + EE_Error::doing_it_wrong( |
|
| 1938 | + __FUNCTION__, |
|
| 1939 | + esc_html__('Please use EE_Ticket::increaseReserved() instead', 'event_espresso'), |
|
| 1940 | + '4.9.80.p', |
|
| 1941 | + '5.0.0.p' |
|
| 1942 | + ); |
|
| 1943 | + return $this->increaseReserved($qty); |
|
| 1944 | + } |
|
| 1945 | + |
|
| 1946 | + |
|
| 1947 | + /** |
|
| 1948 | + * Increases sold on related datetimes |
|
| 1949 | + * |
|
| 1950 | + * @param int $qty |
|
| 1951 | + * @return boolean indicating success |
|
| 1952 | + * @throws EE_Error |
|
| 1953 | + * @throws InvalidArgumentException |
|
| 1954 | + * @throws InvalidDataTypeException |
|
| 1955 | + * @throws InvalidInterfaceException |
|
| 1956 | + * @throws ReflectionException |
|
| 1957 | + * @deprecated 4.9.80.p |
|
| 1958 | + */ |
|
| 1959 | + protected function _increase_reserved_for_datetimes($qty = 1) |
|
| 1960 | + { |
|
| 1961 | + EE_Error::doing_it_wrong( |
|
| 1962 | + __FUNCTION__, |
|
| 1963 | + esc_html__('Please use EE_Ticket::increaseReservedForDatetimes() instead', 'event_espresso'), |
|
| 1964 | + '4.9.80.p', |
|
| 1965 | + '5.0.0.p' |
|
| 1966 | + ); |
|
| 1967 | + return $this->increaseReservedForDatetimes($qty); |
|
| 1968 | + } |
|
| 1969 | + |
|
| 1970 | + |
|
| 1971 | + /** |
|
| 1972 | + * Decrements (subtracts) reserved by amount passed by $qty, and persists it immediately to the database. |
|
| 1973 | + * |
|
| 1974 | + * @param int $qty |
|
| 1975 | + * @param bool $adjust_datetimes |
|
| 1976 | + * @param string $source |
|
| 1977 | + * @return void |
|
| 1978 | + * @throws EE_Error |
|
| 1979 | + * @throws InvalidArgumentException |
|
| 1980 | + * @throws ReflectionException |
|
| 1981 | + * @throws InvalidDataTypeException |
|
| 1982 | + * @throws InvalidInterfaceException |
|
| 1983 | + * @deprecated 4.9.80.p |
|
| 1984 | + */ |
|
| 1985 | + public function decrease_reserved($qty = 1, $adjust_datetimes = true, $source = 'unknown') |
|
| 1986 | + { |
|
| 1987 | + EE_Error::doing_it_wrong( |
|
| 1988 | + __FUNCTION__, |
|
| 1989 | + esc_html__('Please use EE_Ticket::decreaseReserved() instead', 'event_espresso'), |
|
| 1990 | + '4.9.80.p', |
|
| 1991 | + '5.0.0.p' |
|
| 1992 | + ); |
|
| 1993 | + $this->decreaseReserved($qty); |
|
| 1994 | + } |
|
| 1995 | + |
|
| 1996 | + |
|
| 1997 | + /** |
|
| 1998 | + * Decreases reserved on related datetimes |
|
| 1999 | + * |
|
| 2000 | + * @param int $qty |
|
| 2001 | + * @return void |
|
| 2002 | + * @throws EE_Error |
|
| 2003 | + * @throws InvalidArgumentException |
|
| 2004 | + * @throws ReflectionException |
|
| 2005 | + * @throws InvalidDataTypeException |
|
| 2006 | + * @throws InvalidInterfaceException |
|
| 2007 | + * @deprecated 4.9.80.p |
|
| 2008 | + */ |
|
| 2009 | + protected function _decrease_reserved_for_datetimes($qty = 1) |
|
| 2010 | + { |
|
| 2011 | + EE_Error::doing_it_wrong( |
|
| 2012 | + __FUNCTION__, |
|
| 2013 | + esc_html__('Please use EE_Ticket::decreaseReservedForDatetimes() instead', 'event_espresso'), |
|
| 2014 | + '4.9.80.p', |
|
| 2015 | + '5.0.0.p' |
|
| 2016 | + ); |
|
| 2017 | + $this->decreaseReservedForDatetimes($qty); |
|
| 2018 | + } |
|
| 2019 | 2019 | } |
@@ -11,580 +11,580 @@ |
||
| 11 | 11 | class EE_Payment_Method extends EE_Base_Class |
| 12 | 12 | { |
| 13 | 13 | |
| 14 | - /** |
|
| 15 | - * Payment Method type object, which has all the info about this type of payment method, |
|
| 16 | - * including functions for processing payments, to get settings forms, etc. |
|
| 17 | - * |
|
| 18 | - * @var EE_PMT_Base |
|
| 19 | - */ |
|
| 20 | - protected $_type_obj; |
|
| 21 | - |
|
| 22 | - |
|
| 23 | - /** |
|
| 24 | - * @param array $props_n_values |
|
| 25 | - * @return EE_Payment_Method |
|
| 26 | - * @throws \EE_Error |
|
| 27 | - */ |
|
| 28 | - public static function new_instance($props_n_values = array()) |
|
| 29 | - { |
|
| 30 | - $has_object = parent::_check_for_object($props_n_values, __CLASS__); |
|
| 31 | - return $has_object ? $has_object : new self($props_n_values, false); |
|
| 32 | - } |
|
| 33 | - |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * @param array $props_n_values |
|
| 37 | - * @return EE_Payment_Method |
|
| 38 | - * @throws \EE_Error |
|
| 39 | - */ |
|
| 40 | - public static function new_instance_from_db($props_n_values = array()) |
|
| 41 | - { |
|
| 42 | - return new self($props_n_values, true); |
|
| 43 | - } |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - |
|
| 47 | - /** |
|
| 48 | - * Checks if there is a payment method class of the given 'PMD_type', and if so returns the classname. |
|
| 49 | - * Otherwise returns a normal EE_Payment_Method |
|
| 50 | - * |
|
| 51 | - * @param array $props_n_values where 'PMD_type' is a gateway name like 'Paypal_Standard','Invoice',etc (basically |
|
| 52 | - * the classname minus 'EEPM_') |
|
| 53 | - * @return string |
|
| 54 | - */ |
|
| 55 | - // private static function _payment_method_type($props_n_values) |
|
| 56 | - // { |
|
| 57 | - // EE_Registry::instance()->load_lib('Payment_Method_Manager'); |
|
| 58 | - // $type_string = isset($props_n_values['PMD_type']) ? $props_n_values['PMD_type'] : null; |
|
| 59 | - // if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($type_string)) { |
|
| 60 | - // return 'EEPM_' . $type_string; |
|
| 61 | - // } else { |
|
| 62 | - // return __CLASS__; |
|
| 63 | - // } |
|
| 64 | - // } |
|
| 65 | - |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * Gets whether this payment method can be used anywhere at all (ie frontend cart, admin, etc) |
|
| 69 | - * |
|
| 70 | - * @return boolean |
|
| 71 | - */ |
|
| 72 | - public function active() |
|
| 73 | - { |
|
| 74 | - return array_intersect(array_keys(EEM_Payment_Method::instance()->scopes()), $this->scope()); |
|
| 75 | - } |
|
| 76 | - |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * Sets this PM as active by making it usable within the CART scope. Offline gateways |
|
| 80 | - * are also usable from the admin-scope as well. DOES NOT SAVE it |
|
| 81 | - * |
|
| 82 | - * @throws \EE_Error |
|
| 83 | - */ |
|
| 84 | - public function set_active() |
|
| 85 | - { |
|
| 86 | - $default_scopes = array(EEM_Payment_Method::scope_cart); |
|
| 87 | - if ( |
|
| 88 | - $this->type_obj() && |
|
| 89 | - $this->type_obj()->payment_occurs() === EE_PMT_Base::offline |
|
| 90 | - ) { |
|
| 91 | - $default_scopes[] = EEM_Payment_Method::scope_admin; |
|
| 92 | - } |
|
| 93 | - $this->set_scope($default_scopes); |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - |
|
| 97 | - /** |
|
| 98 | - * Makes this payment method apply to NO scopes at all. DOES NOT SAVE it. |
|
| 99 | - */ |
|
| 100 | - public function deactivate() |
|
| 101 | - { |
|
| 102 | - $this->set_scope(array()); |
|
| 103 | - } |
|
| 104 | - |
|
| 105 | - |
|
| 106 | - /** |
|
| 107 | - * Gets button_url |
|
| 108 | - * |
|
| 109 | - * @return string |
|
| 110 | - */ |
|
| 111 | - public function button_url() |
|
| 112 | - { |
|
| 113 | - return $this->get('PMD_button_url'); |
|
| 114 | - } |
|
| 115 | - |
|
| 116 | - |
|
| 117 | - /** |
|
| 118 | - * Sets button_url |
|
| 119 | - * |
|
| 120 | - * @param string $button_url |
|
| 121 | - */ |
|
| 122 | - public function set_button_url($button_url) |
|
| 123 | - { |
|
| 124 | - $this->set('PMD_button_url', $button_url); |
|
| 125 | - } |
|
| 126 | - |
|
| 127 | - |
|
| 128 | - /** |
|
| 129 | - * Gets debug_mode |
|
| 130 | - * |
|
| 131 | - * @return boolean |
|
| 132 | - */ |
|
| 133 | - public function debug_mode() |
|
| 134 | - { |
|
| 135 | - return $this->get('PMD_debug_mode'); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - |
|
| 139 | - /** |
|
| 140 | - * Sets debug_mode |
|
| 141 | - * |
|
| 142 | - * @param boolean $debug_mode |
|
| 143 | - */ |
|
| 144 | - public function set_debug_mode($debug_mode) |
|
| 145 | - { |
|
| 146 | - $this->set('PMD_debug_mode', $debug_mode); |
|
| 147 | - } |
|
| 148 | - |
|
| 149 | - |
|
| 150 | - /** |
|
| 151 | - * Gets description |
|
| 152 | - * |
|
| 153 | - * @return string |
|
| 154 | - */ |
|
| 155 | - public function description() |
|
| 156 | - { |
|
| 157 | - return $this->get('PMD_desc'); |
|
| 158 | - } |
|
| 159 | - |
|
| 160 | - |
|
| 161 | - /** |
|
| 162 | - * Sets description |
|
| 163 | - * |
|
| 164 | - * @param string $description |
|
| 165 | - */ |
|
| 166 | - public function set_description($description) |
|
| 167 | - { |
|
| 168 | - $this->set('PMD_desc', $description); |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * Gets name |
|
| 174 | - * |
|
| 175 | - * @return string |
|
| 176 | - */ |
|
| 177 | - public function name() |
|
| 178 | - { |
|
| 179 | - return $this->get('PMD_name'); |
|
| 180 | - } |
|
| 181 | - |
|
| 182 | - |
|
| 183 | - /** |
|
| 184 | - * Sets name |
|
| 185 | - * |
|
| 186 | - * @param string $name |
|
| 187 | - */ |
|
| 188 | - public function set_name($name) |
|
| 189 | - { |
|
| 190 | - $this->set('PMD_name', $name); |
|
| 191 | - } |
|
| 192 | - |
|
| 193 | - |
|
| 194 | - /** |
|
| 195 | - * Gets open_by_default |
|
| 196 | - * |
|
| 197 | - * @return boolean |
|
| 198 | - */ |
|
| 199 | - public function open_by_default() |
|
| 200 | - { |
|
| 201 | - return $this->get('PMD_open_by_default'); |
|
| 202 | - } |
|
| 203 | - |
|
| 204 | - |
|
| 205 | - /** |
|
| 206 | - * Sets open_by_default |
|
| 207 | - * |
|
| 208 | - * @param boolean $open_by_default |
|
| 209 | - */ |
|
| 210 | - public function set_open_by_default($open_by_default) |
|
| 211 | - { |
|
| 212 | - $this->set('PMD_open_by_default', $open_by_default); |
|
| 213 | - } |
|
| 214 | - |
|
| 215 | - |
|
| 216 | - /** |
|
| 217 | - * Gets order |
|
| 218 | - * |
|
| 219 | - * @return int |
|
| 220 | - */ |
|
| 221 | - public function order() |
|
| 222 | - { |
|
| 223 | - return $this->get('PMD_order'); |
|
| 224 | - } |
|
| 225 | - |
|
| 226 | - |
|
| 227 | - /** |
|
| 228 | - * Sets order |
|
| 229 | - * |
|
| 230 | - * @param int $order |
|
| 231 | - */ |
|
| 232 | - public function set_order($order) |
|
| 233 | - { |
|
| 234 | - $this->set('PMD_order', $order); |
|
| 235 | - } |
|
| 236 | - |
|
| 237 | - |
|
| 238 | - /** |
|
| 239 | - * Gets slug |
|
| 240 | - * |
|
| 241 | - * @return string |
|
| 242 | - */ |
|
| 243 | - public function slug() |
|
| 244 | - { |
|
| 245 | - return $this->get('PMD_slug'); |
|
| 246 | - } |
|
| 247 | - |
|
| 248 | - |
|
| 249 | - /** |
|
| 250 | - * Sets slug |
|
| 251 | - * |
|
| 252 | - * @param string $slug |
|
| 253 | - */ |
|
| 254 | - public function set_slug($slug) |
|
| 255 | - { |
|
| 256 | - $this->set('PMD_slug', $slug); |
|
| 257 | - } |
|
| 258 | - |
|
| 259 | - |
|
| 260 | - /** |
|
| 261 | - * Gets type |
|
| 262 | - * |
|
| 263 | - * @return string |
|
| 264 | - */ |
|
| 265 | - public function type() |
|
| 266 | - { |
|
| 267 | - return $this->get('PMD_type'); |
|
| 268 | - } |
|
| 269 | - |
|
| 270 | - |
|
| 271 | - /** |
|
| 272 | - * Sets type |
|
| 273 | - * |
|
| 274 | - * @param string $type |
|
| 275 | - */ |
|
| 276 | - public function set_type($type) |
|
| 277 | - { |
|
| 278 | - $this->set('PMD_type', $type); |
|
| 279 | - } |
|
| 280 | - |
|
| 281 | - |
|
| 282 | - /** |
|
| 283 | - * Gets wp_user |
|
| 284 | - * |
|
| 285 | - * @return int |
|
| 286 | - */ |
|
| 287 | - public function wp_user() |
|
| 288 | - { |
|
| 289 | - return $this->get('PMD_wp_user'); |
|
| 290 | - } |
|
| 291 | - |
|
| 292 | - |
|
| 293 | - /** |
|
| 294 | - * Sets wp_user |
|
| 295 | - * |
|
| 296 | - * @param int $wp_user_id |
|
| 297 | - */ |
|
| 298 | - public function set_wp_user($wp_user_id) |
|
| 299 | - { |
|
| 300 | - $this->set('PMD_wp_user', $wp_user_id); |
|
| 301 | - } |
|
| 302 | - |
|
| 303 | - /** |
|
| 304 | - * Overrides parent so when PMD_type is changed we refresh the _type_obj |
|
| 305 | - * |
|
| 306 | - * @param string $field_name |
|
| 307 | - * @param mixed $field_value |
|
| 308 | - * @param boolean $use_default |
|
| 309 | - */ |
|
| 310 | - public function set($field_name, $field_value, bool $use_default = false) |
|
| 311 | - { |
|
| 312 | - if ($field_name === 'PMD_type') { |
|
| 313 | - // the type has probably changed, so forget about its old type object |
|
| 314 | - $this->_type_obj = null; |
|
| 315 | - } |
|
| 316 | - parent::set($field_name, $field_value, $use_default); |
|
| 317 | - } |
|
| 318 | - |
|
| 319 | - |
|
| 320 | - /** |
|
| 321 | - * Gets admin_name |
|
| 322 | - * |
|
| 323 | - * @return string |
|
| 324 | - */ |
|
| 325 | - public function admin_name() |
|
| 326 | - { |
|
| 327 | - return $this->get('PMD_admin_name'); |
|
| 328 | - } |
|
| 329 | - |
|
| 330 | - |
|
| 331 | - /** |
|
| 332 | - * Sets admin_name |
|
| 333 | - * |
|
| 334 | - * @param string $admin_name |
|
| 335 | - */ |
|
| 336 | - public function set_admin_name($admin_name) |
|
| 337 | - { |
|
| 338 | - $this->set('PMD_admin_name', $admin_name); |
|
| 339 | - } |
|
| 340 | - |
|
| 341 | - |
|
| 342 | - /** |
|
| 343 | - * Gets admin_desc |
|
| 344 | - * |
|
| 345 | - * @return string |
|
| 346 | - */ |
|
| 347 | - public function admin_desc() |
|
| 348 | - { |
|
| 349 | - return $this->get('PMD_admin_desc'); |
|
| 350 | - } |
|
| 351 | - |
|
| 352 | - |
|
| 353 | - /** |
|
| 354 | - * Sets admin_desc |
|
| 355 | - * |
|
| 356 | - * @param string $admin_desc |
|
| 357 | - */ |
|
| 358 | - public function set_admin_desc($admin_desc) |
|
| 359 | - { |
|
| 360 | - $this->set('PMD_admin_desc', $admin_desc); |
|
| 361 | - } |
|
| 362 | - |
|
| 363 | - |
|
| 364 | - /** |
|
| 365 | - * Gets scope |
|
| 366 | - * |
|
| 367 | - * @return array |
|
| 368 | - */ |
|
| 369 | - public function scope() |
|
| 370 | - { |
|
| 371 | - return $this->get('PMD_scope'); |
|
| 372 | - } |
|
| 373 | - |
|
| 374 | - |
|
| 375 | - /** |
|
| 376 | - * Sets scope |
|
| 377 | - * |
|
| 378 | - * @param array $scope |
|
| 379 | - */ |
|
| 380 | - public function set_scope($scope) |
|
| 381 | - { |
|
| 382 | - $this->set('PMD_scope', $scope); |
|
| 383 | - } |
|
| 384 | - |
|
| 385 | - |
|
| 386 | - /** |
|
| 387 | - * Gets the payment method type for this payment method instance |
|
| 388 | - * |
|
| 389 | - * @return EE_PMT_Base |
|
| 390 | - * @throws EE_Error |
|
| 391 | - */ |
|
| 392 | - public function type_obj() |
|
| 393 | - { |
|
| 394 | - if (! $this->_type_obj) { |
|
| 395 | - EE_Registry::instance()->load_lib('Payment_Method_Manager'); |
|
| 396 | - if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($this->type())) { |
|
| 397 | - $class_name = EE_Payment_Method_Manager::instance()->payment_method_class_from_type($this->type()); |
|
| 398 | - if (! class_exists($class_name)) { |
|
| 399 | - throw new EE_Error( |
|
| 400 | - sprintf( |
|
| 401 | - __( |
|
| 402 | - 'An attempt to use the "%1$s" payment method failed, so it was deactivated.%2$sWas the "%1$s" Plugin recently deactivated? It can be reactivated on the %3$sPlugins Admin Page%4$s', |
|
| 403 | - 'event_espresso' |
|
| 404 | - ), |
|
| 405 | - $class_name, |
|
| 406 | - '<br />', |
|
| 407 | - '<a href="' . admin_url('plugins.php') . '">', |
|
| 408 | - '</a>' |
|
| 409 | - ) |
|
| 410 | - ); |
|
| 411 | - } |
|
| 412 | - $r = new ReflectionClass($class_name); |
|
| 413 | - $this->_type_obj = $r->newInstanceArgs(array($this)); |
|
| 414 | - } else { |
|
| 415 | - throw new EE_Error( |
|
| 416 | - sprintf( |
|
| 417 | - __( |
|
| 418 | - 'A payment method of type "%1$s" does not exist. Only ones existing are: %2$s', |
|
| 419 | - 'event_espresso' |
|
| 420 | - ), |
|
| 421 | - $this->type(), |
|
| 422 | - implode(',', EE_Payment_Method_Manager::instance()->payment_method_type_names()) |
|
| 423 | - ) |
|
| 424 | - ); |
|
| 425 | - } |
|
| 426 | - } |
|
| 427 | - return $this->_type_obj; |
|
| 428 | - } |
|
| 429 | - |
|
| 430 | - |
|
| 431 | - /** |
|
| 432 | - * Returns a simple array of key-value pairs combining the payment method's fields (without the 'PMD_' prefix) |
|
| 433 | - * and the extra meta. Mostly used for passing off ot gateways. * |
|
| 434 | - * |
|
| 435 | - * @return array |
|
| 436 | - */ |
|
| 437 | - public function settings_array() |
|
| 438 | - { |
|
| 439 | - $fields = $this->model_field_array(); |
|
| 440 | - $extra_meta = $this->all_extra_meta_array(); |
|
| 441 | - // remove the model's prefix from the fields |
|
| 442 | - $combined_settings_array = array(); |
|
| 443 | - foreach ($fields as $key => $value) { |
|
| 444 | - if (strpos($key, 'PMD_') === 0) { |
|
| 445 | - $key_sans_model_prefix = str_replace('PMD_', '', $key); |
|
| 446 | - $combined_settings_array [ $key_sans_model_prefix ] = $value; |
|
| 447 | - } |
|
| 448 | - } |
|
| 449 | - $combined_settings_array = array_merge($extra_meta, $combined_settings_array); |
|
| 450 | - return $combined_settings_array; |
|
| 451 | - } |
|
| 452 | - |
|
| 453 | - |
|
| 454 | - /** |
|
| 455 | - * Gets the HTML for displaying the payment method on a page. |
|
| 456 | - * |
|
| 457 | - * @param string $url |
|
| 458 | - * @param string $css_class |
|
| 459 | - * @return string of HTML for displaying the button |
|
| 460 | - * @throws \EE_Error |
|
| 461 | - */ |
|
| 462 | - public function button_html($url = '', $css_class = '') |
|
| 463 | - { |
|
| 464 | - $payment_occurs = $this->type_obj()->payment_occurs(); |
|
| 465 | - return ' |
|
| 14 | + /** |
|
| 15 | + * Payment Method type object, which has all the info about this type of payment method, |
|
| 16 | + * including functions for processing payments, to get settings forms, etc. |
|
| 17 | + * |
|
| 18 | + * @var EE_PMT_Base |
|
| 19 | + */ |
|
| 20 | + protected $_type_obj; |
|
| 21 | + |
|
| 22 | + |
|
| 23 | + /** |
|
| 24 | + * @param array $props_n_values |
|
| 25 | + * @return EE_Payment_Method |
|
| 26 | + * @throws \EE_Error |
|
| 27 | + */ |
|
| 28 | + public static function new_instance($props_n_values = array()) |
|
| 29 | + { |
|
| 30 | + $has_object = parent::_check_for_object($props_n_values, __CLASS__); |
|
| 31 | + return $has_object ? $has_object : new self($props_n_values, false); |
|
| 32 | + } |
|
| 33 | + |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * @param array $props_n_values |
|
| 37 | + * @return EE_Payment_Method |
|
| 38 | + * @throws \EE_Error |
|
| 39 | + */ |
|
| 40 | + public static function new_instance_from_db($props_n_values = array()) |
|
| 41 | + { |
|
| 42 | + return new self($props_n_values, true); |
|
| 43 | + } |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + |
|
| 47 | + /** |
|
| 48 | + * Checks if there is a payment method class of the given 'PMD_type', and if so returns the classname. |
|
| 49 | + * Otherwise returns a normal EE_Payment_Method |
|
| 50 | + * |
|
| 51 | + * @param array $props_n_values where 'PMD_type' is a gateway name like 'Paypal_Standard','Invoice',etc (basically |
|
| 52 | + * the classname minus 'EEPM_') |
|
| 53 | + * @return string |
|
| 54 | + */ |
|
| 55 | + // private static function _payment_method_type($props_n_values) |
|
| 56 | + // { |
|
| 57 | + // EE_Registry::instance()->load_lib('Payment_Method_Manager'); |
|
| 58 | + // $type_string = isset($props_n_values['PMD_type']) ? $props_n_values['PMD_type'] : null; |
|
| 59 | + // if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($type_string)) { |
|
| 60 | + // return 'EEPM_' . $type_string; |
|
| 61 | + // } else { |
|
| 62 | + // return __CLASS__; |
|
| 63 | + // } |
|
| 64 | + // } |
|
| 65 | + |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * Gets whether this payment method can be used anywhere at all (ie frontend cart, admin, etc) |
|
| 69 | + * |
|
| 70 | + * @return boolean |
|
| 71 | + */ |
|
| 72 | + public function active() |
|
| 73 | + { |
|
| 74 | + return array_intersect(array_keys(EEM_Payment_Method::instance()->scopes()), $this->scope()); |
|
| 75 | + } |
|
| 76 | + |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * Sets this PM as active by making it usable within the CART scope. Offline gateways |
|
| 80 | + * are also usable from the admin-scope as well. DOES NOT SAVE it |
|
| 81 | + * |
|
| 82 | + * @throws \EE_Error |
|
| 83 | + */ |
|
| 84 | + public function set_active() |
|
| 85 | + { |
|
| 86 | + $default_scopes = array(EEM_Payment_Method::scope_cart); |
|
| 87 | + if ( |
|
| 88 | + $this->type_obj() && |
|
| 89 | + $this->type_obj()->payment_occurs() === EE_PMT_Base::offline |
|
| 90 | + ) { |
|
| 91 | + $default_scopes[] = EEM_Payment_Method::scope_admin; |
|
| 92 | + } |
|
| 93 | + $this->set_scope($default_scopes); |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + |
|
| 97 | + /** |
|
| 98 | + * Makes this payment method apply to NO scopes at all. DOES NOT SAVE it. |
|
| 99 | + */ |
|
| 100 | + public function deactivate() |
|
| 101 | + { |
|
| 102 | + $this->set_scope(array()); |
|
| 103 | + } |
|
| 104 | + |
|
| 105 | + |
|
| 106 | + /** |
|
| 107 | + * Gets button_url |
|
| 108 | + * |
|
| 109 | + * @return string |
|
| 110 | + */ |
|
| 111 | + public function button_url() |
|
| 112 | + { |
|
| 113 | + return $this->get('PMD_button_url'); |
|
| 114 | + } |
|
| 115 | + |
|
| 116 | + |
|
| 117 | + /** |
|
| 118 | + * Sets button_url |
|
| 119 | + * |
|
| 120 | + * @param string $button_url |
|
| 121 | + */ |
|
| 122 | + public function set_button_url($button_url) |
|
| 123 | + { |
|
| 124 | + $this->set('PMD_button_url', $button_url); |
|
| 125 | + } |
|
| 126 | + |
|
| 127 | + |
|
| 128 | + /** |
|
| 129 | + * Gets debug_mode |
|
| 130 | + * |
|
| 131 | + * @return boolean |
|
| 132 | + */ |
|
| 133 | + public function debug_mode() |
|
| 134 | + { |
|
| 135 | + return $this->get('PMD_debug_mode'); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + |
|
| 139 | + /** |
|
| 140 | + * Sets debug_mode |
|
| 141 | + * |
|
| 142 | + * @param boolean $debug_mode |
|
| 143 | + */ |
|
| 144 | + public function set_debug_mode($debug_mode) |
|
| 145 | + { |
|
| 146 | + $this->set('PMD_debug_mode', $debug_mode); |
|
| 147 | + } |
|
| 148 | + |
|
| 149 | + |
|
| 150 | + /** |
|
| 151 | + * Gets description |
|
| 152 | + * |
|
| 153 | + * @return string |
|
| 154 | + */ |
|
| 155 | + public function description() |
|
| 156 | + { |
|
| 157 | + return $this->get('PMD_desc'); |
|
| 158 | + } |
|
| 159 | + |
|
| 160 | + |
|
| 161 | + /** |
|
| 162 | + * Sets description |
|
| 163 | + * |
|
| 164 | + * @param string $description |
|
| 165 | + */ |
|
| 166 | + public function set_description($description) |
|
| 167 | + { |
|
| 168 | + $this->set('PMD_desc', $description); |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * Gets name |
|
| 174 | + * |
|
| 175 | + * @return string |
|
| 176 | + */ |
|
| 177 | + public function name() |
|
| 178 | + { |
|
| 179 | + return $this->get('PMD_name'); |
|
| 180 | + } |
|
| 181 | + |
|
| 182 | + |
|
| 183 | + /** |
|
| 184 | + * Sets name |
|
| 185 | + * |
|
| 186 | + * @param string $name |
|
| 187 | + */ |
|
| 188 | + public function set_name($name) |
|
| 189 | + { |
|
| 190 | + $this->set('PMD_name', $name); |
|
| 191 | + } |
|
| 192 | + |
|
| 193 | + |
|
| 194 | + /** |
|
| 195 | + * Gets open_by_default |
|
| 196 | + * |
|
| 197 | + * @return boolean |
|
| 198 | + */ |
|
| 199 | + public function open_by_default() |
|
| 200 | + { |
|
| 201 | + return $this->get('PMD_open_by_default'); |
|
| 202 | + } |
|
| 203 | + |
|
| 204 | + |
|
| 205 | + /** |
|
| 206 | + * Sets open_by_default |
|
| 207 | + * |
|
| 208 | + * @param boolean $open_by_default |
|
| 209 | + */ |
|
| 210 | + public function set_open_by_default($open_by_default) |
|
| 211 | + { |
|
| 212 | + $this->set('PMD_open_by_default', $open_by_default); |
|
| 213 | + } |
|
| 214 | + |
|
| 215 | + |
|
| 216 | + /** |
|
| 217 | + * Gets order |
|
| 218 | + * |
|
| 219 | + * @return int |
|
| 220 | + */ |
|
| 221 | + public function order() |
|
| 222 | + { |
|
| 223 | + return $this->get('PMD_order'); |
|
| 224 | + } |
|
| 225 | + |
|
| 226 | + |
|
| 227 | + /** |
|
| 228 | + * Sets order |
|
| 229 | + * |
|
| 230 | + * @param int $order |
|
| 231 | + */ |
|
| 232 | + public function set_order($order) |
|
| 233 | + { |
|
| 234 | + $this->set('PMD_order', $order); |
|
| 235 | + } |
|
| 236 | + |
|
| 237 | + |
|
| 238 | + /** |
|
| 239 | + * Gets slug |
|
| 240 | + * |
|
| 241 | + * @return string |
|
| 242 | + */ |
|
| 243 | + public function slug() |
|
| 244 | + { |
|
| 245 | + return $this->get('PMD_slug'); |
|
| 246 | + } |
|
| 247 | + |
|
| 248 | + |
|
| 249 | + /** |
|
| 250 | + * Sets slug |
|
| 251 | + * |
|
| 252 | + * @param string $slug |
|
| 253 | + */ |
|
| 254 | + public function set_slug($slug) |
|
| 255 | + { |
|
| 256 | + $this->set('PMD_slug', $slug); |
|
| 257 | + } |
|
| 258 | + |
|
| 259 | + |
|
| 260 | + /** |
|
| 261 | + * Gets type |
|
| 262 | + * |
|
| 263 | + * @return string |
|
| 264 | + */ |
|
| 265 | + public function type() |
|
| 266 | + { |
|
| 267 | + return $this->get('PMD_type'); |
|
| 268 | + } |
|
| 269 | + |
|
| 270 | + |
|
| 271 | + /** |
|
| 272 | + * Sets type |
|
| 273 | + * |
|
| 274 | + * @param string $type |
|
| 275 | + */ |
|
| 276 | + public function set_type($type) |
|
| 277 | + { |
|
| 278 | + $this->set('PMD_type', $type); |
|
| 279 | + } |
|
| 280 | + |
|
| 281 | + |
|
| 282 | + /** |
|
| 283 | + * Gets wp_user |
|
| 284 | + * |
|
| 285 | + * @return int |
|
| 286 | + */ |
|
| 287 | + public function wp_user() |
|
| 288 | + { |
|
| 289 | + return $this->get('PMD_wp_user'); |
|
| 290 | + } |
|
| 291 | + |
|
| 292 | + |
|
| 293 | + /** |
|
| 294 | + * Sets wp_user |
|
| 295 | + * |
|
| 296 | + * @param int $wp_user_id |
|
| 297 | + */ |
|
| 298 | + public function set_wp_user($wp_user_id) |
|
| 299 | + { |
|
| 300 | + $this->set('PMD_wp_user', $wp_user_id); |
|
| 301 | + } |
|
| 302 | + |
|
| 303 | + /** |
|
| 304 | + * Overrides parent so when PMD_type is changed we refresh the _type_obj |
|
| 305 | + * |
|
| 306 | + * @param string $field_name |
|
| 307 | + * @param mixed $field_value |
|
| 308 | + * @param boolean $use_default |
|
| 309 | + */ |
|
| 310 | + public function set($field_name, $field_value, bool $use_default = false) |
|
| 311 | + { |
|
| 312 | + if ($field_name === 'PMD_type') { |
|
| 313 | + // the type has probably changed, so forget about its old type object |
|
| 314 | + $this->_type_obj = null; |
|
| 315 | + } |
|
| 316 | + parent::set($field_name, $field_value, $use_default); |
|
| 317 | + } |
|
| 318 | + |
|
| 319 | + |
|
| 320 | + /** |
|
| 321 | + * Gets admin_name |
|
| 322 | + * |
|
| 323 | + * @return string |
|
| 324 | + */ |
|
| 325 | + public function admin_name() |
|
| 326 | + { |
|
| 327 | + return $this->get('PMD_admin_name'); |
|
| 328 | + } |
|
| 329 | + |
|
| 330 | + |
|
| 331 | + /** |
|
| 332 | + * Sets admin_name |
|
| 333 | + * |
|
| 334 | + * @param string $admin_name |
|
| 335 | + */ |
|
| 336 | + public function set_admin_name($admin_name) |
|
| 337 | + { |
|
| 338 | + $this->set('PMD_admin_name', $admin_name); |
|
| 339 | + } |
|
| 340 | + |
|
| 341 | + |
|
| 342 | + /** |
|
| 343 | + * Gets admin_desc |
|
| 344 | + * |
|
| 345 | + * @return string |
|
| 346 | + */ |
|
| 347 | + public function admin_desc() |
|
| 348 | + { |
|
| 349 | + return $this->get('PMD_admin_desc'); |
|
| 350 | + } |
|
| 351 | + |
|
| 352 | + |
|
| 353 | + /** |
|
| 354 | + * Sets admin_desc |
|
| 355 | + * |
|
| 356 | + * @param string $admin_desc |
|
| 357 | + */ |
|
| 358 | + public function set_admin_desc($admin_desc) |
|
| 359 | + { |
|
| 360 | + $this->set('PMD_admin_desc', $admin_desc); |
|
| 361 | + } |
|
| 362 | + |
|
| 363 | + |
|
| 364 | + /** |
|
| 365 | + * Gets scope |
|
| 366 | + * |
|
| 367 | + * @return array |
|
| 368 | + */ |
|
| 369 | + public function scope() |
|
| 370 | + { |
|
| 371 | + return $this->get('PMD_scope'); |
|
| 372 | + } |
|
| 373 | + |
|
| 374 | + |
|
| 375 | + /** |
|
| 376 | + * Sets scope |
|
| 377 | + * |
|
| 378 | + * @param array $scope |
|
| 379 | + */ |
|
| 380 | + public function set_scope($scope) |
|
| 381 | + { |
|
| 382 | + $this->set('PMD_scope', $scope); |
|
| 383 | + } |
|
| 384 | + |
|
| 385 | + |
|
| 386 | + /** |
|
| 387 | + * Gets the payment method type for this payment method instance |
|
| 388 | + * |
|
| 389 | + * @return EE_PMT_Base |
|
| 390 | + * @throws EE_Error |
|
| 391 | + */ |
|
| 392 | + public function type_obj() |
|
| 393 | + { |
|
| 394 | + if (! $this->_type_obj) { |
|
| 395 | + EE_Registry::instance()->load_lib('Payment_Method_Manager'); |
|
| 396 | + if (EE_Payment_Method_Manager::instance()->payment_method_type_exists($this->type())) { |
|
| 397 | + $class_name = EE_Payment_Method_Manager::instance()->payment_method_class_from_type($this->type()); |
|
| 398 | + if (! class_exists($class_name)) { |
|
| 399 | + throw new EE_Error( |
|
| 400 | + sprintf( |
|
| 401 | + __( |
|
| 402 | + 'An attempt to use the "%1$s" payment method failed, so it was deactivated.%2$sWas the "%1$s" Plugin recently deactivated? It can be reactivated on the %3$sPlugins Admin Page%4$s', |
|
| 403 | + 'event_espresso' |
|
| 404 | + ), |
|
| 405 | + $class_name, |
|
| 406 | + '<br />', |
|
| 407 | + '<a href="' . admin_url('plugins.php') . '">', |
|
| 408 | + '</a>' |
|
| 409 | + ) |
|
| 410 | + ); |
|
| 411 | + } |
|
| 412 | + $r = new ReflectionClass($class_name); |
|
| 413 | + $this->_type_obj = $r->newInstanceArgs(array($this)); |
|
| 414 | + } else { |
|
| 415 | + throw new EE_Error( |
|
| 416 | + sprintf( |
|
| 417 | + __( |
|
| 418 | + 'A payment method of type "%1$s" does not exist. Only ones existing are: %2$s', |
|
| 419 | + 'event_espresso' |
|
| 420 | + ), |
|
| 421 | + $this->type(), |
|
| 422 | + implode(',', EE_Payment_Method_Manager::instance()->payment_method_type_names()) |
|
| 423 | + ) |
|
| 424 | + ); |
|
| 425 | + } |
|
| 426 | + } |
|
| 427 | + return $this->_type_obj; |
|
| 428 | + } |
|
| 429 | + |
|
| 430 | + |
|
| 431 | + /** |
|
| 432 | + * Returns a simple array of key-value pairs combining the payment method's fields (without the 'PMD_' prefix) |
|
| 433 | + * and the extra meta. Mostly used for passing off ot gateways. * |
|
| 434 | + * |
|
| 435 | + * @return array |
|
| 436 | + */ |
|
| 437 | + public function settings_array() |
|
| 438 | + { |
|
| 439 | + $fields = $this->model_field_array(); |
|
| 440 | + $extra_meta = $this->all_extra_meta_array(); |
|
| 441 | + // remove the model's prefix from the fields |
|
| 442 | + $combined_settings_array = array(); |
|
| 443 | + foreach ($fields as $key => $value) { |
|
| 444 | + if (strpos($key, 'PMD_') === 0) { |
|
| 445 | + $key_sans_model_prefix = str_replace('PMD_', '', $key); |
|
| 446 | + $combined_settings_array [ $key_sans_model_prefix ] = $value; |
|
| 447 | + } |
|
| 448 | + } |
|
| 449 | + $combined_settings_array = array_merge($extra_meta, $combined_settings_array); |
|
| 450 | + return $combined_settings_array; |
|
| 451 | + } |
|
| 452 | + |
|
| 453 | + |
|
| 454 | + /** |
|
| 455 | + * Gets the HTML for displaying the payment method on a page. |
|
| 456 | + * |
|
| 457 | + * @param string $url |
|
| 458 | + * @param string $css_class |
|
| 459 | + * @return string of HTML for displaying the button |
|
| 460 | + * @throws \EE_Error |
|
| 461 | + */ |
|
| 462 | + public function button_html($url = '', $css_class = '') |
|
| 463 | + { |
|
| 464 | + $payment_occurs = $this->type_obj()->payment_occurs(); |
|
| 465 | + return ' |
|
| 466 | 466 | <div id="' |
| 467 | - . $this->slug() |
|
| 468 | - . '-payment-option-dv" class="' |
|
| 469 | - . $payment_occurs . '-payment-gateway reg-page-payment-option-dv' . $css_class . '"> |
|
| 467 | + . $this->slug() |
|
| 468 | + . '-payment-option-dv" class="' |
|
| 469 | + . $payment_occurs . '-payment-gateway reg-page-payment-option-dv' . $css_class . '"> |
|
| 470 | 470 | <a id="payment-gateway-button-' . $this->slug() |
| 471 | - . '" class="reg-page-payment-option-lnk" rel="' |
|
| 472 | - . $this->slug() . '" href="' . $url . '" > |
|
| 471 | + . '" class="reg-page-payment-option-lnk" rel="' |
|
| 472 | + . $this->slug() . '" href="' . $url . '" > |
|
| 473 | 473 | <img src="' . $this->button_url() . '" alt="' . sprintf( |
| 474 | - esc_attr__('Pay using %s', 'event_espresso'), |
|
| 475 | - $this->get_pretty('PMD_name', 'form_input') |
|
| 476 | - ) . '" /> |
|
| 474 | + esc_attr__('Pay using %s', 'event_espresso'), |
|
| 475 | + $this->get_pretty('PMD_name', 'form_input') |
|
| 476 | + ) . '" /> |
|
| 477 | 477 | </a> |
| 478 | 478 | </div> |
| 479 | 479 | '; |
| 480 | - } |
|
| 481 | - |
|
| 482 | - |
|
| 483 | - /** |
|
| 484 | - * Gets all the currencies which are an option for this payment method |
|
| 485 | - * (as defined by the gateway and the currently active currencies) |
|
| 486 | - * |
|
| 487 | - * @return EE_Currency[] |
|
| 488 | - * @throws \EE_Error |
|
| 489 | - */ |
|
| 490 | - public function get_all_usable_currencies() |
|
| 491 | - { |
|
| 492 | - return EEM_Currency::instance()->get_all_currencies_usable_by($this->type_obj()); |
|
| 493 | - } |
|
| 494 | - |
|
| 495 | - |
|
| 496 | - /** |
|
| 497 | - * Reports whether or not this payment method can be used for this payment method |
|
| 498 | - * |
|
| 499 | - * @param string $currency_code currency ID (code) |
|
| 500 | - * @return boolean |
|
| 501 | - * @throws \EE_Error |
|
| 502 | - */ |
|
| 503 | - public function usable_for_currency($currency_code) |
|
| 504 | - { |
|
| 505 | - foreach ($this->get_all_usable_currencies() as $currency_obj) { |
|
| 506 | - if ($currency_obj->ID() === $currency_code) { |
|
| 507 | - return true; |
|
| 508 | - } |
|
| 509 | - } |
|
| 510 | - return false; |
|
| 511 | - } |
|
| 512 | - |
|
| 513 | - |
|
| 514 | - /** |
|
| 515 | - * Returns TRUE if this payment method's gateway is an instance of EE_Onsite_Gateway |
|
| 516 | - * |
|
| 517 | - * @return bool |
|
| 518 | - * @throws \EE_Error |
|
| 519 | - */ |
|
| 520 | - public function is_on_site() |
|
| 521 | - { |
|
| 522 | - return $this->type_obj()->payment_occurs() === EE_PMT_Base::onsite; |
|
| 523 | - } |
|
| 524 | - |
|
| 525 | - |
|
| 526 | - /** |
|
| 527 | - * Returns TRUE if this payment method's gateway is an instance of EE_Offsite_Gateway |
|
| 528 | - * |
|
| 529 | - * @return bool |
|
| 530 | - * @throws \EE_Error |
|
| 531 | - */ |
|
| 532 | - public function is_off_site() |
|
| 533 | - { |
|
| 534 | - return $this->type_obj()->payment_occurs() === EE_PMT_Base::offsite; |
|
| 535 | - } |
|
| 536 | - |
|
| 537 | - |
|
| 538 | - /** |
|
| 539 | - * Returns TRUE if this payment method does not utilize a gateway |
|
| 540 | - * |
|
| 541 | - * @return bool |
|
| 542 | - * @throws \EE_Error |
|
| 543 | - */ |
|
| 544 | - public function is_off_line() |
|
| 545 | - { |
|
| 546 | - return $this->type_obj()->payment_occurs() === EE_PMT_Base::offline; |
|
| 547 | - } |
|
| 548 | - |
|
| 549 | - /** |
|
| 550 | - * Overrides default __sleep so the object type is NOT cached. |
|
| 551 | - * This way we can rely on the normal EE_Payment_Method::type_obj() logic |
|
| 552 | - * to load the required classes, and don't need them at the time of unserialization |
|
| 553 | - * |
|
| 554 | - * @return array |
|
| 555 | - */ |
|
| 556 | - public function __sleep() |
|
| 557 | - { |
|
| 558 | - $properties = get_object_vars($this); |
|
| 559 | - unset($properties['_type_obj']); |
|
| 560 | - return array_keys($properties); |
|
| 561 | - } |
|
| 562 | - |
|
| 563 | - |
|
| 564 | - /** |
|
| 565 | - * Overrides parent to add some logging for when payment methods get deactivated |
|
| 566 | - * |
|
| 567 | - * @param array $set_cols_n_values |
|
| 568 | - * @return int @see EE_Base_Class::save() |
|
| 569 | - * @throws \EE_Error |
|
| 570 | - */ |
|
| 571 | - public function save($set_cols_n_values = array()) |
|
| 572 | - { |
|
| 573 | - $results = parent::save($set_cols_n_values); |
|
| 574 | - if ($this->get_original('PMD_scope') !== $this->get('PMD_scope')) { |
|
| 575 | - EE_Log::instance()->log( |
|
| 576 | - __FILE__, |
|
| 577 | - __FUNCTION__, |
|
| 578 | - sprintf( |
|
| 579 | - __('Set new scope on payment method %1$s to %2$s from %3$s on URL %4$s', 'event_espresso'), |
|
| 580 | - $this->name(), |
|
| 581 | - serialize($this->get_original('PMD_scope')), |
|
| 582 | - serialize($this->get('PMD_scope')), |
|
| 583 | - EE_Registry::instance()->REQ->get_current_page_permalink() |
|
| 584 | - ), |
|
| 585 | - 'payment_method_change' |
|
| 586 | - ); |
|
| 587 | - } |
|
| 588 | - return $results; |
|
| 589 | - } |
|
| 480 | + } |
|
| 481 | + |
|
| 482 | + |
|
| 483 | + /** |
|
| 484 | + * Gets all the currencies which are an option for this payment method |
|
| 485 | + * (as defined by the gateway and the currently active currencies) |
|
| 486 | + * |
|
| 487 | + * @return EE_Currency[] |
|
| 488 | + * @throws \EE_Error |
|
| 489 | + */ |
|
| 490 | + public function get_all_usable_currencies() |
|
| 491 | + { |
|
| 492 | + return EEM_Currency::instance()->get_all_currencies_usable_by($this->type_obj()); |
|
| 493 | + } |
|
| 494 | + |
|
| 495 | + |
|
| 496 | + /** |
|
| 497 | + * Reports whether or not this payment method can be used for this payment method |
|
| 498 | + * |
|
| 499 | + * @param string $currency_code currency ID (code) |
|
| 500 | + * @return boolean |
|
| 501 | + * @throws \EE_Error |
|
| 502 | + */ |
|
| 503 | + public function usable_for_currency($currency_code) |
|
| 504 | + { |
|
| 505 | + foreach ($this->get_all_usable_currencies() as $currency_obj) { |
|
| 506 | + if ($currency_obj->ID() === $currency_code) { |
|
| 507 | + return true; |
|
| 508 | + } |
|
| 509 | + } |
|
| 510 | + return false; |
|
| 511 | + } |
|
| 512 | + |
|
| 513 | + |
|
| 514 | + /** |
|
| 515 | + * Returns TRUE if this payment method's gateway is an instance of EE_Onsite_Gateway |
|
| 516 | + * |
|
| 517 | + * @return bool |
|
| 518 | + * @throws \EE_Error |
|
| 519 | + */ |
|
| 520 | + public function is_on_site() |
|
| 521 | + { |
|
| 522 | + return $this->type_obj()->payment_occurs() === EE_PMT_Base::onsite; |
|
| 523 | + } |
|
| 524 | + |
|
| 525 | + |
|
| 526 | + /** |
|
| 527 | + * Returns TRUE if this payment method's gateway is an instance of EE_Offsite_Gateway |
|
| 528 | + * |
|
| 529 | + * @return bool |
|
| 530 | + * @throws \EE_Error |
|
| 531 | + */ |
|
| 532 | + public function is_off_site() |
|
| 533 | + { |
|
| 534 | + return $this->type_obj()->payment_occurs() === EE_PMT_Base::offsite; |
|
| 535 | + } |
|
| 536 | + |
|
| 537 | + |
|
| 538 | + /** |
|
| 539 | + * Returns TRUE if this payment method does not utilize a gateway |
|
| 540 | + * |
|
| 541 | + * @return bool |
|
| 542 | + * @throws \EE_Error |
|
| 543 | + */ |
|
| 544 | + public function is_off_line() |
|
| 545 | + { |
|
| 546 | + return $this->type_obj()->payment_occurs() === EE_PMT_Base::offline; |
|
| 547 | + } |
|
| 548 | + |
|
| 549 | + /** |
|
| 550 | + * Overrides default __sleep so the object type is NOT cached. |
|
| 551 | + * This way we can rely on the normal EE_Payment_Method::type_obj() logic |
|
| 552 | + * to load the required classes, and don't need them at the time of unserialization |
|
| 553 | + * |
|
| 554 | + * @return array |
|
| 555 | + */ |
|
| 556 | + public function __sleep() |
|
| 557 | + { |
|
| 558 | + $properties = get_object_vars($this); |
|
| 559 | + unset($properties['_type_obj']); |
|
| 560 | + return array_keys($properties); |
|
| 561 | + } |
|
| 562 | + |
|
| 563 | + |
|
| 564 | + /** |
|
| 565 | + * Overrides parent to add some logging for when payment methods get deactivated |
|
| 566 | + * |
|
| 567 | + * @param array $set_cols_n_values |
|
| 568 | + * @return int @see EE_Base_Class::save() |
|
| 569 | + * @throws \EE_Error |
|
| 570 | + */ |
|
| 571 | + public function save($set_cols_n_values = array()) |
|
| 572 | + { |
|
| 573 | + $results = parent::save($set_cols_n_values); |
|
| 574 | + if ($this->get_original('PMD_scope') !== $this->get('PMD_scope')) { |
|
| 575 | + EE_Log::instance()->log( |
|
| 576 | + __FILE__, |
|
| 577 | + __FUNCTION__, |
|
| 578 | + sprintf( |
|
| 579 | + __('Set new scope on payment method %1$s to %2$s from %3$s on URL %4$s', 'event_espresso'), |
|
| 580 | + $this->name(), |
|
| 581 | + serialize($this->get_original('PMD_scope')), |
|
| 582 | + serialize($this->get('PMD_scope')), |
|
| 583 | + EE_Registry::instance()->REQ->get_current_page_permalink() |
|
| 584 | + ), |
|
| 585 | + 'payment_method_change' |
|
| 586 | + ); |
|
| 587 | + } |
|
| 588 | + return $results; |
|
| 589 | + } |
|
| 590 | 590 | } |
@@ -32,1269 +32,1269 @@ |
||
| 32 | 32 | class EE_Data_Migration_Manager implements ResettableInterface |
| 33 | 33 | { |
| 34 | 34 | |
| 35 | - /** |
|
| 36 | - * |
|
| 37 | - * @var EE_Registry |
|
| 38 | - */ |
|
| 39 | - // protected $EE; |
|
| 40 | - /** |
|
| 41 | - * name of the wordpress option which stores an array of data about |
|
| 42 | - */ |
|
| 43 | - const data_migrations_option_name = 'ee_data_migration'; |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - const data_migration_script_option_prefix = 'ee_data_migration_script_'; |
|
| 47 | - |
|
| 48 | - const data_migration_script_mapping_option_prefix = 'ee_dms_map_'; |
|
| 49 | - |
|
| 50 | - /** |
|
| 51 | - * name of the wordpress option which stores the database' current version. IE, the code may be at version 4.2.0, |
|
| 52 | - * but as migrations are performed the database will progress from 3.1.35 to 4.1.0 etc. |
|
| 53 | - */ |
|
| 54 | - const current_database_state = 'ee_data_migration_current_db_state'; |
|
| 55 | - |
|
| 56 | - /** |
|
| 57 | - * Special status string returned when we're positive there are no more data migration |
|
| 58 | - * scripts that can be run. |
|
| 59 | - */ |
|
| 60 | - const status_no_more_migration_scripts = 'no_more_migration_scripts'; |
|
| 61 | - /** |
|
| 62 | - * string indicating the migration should continue |
|
| 63 | - */ |
|
| 64 | - const status_continue = 'status_continue'; |
|
| 65 | - /** |
|
| 66 | - * string indicating the migration has completed and should be ended |
|
| 67 | - */ |
|
| 68 | - const status_completed = 'status_completed'; |
|
| 69 | - /** |
|
| 70 | - * string indicating a fatal error occurred and the data migration should be completely aborted |
|
| 71 | - */ |
|
| 72 | - const status_fatal_error = 'status_fatal_error'; |
|
| 73 | - |
|
| 74 | - /** |
|
| 75 | - * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent |
|
| 76 | - * during migration) |
|
| 77 | - */ |
|
| 78 | - const step_size = 50; |
|
| 79 | - |
|
| 80 | - /** |
|
| 81 | - * option name that stores the queue of ee plugins needing to have |
|
| 82 | - * their data initialized (or re-initialized) once we are done migrations |
|
| 83 | - */ |
|
| 84 | - const db_init_queue_option_name = 'ee_db_init_queue'; |
|
| 85 | - /** |
|
| 86 | - * Array of information concerning data migrations that have ran in the history |
|
| 87 | - * of this EE installation. Keys should be the name of the version the script upgraded to |
|
| 88 | - * |
|
| 89 | - * @var EE_Data_Migration_Script_Base[] |
|
| 90 | - */ |
|
| 91 | - private $_data_migrations_ran = null; |
|
| 92 | - /** |
|
| 93 | - * The last ran script. It's nice to store this somewhere accessible, as its easiest |
|
| 94 | - * to know which was the last run by which is the newest wp option; but in most of the code |
|
| 95 | - * we just use the local $_data_migration_ran array, which organized the scripts differently |
|
| 96 | - * |
|
| 97 | - * @var EE_Data_Migration_Script_Base |
|
| 98 | - */ |
|
| 99 | - private $_last_ran_script = null; |
|
| 100 | - |
|
| 101 | - /** |
|
| 102 | - * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script. |
|
| 103 | - * |
|
| 104 | - * @var EE_Data_Migration_Script_Base |
|
| 105 | - */ |
|
| 106 | - private $_last_ran_incomplete_script = null; |
|
| 107 | - /** |
|
| 108 | - * array where keys are classnames, and values are filepaths of all the known migration scripts |
|
| 109 | - * |
|
| 110 | - * @var array |
|
| 111 | - */ |
|
| 112 | - private $_data_migration_class_to_filepath_map; |
|
| 113 | - |
|
| 114 | - /** |
|
| 115 | - * the following 4 properties are fully set on construction. |
|
| 116 | - * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished |
|
| 117 | - * one, we may want to start the next one); whereas the last two indicate whether to continue running a single |
|
| 118 | - * data migration script |
|
| 119 | - * |
|
| 120 | - * @var array |
|
| 121 | - */ |
|
| 122 | - public $stati_that_indicate_to_continue_migrations = array(); |
|
| 123 | - |
|
| 124 | - public $stati_that_indicate_to_stop_migrations = array(); |
|
| 125 | - |
|
| 126 | - public $stati_that_indicate_to_continue_single_migration_script = array(); |
|
| 127 | - |
|
| 128 | - public $stati_that_indicate_to_stop_single_migration_script = array(); |
|
| 129 | - |
|
| 130 | - /** |
|
| 131 | - * @var TableManager $table_manager |
|
| 132 | - */ |
|
| 133 | - protected $_table_manager; |
|
| 134 | - |
|
| 135 | - /** |
|
| 136 | - * @var TableAnalysis $table_analysis |
|
| 137 | - */ |
|
| 138 | - protected $_table_analysis; |
|
| 139 | - |
|
| 140 | - /** |
|
| 141 | - * @var array $script_migration_versions |
|
| 142 | - */ |
|
| 143 | - protected $script_migration_versions; |
|
| 144 | - |
|
| 145 | - /** |
|
| 146 | - * @var array $dms_folders |
|
| 147 | - */ |
|
| 148 | - protected $dms_folders; |
|
| 149 | - |
|
| 150 | - /** |
|
| 151 | - * @var EE_Data_Migration_Manager $_instance |
|
| 152 | - * @access private |
|
| 153 | - */ |
|
| 154 | - private static $_instance; |
|
| 155 | - |
|
| 156 | - |
|
| 157 | - /** |
|
| 158 | - * @singleton method used to instantiate class object |
|
| 159 | - * @access public |
|
| 160 | - * @return EE_Data_Migration_Manager instance |
|
| 161 | - */ |
|
| 162 | - public static function instance() |
|
| 163 | - { |
|
| 164 | - // check if class object is instantiated |
|
| 165 | - if (! self::$_instance instanceof EE_Data_Migration_Manager) { |
|
| 166 | - self::$_instance = new self(); |
|
| 167 | - } |
|
| 168 | - return self::$_instance; |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - /** |
|
| 172 | - * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning, |
|
| 173 | - * all new usages of the singleton should be made with Classname::instance()) and returns it |
|
| 174 | - * |
|
| 175 | - * @return EE_Data_Migration_Manager |
|
| 176 | - */ |
|
| 177 | - public static function reset() |
|
| 178 | - { |
|
| 179 | - self::$_instance = null; |
|
| 180 | - return self::instance(); |
|
| 181 | - } |
|
| 182 | - |
|
| 183 | - |
|
| 184 | - /** |
|
| 185 | - * @throws EE_Error |
|
| 186 | - * @throws ReflectionException |
|
| 187 | - */ |
|
| 188 | - private function __construct() |
|
| 189 | - { |
|
| 190 | - $this->stati_that_indicate_to_continue_migrations = array( |
|
| 191 | - self::status_continue, |
|
| 192 | - self::status_completed, |
|
| 193 | - ); |
|
| 194 | - $this->stati_that_indicate_to_stop_migrations = array( |
|
| 195 | - self::status_fatal_error, |
|
| 196 | - self::status_no_more_migration_scripts, |
|
| 197 | - ); |
|
| 198 | - $this->stati_that_indicate_to_continue_single_migration_script = array( |
|
| 199 | - self::status_continue, |
|
| 200 | - ); |
|
| 201 | - $this->stati_that_indicate_to_stop_single_migration_script = array( |
|
| 202 | - self::status_completed, |
|
| 203 | - self::status_fatal_error |
|
| 204 | - // note: status_no_more_migration_scripts doesn't apply |
|
| 205 | - ); |
|
| 206 | - // make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class |
|
| 207 | - // to be defined, because right now it doesn't get autoloaded on its own |
|
| 208 | - EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), true); |
|
| 209 | - EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), true); |
|
| 210 | - EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), true); |
|
| 211 | - EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), true); |
|
| 212 | - EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), true); |
|
| 213 | - $this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true); |
|
| 214 | - $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true); |
|
| 215 | - } |
|
| 216 | - |
|
| 217 | - |
|
| 218 | - /** |
|
| 219 | - * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what |
|
| 220 | - * the option names are like, but generally they're like |
|
| 221 | - * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that). |
|
| 222 | - * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived, |
|
| 223 | - * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php (eg |
|
| 224 | - * EE_DMS_Core_4_1_0.dms.php) |
|
| 225 | - * |
|
| 226 | - * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set) |
|
| 227 | - * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of |
|
| 228 | - * that plugin (eg '4.1.0') |
|
| 229 | - */ |
|
| 230 | - private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name) |
|
| 231 | - { |
|
| 232 | - $plugin_slug_and_version_string = str_replace( |
|
| 233 | - EE_Data_Migration_Manager::data_migration_script_option_prefix, |
|
| 234 | - "", |
|
| 235 | - $option_name |
|
| 236 | - ); |
|
| 237 | - // check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style) |
|
| 238 | - $parts = explode(".", $plugin_slug_and_version_string); |
|
| 239 | - |
|
| 240 | - if (count($parts) == 4) { |
|
| 241 | - // it's 4.2-style.eg Core.4.1.0 |
|
| 242 | - $plugin_slug = $parts[0];// eg Core |
|
| 243 | - $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0 |
|
| 244 | - } else { |
|
| 245 | - // it's 4.1-style: eg 4.1.0 |
|
| 246 | - $plugin_slug = 'Core'; |
|
| 247 | - $version_string = $plugin_slug_and_version_string;// eg 4.1.0 |
|
| 248 | - } |
|
| 249 | - return array($plugin_slug, $version_string); |
|
| 250 | - } |
|
| 251 | - |
|
| 252 | - /** |
|
| 253 | - * Gets the DMS class from the wordpress option, otherwise throws an EE_Error if it's not |
|
| 254 | - * for a known DMS class. |
|
| 255 | - * |
|
| 256 | - * @param string $dms_option_name |
|
| 257 | - * @param string $dms_option_value (serialized) |
|
| 258 | - * @return EE_Data_Migration_Script_Base |
|
| 259 | - * @throws EE_Error |
|
| 260 | - */ |
|
| 261 | - private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value) |
|
| 262 | - { |
|
| 263 | - $data_migration_data = maybe_unserialize($dms_option_value); |
|
| 264 | - if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) { |
|
| 265 | - $class = LoaderFactory::getLoader()->getShared($data_migration_data['class']); |
|
| 266 | - if ($class instanceof EE_Data_Migration_Script_Base) { |
|
| 267 | - $class->instantiate_from_array_of_properties($data_migration_data); |
|
| 268 | - return $class; |
|
| 269 | - } else { |
|
| 270 | - // huh, so its an object but not a data migration script?? that shouldn't happen |
|
| 271 | - // just leave it as an array (which will probably just get ignored) |
|
| 272 | - throw new EE_Error( |
|
| 273 | - sprintf( |
|
| 274 | - __( |
|
| 275 | - "Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists", |
|
| 276 | - 'event_espresso' |
|
| 277 | - ), |
|
| 278 | - $data_migration_data['class'] |
|
| 279 | - ) |
|
| 280 | - ); |
|
| 281 | - } |
|
| 282 | - } else { |
|
| 283 | - // so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists |
|
| 284 | - throw new EE_Error( |
|
| 285 | - sprintf(__("The wp option with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name) |
|
| 286 | - ); |
|
| 287 | - } |
|
| 288 | - } |
|
| 289 | - |
|
| 290 | - |
|
| 291 | - /** |
|
| 292 | - * Gets the array describing what data migrations have run. Also has a side-effect of recording which was the last |
|
| 293 | - * ran, and which was the last ran which hasn't finished yet |
|
| 294 | - * |
|
| 295 | - * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy |
|
| 296 | - * arrays in there - which should probably be ignored) |
|
| 297 | - * @throws EE_Error |
|
| 298 | - */ |
|
| 299 | - public function get_data_migrations_ran() |
|
| 300 | - { |
|
| 301 | - if (! $this->_data_migrations_ran) { |
|
| 302 | - // setup autoloaders for each of the scripts in there |
|
| 303 | - $this->get_all_data_migration_scripts_available(); |
|
| 304 | - $data_migrations_options = $this->get_all_migration_script_options( |
|
| 305 | - );// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array())); |
|
| 306 | - |
|
| 307 | - $data_migrations_ran = array(); |
|
| 308 | - // convert into data migration script classes where possible |
|
| 309 | - foreach ($data_migrations_options as $data_migration_option) { |
|
| 310 | - list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name( |
|
| 311 | - $data_migration_option['option_name'] |
|
| 312 | - ); |
|
| 313 | - |
|
| 314 | - try { |
|
| 315 | - $class = $this->_get_dms_class_from_wp_option( |
|
| 316 | - $data_migration_option['option_name'], |
|
| 317 | - $data_migration_option['option_value'] |
|
| 318 | - ); |
|
| 319 | - $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class; |
|
| 320 | - // ok so far THIS is the 'last-ran-script'... unless we find another on next iteration |
|
| 321 | - $this->_last_ran_script = $class; |
|
| 322 | - if (! $class->is_completed()) { |
|
| 323 | - // sometimes we also like to know which was the last incomplete script (or if there are any at all) |
|
| 324 | - $this->_last_ran_incomplete_script = $class; |
|
| 325 | - } |
|
| 326 | - } catch (EE_Error $e) { |
|
| 327 | - // ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs |
|
| 328 | - $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize( |
|
| 329 | - $data_migration_option['option_value'] |
|
| 330 | - ); |
|
| 331 | - } |
|
| 332 | - } |
|
| 333 | - // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays |
|
| 334 | - $this->_data_migrations_ran = $data_migrations_ran; |
|
| 335 | - if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) { |
|
| 336 | - $this->_data_migrations_ran = array(); |
|
| 337 | - } |
|
| 338 | - } |
|
| 339 | - return $this->_data_migrations_ran; |
|
| 340 | - } |
|
| 341 | - |
|
| 342 | - |
|
| 343 | - /** |
|
| 344 | - * |
|
| 345 | - * @param string $script_name eg 'DMS_Core_4_1_0' |
|
| 346 | - * @param string $old_table eg 'wp_events_detail' |
|
| 347 | - * @param string $old_pk eg 'wp_esp_posts' |
|
| 348 | - * @param $new_table |
|
| 349 | - * @return mixed string or int |
|
| 350 | - * @throws EE_Error |
|
| 351 | - * @throws ReflectionException |
|
| 352 | - */ |
|
| 353 | - public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table) |
|
| 354 | - { |
|
| 355 | - $script = EE_Registry::instance()->load_dms($script_name); |
|
| 356 | - return $script->get_mapping_new_pk($old_table, $old_pk, $new_table); |
|
| 357 | - } |
|
| 358 | - |
|
| 359 | - /** |
|
| 360 | - * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that |
|
| 361 | - * the last option returned in this array is the most-recently ran DMS option |
|
| 362 | - * |
|
| 363 | - * @return array |
|
| 364 | - */ |
|
| 365 | - public function get_all_migration_script_options() |
|
| 366 | - { |
|
| 367 | - global $wpdb; |
|
| 368 | - return $wpdb->get_results( |
|
| 369 | - "SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC", |
|
| 370 | - ARRAY_A |
|
| 371 | - ); |
|
| 372 | - } |
|
| 373 | - |
|
| 374 | - /** |
|
| 375 | - * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded |
|
| 376 | - * |
|
| 377 | - * @return array where each value is the full folder path of a folder containing data migration scripts, WITH |
|
| 378 | - * slashes at the end of the folder name. |
|
| 379 | - */ |
|
| 380 | - public function get_data_migration_script_folders() |
|
| 381 | - { |
|
| 382 | - if (empty($this->dms_folders)) { |
|
| 383 | - $this->dms_folders = apply_filters( |
|
| 384 | - 'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders', |
|
| 385 | - array('Core' => EE_CORE . 'data_migration_scripts') |
|
| 386 | - ); |
|
| 387 | - } |
|
| 388 | - return $this->dms_folders; |
|
| 389 | - } |
|
| 390 | - |
|
| 391 | - /** |
|
| 392 | - * Gets the version the migration script upgrades to |
|
| 393 | - * |
|
| 394 | - * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0' |
|
| 395 | - * @return array { |
|
| 396 | - * @type string $slug like 'Core','Calendar',etc |
|
| 397 | - * @type string $version like 4.3.0 |
|
| 398 | - * } |
|
| 399 | - * @throws EE_Error |
|
| 400 | - */ |
|
| 401 | - public function script_migrates_to_version($migration_script_name, $eeAddonClass = '') |
|
| 402 | - { |
|
| 403 | - if (isset($this->script_migration_versions[ $migration_script_name ])) { |
|
| 404 | - return $this->script_migration_versions[ $migration_script_name ]; |
|
| 405 | - } |
|
| 406 | - $dms_info = $this->parse_dms_classname($migration_script_name); |
|
| 407 | - $this->script_migration_versions[ $migration_script_name ] = array( |
|
| 408 | - 'slug' => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'], |
|
| 409 | - 'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'], |
|
| 410 | - ); |
|
| 411 | - return $this->script_migration_versions[ $migration_script_name ]; |
|
| 412 | - } |
|
| 413 | - |
|
| 414 | - /** |
|
| 415 | - * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0' |
|
| 416 | - * |
|
| 417 | - * @param string $classname |
|
| 418 | - * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints) |
|
| 419 | - * @throws EE_Error |
|
| 420 | - */ |
|
| 421 | - public function parse_dms_classname($classname) |
|
| 422 | - { |
|
| 423 | - $matches = array(); |
|
| 424 | - preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches); |
|
| 425 | - if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) { |
|
| 426 | - throw new EE_Error( |
|
| 427 | - sprintf( |
|
| 428 | - __( |
|
| 429 | - "%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ", |
|
| 430 | - "event_espresso" |
|
| 431 | - ), |
|
| 432 | - $classname |
|
| 433 | - ) |
|
| 434 | - ); |
|
| 435 | - } |
|
| 436 | - return array( |
|
| 437 | - 'slug' => $matches[1], |
|
| 438 | - 'major_version' => intval($matches[2]), |
|
| 439 | - 'minor_version' => intval($matches[3]), |
|
| 440 | - 'micro_version' => intval($matches[4]), |
|
| 441 | - ); |
|
| 442 | - } |
|
| 443 | - |
|
| 444 | - /** |
|
| 445 | - * Ensures that the option indicating the current DB version is set. This should only be |
|
| 446 | - * a concern when activating EE for the first time, THEORETICALLY. |
|
| 447 | - * If we detect that we're activating EE4 over top of EE3.1, then we set the current db state to 3.1.x, otherwise |
|
| 448 | - * to 4.1.x. |
|
| 449 | - * |
|
| 450 | - * @return string of current db state |
|
| 451 | - */ |
|
| 452 | - public function ensure_current_database_state_is_set() |
|
| 453 | - { |
|
| 454 | - $espresso_db_core_updates = get_option('espresso_db_update', array()); |
|
| 455 | - $db_state = get_option(EE_Data_Migration_Manager::current_database_state); |
|
| 456 | - if (! $db_state) { |
|
| 457 | - // mark the DB as being in the state as the last version in there. |
|
| 458 | - // this is done to trigger maintenance mode and do data migration scripts |
|
| 459 | - // if the admin installed this version of EE over 3.1.x or 4.0.x |
|
| 460 | - // otherwise, the normal maintenance mode code is fine |
|
| 461 | - $previous_versions_installed = array_keys($espresso_db_core_updates); |
|
| 462 | - $previous_version_installed = end($previous_versions_installed); |
|
| 463 | - if (version_compare('4.1.0', $previous_version_installed)) { |
|
| 464 | - // last installed version was less than 4.1 |
|
| 465 | - // so we want the data migrations to happen. SO, we're going to say the DB is at that state |
|
| 466 | - $db_state = array('Core' => $previous_version_installed); |
|
| 467 | - } else { |
|
| 468 | - $db_state = array('Core' => EVENT_ESPRESSO_VERSION); |
|
| 469 | - } |
|
| 470 | - update_option(EE_Data_Migration_Manager::current_database_state, $db_state); |
|
| 471 | - } |
|
| 472 | - // in 4.1, $db_state would have only been a simple string like '4.1.0', |
|
| 473 | - // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's |
|
| 474 | - // db, and possibly other keys for other addons like 'Calendar','Permissions',etc |
|
| 475 | - if (! is_array($db_state)) { |
|
| 476 | - $db_state = array('Core' => $db_state); |
|
| 477 | - update_option(EE_Data_Migration_Manager::current_database_state, $db_state); |
|
| 478 | - } |
|
| 479 | - return $db_state; |
|
| 480 | - } |
|
| 481 | - |
|
| 482 | - |
|
| 483 | - /** |
|
| 484 | - * Checks if there are any data migration scripts that ought to be run. If found, |
|
| 485 | - * returns the instantiated classes. If none are found (ie, they've all already been run |
|
| 486 | - * or they don't apply), returns an empty array |
|
| 487 | - * |
|
| 488 | - * @return EE_Data_Migration_Script_Base[] |
|
| 489 | - * @throws EE_Error |
|
| 490 | - */ |
|
| 491 | - public function check_for_applicable_data_migration_scripts() |
|
| 492 | - { |
|
| 493 | - // get the option describing what options have already run |
|
| 494 | - $scripts_ran = $this->get_data_migrations_ran(); |
|
| 495 | - // $scripts_ran = array('4.1.0.core'=>array('monkey'=>null)); |
|
| 496 | - $script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available(); |
|
| 497 | - |
|
| 498 | - |
|
| 499 | - $current_database_state = $this->ensure_current_database_state_is_set(); |
|
| 500 | - // determine which have already been run |
|
| 501 | - $script_classes_that_should_run_per_iteration = array(); |
|
| 502 | - $iteration = 0; |
|
| 503 | - $next_database_state_to_consider = $current_database_state; |
|
| 504 | - $theoretical_database_state = null; |
|
| 505 | - do { |
|
| 506 | - // the next state after the currently-considered one will start off looking the same as the current, but we may make additions... |
|
| 507 | - $theoretical_database_state = $next_database_state_to_consider; |
|
| 508 | - // the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?) |
|
| 509 | - foreach ($script_class_and_filepaths_available as $classname => $filepath) { |
|
| 510 | - $migrates_to_version = $this->script_migrates_to_version($classname); |
|
| 511 | - $script_converts_plugin_slug = $migrates_to_version['slug']; |
|
| 512 | - $script_converts_to_version = $migrates_to_version['version']; |
|
| 513 | - // check if this version script is DONE or not; or if it's never been ran |
|
| 514 | - if ( |
|
| 515 | - ! $scripts_ran || |
|
| 516 | - ! isset($scripts_ran[ $script_converts_plugin_slug ]) || |
|
| 517 | - ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]) |
|
| 518 | - ) { |
|
| 519 | - // we haven't ran this conversion script before |
|
| 520 | - // now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available |
|
| 521 | - $script = LoaderFactory::getLoader()->load($classname); |
|
| 522 | - /* @var $script EE_Data_Migration_Script_Base */ |
|
| 523 | - $can_migrate = $script->can_migrate_from_version($theoretical_database_state); |
|
| 524 | - if ($can_migrate) { |
|
| 525 | - $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script; |
|
| 526 | - $migrates_to_version = $script->migrates_to_version(); |
|
| 527 | - $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version']; |
|
| 528 | - unset($script_class_and_filepaths_available[ $classname ]); |
|
| 529 | - } |
|
| 530 | - } elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) { |
|
| 531 | - // this script has been ran, or at least started |
|
| 532 | - $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]; |
|
| 533 | - if ($script->get_status() != self::status_completed) { |
|
| 534 | - // this script is already underway... keep going with it |
|
| 535 | - $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script; |
|
| 536 | - $migrates_to_version = $script->migrates_to_version(); |
|
| 537 | - $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version']; |
|
| 538 | - unset($script_class_and_filepaths_available[ $classname ]); |
|
| 539 | - } |
|
| 540 | - // else it must have a status that indicates it has finished, so we don't want to try and run it again |
|
| 541 | - } |
|
| 542 | - // else it exists but it's not a proper data migration script |
|
| 543 | - // maybe the script got renamed? or was simply removed from EE? |
|
| 544 | - // either way, its certainly not runnable! |
|
| 545 | - } |
|
| 546 | - $iteration++; |
|
| 547 | - } while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6); |
|
| 548 | - // ok we have all the scripts that should run, now let's make them into flat array |
|
| 549 | - $scripts_that_should_run = array(); |
|
| 550 | - foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) { |
|
| 551 | - ksort($scripts_at_priority); |
|
| 552 | - foreach ($scripts_at_priority as $scripts) { |
|
| 553 | - foreach ($scripts as $script) { |
|
| 554 | - $scripts_that_should_run[ get_class($script) ] = $script; |
|
| 555 | - } |
|
| 556 | - } |
|
| 557 | - } |
|
| 558 | - |
|
| 559 | - do_action( |
|
| 560 | - 'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run', |
|
| 561 | - $scripts_that_should_run |
|
| 562 | - ); |
|
| 563 | - return $scripts_that_should_run; |
|
| 564 | - } |
|
| 565 | - |
|
| 566 | - |
|
| 567 | - /** |
|
| 568 | - * Gets the script which is currently being ran, if there is one. If $include_completed_scripts is set to TRUE |
|
| 569 | - * it will return the last ran script even if its complete. |
|
| 570 | - * This means: if you want to find the currently-executing script, leave it as FALSE. |
|
| 571 | - * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE. |
|
| 572 | - * |
|
| 573 | - * @param bool $include_completed_scripts |
|
| 574 | - * @return EE_Data_Migration_Script_Base |
|
| 575 | - * @throws EE_Error |
|
| 576 | - * @throws EE_Error |
|
| 577 | - */ |
|
| 578 | - public function get_last_ran_script($include_completed_scripts = false) |
|
| 579 | - { |
|
| 580 | - // make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script |
|
| 581 | - if (! $this->_data_migrations_ran) { |
|
| 582 | - $this->get_data_migrations_ran(); |
|
| 583 | - } |
|
| 584 | - if ($include_completed_scripts) { |
|
| 585 | - return $this->_last_ran_script; |
|
| 586 | - } else { |
|
| 587 | - return $this->_last_ran_incomplete_script; |
|
| 588 | - } |
|
| 589 | - } |
|
| 590 | - |
|
| 591 | - |
|
| 592 | - /** |
|
| 593 | - * Runs the data migration scripts (well, each request to this method calls one of the |
|
| 594 | - * data migration scripts' migration_step() functions). |
|
| 595 | - * |
|
| 596 | - * @param int $step_size |
|
| 597 | - * @throws EE_Error |
|
| 598 | - * @return array { |
|
| 599 | - * // where the first item is one EE_Data_Migration_Script_Base's stati, |
|
| 600 | - * //and the second item is a string describing what was done |
|
| 601 | - * @type int $records_to_migrate from the current migration script |
|
| 602 | - * @type int $records_migrated |
|
| 603 | - * @type string $status one of EE_Data_Migration_Manager::status_* |
|
| 604 | - * @type string $script verbose name of the current DMS |
|
| 605 | - * @type string $message string describing what was done during this step |
|
| 606 | - * } |
|
| 607 | - */ |
|
| 608 | - public function migration_step($step_size = 0) |
|
| 609 | - { |
|
| 610 | - |
|
| 611 | - // bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535 |
|
| 612 | - if (class_exists('EE_CPT_Strategy')) { |
|
| 613 | - remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5); |
|
| 614 | - } |
|
| 615 | - |
|
| 616 | - try { |
|
| 617 | - $currently_executing_script = $this->get_last_ran_script(); |
|
| 618 | - if (! $currently_executing_script) { |
|
| 619 | - // Find the next script that needs to execute |
|
| 620 | - $scripts = $this->check_for_applicable_data_migration_scripts(); |
|
| 621 | - if (! $scripts) { |
|
| 622 | - // huh, no more scripts to run... apparently we're done! |
|
| 623 | - // but dont forget to make sure initial data is there |
|
| 624 | - // we should be good to allow them to exit maintenance mode now |
|
| 625 | - EE_Maintenance_Mode::instance()->set_maintenance_level( |
|
| 626 | - intval(EE_Maintenance_Mode::level_0_not_in_maintenance) |
|
| 627 | - ); |
|
| 628 | - // saving migrations ran should actually be unnecessary, but leaving in place just in case |
|
| 629 | - // remember this migration was finished (even if we timeout initing db for core and plugins) |
|
| 630 | - $this->_save_migrations_ran(); |
|
| 631 | - // make sure DB was updated AFTER we've recorded the migration was done |
|
| 632 | - $this->initialize_db_for_enqueued_ee_plugins(); |
|
| 633 | - return array( |
|
| 634 | - 'records_to_migrate' => 1, |
|
| 635 | - 'records_migrated' => 1, |
|
| 636 | - 'status' => self::status_no_more_migration_scripts, |
|
| 637 | - 'script' => __("Data Migration Completed Successfully", "event_espresso"), |
|
| 638 | - 'message' => __("All done!", "event_espresso"), |
|
| 639 | - ); |
|
| 640 | - } |
|
| 641 | - $currently_executing_script = array_shift($scripts); |
|
| 642 | - // and add to the array/wp option showing the scripts ran |
|
| 643 | - |
|
| 644 | - $migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script)); |
|
| 645 | - $plugin_slug = $migrates_to['slug']; |
|
| 646 | - $version = $migrates_to['version']; |
|
| 647 | - $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script; |
|
| 648 | - } |
|
| 649 | - $current_script_name = get_class($currently_executing_script); |
|
| 650 | - } catch (Exception $e) { |
|
| 651 | - // an exception occurred while trying to get migration scripts |
|
| 652 | - |
|
| 653 | - $message = sprintf( |
|
| 654 | - __("Error Message: %sStack Trace:%s", "event_espresso"), |
|
| 655 | - $e->getMessage() . '<br>', |
|
| 656 | - $e->getTraceAsString() |
|
| 657 | - ); |
|
| 658 | - // record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations |
|
| 659 | - // but that's ok-- it's just an FYI to support that we couldn't even run any data migrations |
|
| 660 | - $this->add_error_to_migrations_ran( |
|
| 661 | - sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message) |
|
| 662 | - ); |
|
| 663 | - return array( |
|
| 664 | - 'records_to_migrate' => 1, |
|
| 665 | - 'records_migrated' => 0, |
|
| 666 | - 'status' => self::status_fatal_error, |
|
| 667 | - 'script' => __("Error loading data migration scripts", "event_espresso"), |
|
| 668 | - 'message' => $message, |
|
| 669 | - ); |
|
| 670 | - } |
|
| 671 | - // ok so we definitely have a data migration script |
|
| 672 | - try { |
|
| 673 | - $init_dbs = false; |
|
| 674 | - // how big of a bite do we want to take? Allow users to easily override via their wp-config |
|
| 675 | - if (absint($step_size) < 1) { |
|
| 676 | - $step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE) |
|
| 677 | - ? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size; |
|
| 678 | - } |
|
| 679 | - // do what we came to do! |
|
| 680 | - $currently_executing_script->migration_step($step_size); |
|
| 681 | - // can we wrap it up and verify default data? |
|
| 682 | - switch ($currently_executing_script->get_status()) { |
|
| 683 | - case EE_Data_Migration_Manager::status_continue: |
|
| 684 | - $response_array = array( |
|
| 685 | - 'records_to_migrate' => $currently_executing_script->count_records_to_migrate(), |
|
| 686 | - 'records_migrated' => $currently_executing_script->count_records_migrated(), |
|
| 687 | - 'status' => EE_Data_Migration_Manager::status_continue, |
|
| 688 | - 'message' => $currently_executing_script->get_feedback_message(), |
|
| 689 | - 'script' => $currently_executing_script->pretty_name(), |
|
| 690 | - ); |
|
| 691 | - break; |
|
| 692 | - case EE_Data_Migration_Manager::status_completed: |
|
| 693 | - // ok so THAT script has completed |
|
| 694 | - $this->update_current_database_state_to($this->script_migrates_to_version($current_script_name)); |
|
| 695 | - $response_array = array( |
|
| 696 | - 'records_to_migrate' => $currently_executing_script->count_records_to_migrate(), |
|
| 697 | - 'records_migrated' => $currently_executing_script->count_records_migrated(), |
|
| 698 | - 'status' => EE_Data_Migration_Manager::status_completed, |
|
| 699 | - 'message' => $currently_executing_script->get_feedback_message(), |
|
| 700 | - 'script' => sprintf( |
|
| 701 | - __("%s Completed", 'event_espresso'), |
|
| 702 | - $currently_executing_script->pretty_name() |
|
| 703 | - ), |
|
| 704 | - ); |
|
| 705 | - // check if there are any more after this one. |
|
| 706 | - $scripts_remaining = $this->check_for_applicable_data_migration_scripts(); |
|
| 707 | - if (! $scripts_remaining) { |
|
| 708 | - // we should be good to allow them to exit maintenance mode now |
|
| 709 | - EE_Maintenance_Mode::instance()->set_maintenance_level( |
|
| 710 | - intval(EE_Maintenance_Mode::level_0_not_in_maintenance) |
|
| 711 | - ); |
|
| 712 | - // huh, no more scripts to run... apparently we're done! |
|
| 713 | - // but dont forget to make sure initial data is there |
|
| 714 | - $init_dbs = true; |
|
| 715 | - $response_array['status'] = self::status_no_more_migration_scripts; |
|
| 716 | - } |
|
| 717 | - break; |
|
| 718 | - default: |
|
| 719 | - $response_array = array( |
|
| 720 | - 'records_to_migrate' => $currently_executing_script->count_records_to_migrate(), |
|
| 721 | - 'records_migrated' => $currently_executing_script->count_records_migrated(), |
|
| 722 | - 'status' => $currently_executing_script->get_status(), |
|
| 723 | - 'message' => sprintf( |
|
| 724 | - __("Minor errors occurred during %s: %s", "event_espresso"), |
|
| 725 | - $currently_executing_script->pretty_name(), |
|
| 726 | - implode(", ", $currently_executing_script->get_errors()) |
|
| 727 | - ), |
|
| 728 | - 'script' => $currently_executing_script->pretty_name(), |
|
| 729 | - ); |
|
| 730 | - break; |
|
| 731 | - } |
|
| 732 | - } catch (Exception $e) { |
|
| 733 | - // ok so some exception was thrown which killed the data migration script |
|
| 734 | - // double-check we have a real script |
|
| 735 | - if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) { |
|
| 736 | - $script_name = $currently_executing_script->pretty_name(); |
|
| 737 | - $currently_executing_script->set_broken(); |
|
| 738 | - $currently_executing_script->add_error($e->getMessage()); |
|
| 739 | - } else { |
|
| 740 | - $script_name = __("Error getting Migration Script", "event_espresso"); |
|
| 741 | - } |
|
| 742 | - $response_array = array( |
|
| 743 | - 'records_to_migrate' => 1, |
|
| 744 | - 'records_migrated' => 0, |
|
| 745 | - 'status' => self::status_fatal_error, |
|
| 746 | - 'message' => sprintf( |
|
| 747 | - __("A fatal error occurred during the migration: %s", "event_espresso"), |
|
| 748 | - $e->getMessage() |
|
| 749 | - ), |
|
| 750 | - 'script' => $script_name, |
|
| 751 | - ); |
|
| 752 | - } |
|
| 753 | - $successful_save = $this->_save_migrations_ran(); |
|
| 754 | - if ($successful_save !== true) { |
|
| 755 | - // ok so the current wp option didn't save. that's tricky, because we'd like to update it |
|
| 756 | - // and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION! |
|
| 757 | - // however, if we throw an exception, and return that, then the next request |
|
| 758 | - // won't have as much info in it, and it may be able to save |
|
| 759 | - throw new EE_Error( |
|
| 760 | - sprintf( |
|
| 761 | - __( |
|
| 762 | - "The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.", |
|
| 763 | - "event_espresso" |
|
| 764 | - ), |
|
| 765 | - $successful_save |
|
| 766 | - ) |
|
| 767 | - ); |
|
| 768 | - } |
|
| 769 | - // if we're all done, initialize EE plugins' default data etc. |
|
| 770 | - if ($init_dbs) { |
|
| 771 | - $this->initialize_db_for_enqueued_ee_plugins(); |
|
| 772 | - } |
|
| 773 | - return $response_array; |
|
| 774 | - } |
|
| 775 | - |
|
| 776 | - |
|
| 777 | - /** |
|
| 778 | - * Echo out JSON response to migration script AJAX requests. Takes precautions |
|
| 779 | - * to buffer output so that we don't throw junk into our json. |
|
| 780 | - * |
|
| 781 | - * @return array with keys: |
|
| 782 | - * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie, |
|
| 783 | - * it's NOT the count of hwo many remain) |
|
| 784 | - * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete = |
|
| 785 | - * records_migrated/records_to_migrate) |
|
| 786 | - * 'status'=>a string, one of EE_Data_migration_Manager::status_* |
|
| 787 | - * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into |
|
| 788 | - * errors, notifications, and successes |
|
| 789 | - * 'script'=>a pretty name of the script currently running |
|
| 790 | - */ |
|
| 791 | - public function response_to_migration_ajax_request() |
|
| 792 | - { |
|
| 793 | - ob_start(); |
|
| 794 | - try { |
|
| 795 | - $response = $this->migration_step(); |
|
| 796 | - } catch (Exception $e) { |
|
| 797 | - $response = array( |
|
| 798 | - 'records_to_migrate' => 0, |
|
| 799 | - 'records_migrated' => 0, |
|
| 800 | - 'status' => EE_Data_Migration_Manager::status_fatal_error, |
|
| 801 | - 'message' => sprintf( |
|
| 802 | - __("Unknown fatal error occurred: %s", "event_espresso"), |
|
| 803 | - $e->getMessage() |
|
| 804 | - ), |
|
| 805 | - 'script' => 'Unknown', |
|
| 806 | - ); |
|
| 807 | - $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString()); |
|
| 808 | - } |
|
| 809 | - $warnings_etc = @ob_get_contents(); |
|
| 810 | - ob_end_clean(); |
|
| 811 | - $response['message'] .= $warnings_etc; |
|
| 812 | - return $response; |
|
| 813 | - } |
|
| 814 | - |
|
| 815 | - /** |
|
| 816 | - * Updates the wordpress option that keeps track of which which EE version the database |
|
| 817 | - * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35) |
|
| 818 | - * |
|
| 819 | - * @param array $slug_and_version { |
|
| 820 | - * @type string $slug like 'Core' or 'Calendar', |
|
| 821 | - * @type string $version like '4.1.0' |
|
| 822 | - * } |
|
| 823 | - * @return void |
|
| 824 | - */ |
|
| 825 | - public function update_current_database_state_to($slug_and_version = null) |
|
| 826 | - { |
|
| 827 | - if (! $slug_and_version) { |
|
| 828 | - // no version was provided, assume it should be at the current code version |
|
| 829 | - $slug_and_version = array('slug' => 'Core', 'version' => espresso_version()); |
|
| 830 | - } |
|
| 831 | - $current_database_state = get_option(self::current_database_state); |
|
| 832 | - $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version']; |
|
| 833 | - update_option(self::current_database_state, $current_database_state); |
|
| 834 | - } |
|
| 835 | - |
|
| 836 | - /** |
|
| 837 | - * Determines if the database is currently at a state matching what's indicated in $slug and $version. |
|
| 838 | - * |
|
| 839 | - * @param array $slug_and_version { |
|
| 840 | - * @type string $slug like 'Core' or 'Calendar', |
|
| 841 | - * @type string $version like '4.1.0' |
|
| 842 | - * } |
|
| 843 | - * @return boolean |
|
| 844 | - */ |
|
| 845 | - public function database_needs_updating_to($slug_and_version) |
|
| 846 | - { |
|
| 847 | - |
|
| 848 | - $slug = $slug_and_version['slug']; |
|
| 849 | - $version = $slug_and_version['version']; |
|
| 850 | - $current_database_state = get_option(self::current_database_state); |
|
| 851 | - if (! isset($current_database_state[ $slug ])) { |
|
| 852 | - return true; |
|
| 853 | - } else { |
|
| 854 | - // just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes |
|
| 855 | - $version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3); |
|
| 856 | - $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3); |
|
| 857 | - $needs_updating = false; |
|
| 858 | - foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) { |
|
| 859 | - if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) { |
|
| 860 | - $needs_updating = true; |
|
| 861 | - break; |
|
| 862 | - } |
|
| 863 | - } |
|
| 864 | - return $needs_updating; |
|
| 865 | - } |
|
| 866 | - } |
|
| 867 | - |
|
| 868 | - |
|
| 869 | - /** |
|
| 870 | - * Gets all the data migration scripts available in the core folder and folders |
|
| 871 | - * in addons. Has the side effect of adding them for autoloading |
|
| 872 | - * |
|
| 873 | - * @return array keys are expected classnames, values are their filepaths |
|
| 874 | - * @throws InvalidInterfaceException |
|
| 875 | - * @throws InvalidDataTypeException |
|
| 876 | - * @throws EE_Error |
|
| 877 | - * @throws InvalidArgumentException |
|
| 878 | - */ |
|
| 879 | - public function get_all_data_migration_scripts_available() |
|
| 880 | - { |
|
| 881 | - if (! $this->_data_migration_class_to_filepath_map) { |
|
| 882 | - $this->_data_migration_class_to_filepath_map = array(); |
|
| 883 | - foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) { |
|
| 884 | - // strip any placeholders added to classname to make it a unique array key |
|
| 885 | - $eeAddonClass = trim($eeAddonClass, '*'); |
|
| 886 | - $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass) |
|
| 887 | - ? $eeAddonClass |
|
| 888 | - : ''; |
|
| 889 | - $folder_path = EEH_File::end_with_directory_separator($folder_path); |
|
| 890 | - $files = glob($folder_path . '*.dms.php'); |
|
| 891 | - if (empty($files)) { |
|
| 892 | - continue; |
|
| 893 | - } |
|
| 894 | - foreach ($files as $file) { |
|
| 895 | - $pos_of_last_slash = strrpos($file, '/'); |
|
| 896 | - $classname = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1)); |
|
| 897 | - $migrates_to = $this->script_migrates_to_version($classname, $eeAddonClass); |
|
| 898 | - $slug = $migrates_to['slug']; |
|
| 899 | - // check that the slug as contained in the DMS is associated with |
|
| 900 | - // the slug of an addon or core |
|
| 901 | - if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) { |
|
| 902 | - EE_Error::doing_it_wrong( |
|
| 903 | - __FUNCTION__, |
|
| 904 | - sprintf( |
|
| 905 | - esc_html__( |
|
| 906 | - 'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ', |
|
| 907 | - 'event_espresso' |
|
| 908 | - ), |
|
| 909 | - $classname, |
|
| 910 | - $slug, |
|
| 911 | - implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name())) |
|
| 912 | - ), |
|
| 913 | - '4.3.0.alpha.019' |
|
| 914 | - ); |
|
| 915 | - } |
|
| 916 | - $this->_data_migration_class_to_filepath_map[ $classname ] = $file; |
|
| 917 | - } |
|
| 918 | - } |
|
| 919 | - EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map); |
|
| 920 | - } |
|
| 921 | - return $this->_data_migration_class_to_filepath_map; |
|
| 922 | - } |
|
| 923 | - |
|
| 924 | - |
|
| 925 | - /** |
|
| 926 | - * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs |
|
| 927 | - * from each addon, and check if they need updating, |
|
| 928 | - * |
|
| 929 | - * @return boolean |
|
| 930 | - */ |
|
| 931 | - public function addons_need_updating() |
|
| 932 | - { |
|
| 933 | - return false; |
|
| 934 | - } |
|
| 935 | - |
|
| 936 | - |
|
| 937 | - /** |
|
| 938 | - * Adds this error string to the data_migrations_ran array, but we dont necessarily know |
|
| 939 | - * where to put it, so we just throw it in there... better than nothing... |
|
| 940 | - * |
|
| 941 | - * @param string $error_message |
|
| 942 | - */ |
|
| 943 | - public function add_error_to_migrations_ran($error_message) |
|
| 944 | - { |
|
| 945 | - // get last-ran migration script |
|
| 946 | - global $wpdb; |
|
| 947 | - $last_migration_script_option = $wpdb->get_row( |
|
| 948 | - "SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1", |
|
| 949 | - ARRAY_A |
|
| 950 | - ); |
|
| 951 | - |
|
| 952 | - $last_ran_migration_script_properties = isset($last_migration_script_option['option_value']) |
|
| 953 | - ? maybe_unserialize($last_migration_script_option['option_value']) : null; |
|
| 954 | - // now, tread lightly because we're here because a FATAL non-catchable error |
|
| 955 | - // was thrown last time when we were trying to run a data migration script |
|
| 956 | - // so the fatal error could have happened while getting the migration script |
|
| 957 | - // or doing running it... |
|
| 958 | - $versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace( |
|
| 959 | - EE_Data_Migration_Manager::data_migration_script_option_prefix, |
|
| 960 | - "", |
|
| 961 | - $last_migration_script_option['option_name'] |
|
| 962 | - ) : null; |
|
| 963 | - |
|
| 964 | - // check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet |
|
| 965 | - // because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done) |
|
| 966 | - if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) { |
|
| 967 | - // ok then just add this error to its list of errors |
|
| 968 | - $last_ran_migration_script_properties['_errors'][] = $error_message; |
|
| 969 | - $last_ran_migration_script_properties['_status'] = self::status_fatal_error; |
|
| 970 | - } else { |
|
| 971 | - // so we don't even know which script was last running |
|
| 972 | - // use the data migration error stub, which is designed specifically for this type of thing |
|
| 973 | - $general_migration_error = new EE_DMS_Unknown_1_0_0(); |
|
| 974 | - $general_migration_error->add_error($error_message); |
|
| 975 | - $general_migration_error->set_broken(); |
|
| 976 | - $last_ran_migration_script_properties = $general_migration_error->properties_as_array(); |
|
| 977 | - $versions_migrated_to = 'Unknown.1.0.0'; |
|
| 978 | - // now just to make sure appears as last (in case the were previously a fatal error like this) |
|
| 979 | - // delete the old one |
|
| 980 | - delete_option(self::data_migration_script_option_prefix . $versions_migrated_to); |
|
| 981 | - } |
|
| 982 | - update_option( |
|
| 983 | - self::data_migration_script_option_prefix . $versions_migrated_to, |
|
| 984 | - $last_ran_migration_script_properties |
|
| 985 | - ); |
|
| 986 | - } |
|
| 987 | - |
|
| 988 | - |
|
| 989 | - /** |
|
| 990 | - * saves what data migrations have ran to the database |
|
| 991 | - * |
|
| 992 | - * @return mixed TRUE if successfully saved migrations ran, string if an error occurred |
|
| 993 | - * @throws EE_Error |
|
| 994 | - * @throws EE_Error |
|
| 995 | - */ |
|
| 996 | - protected function _save_migrations_ran() |
|
| 997 | - { |
|
| 998 | - if ($this->_data_migrations_ran == null) { |
|
| 999 | - $this->get_data_migrations_ran(); |
|
| 1000 | - } |
|
| 1001 | - // now, we don't want to save actual classes to the DB because that's messy |
|
| 1002 | - $successful_updates = true; |
|
| 1003 | - foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) { |
|
| 1004 | - foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) { |
|
| 1005 | - $plugin_slug_for_use_in_option_name = $plugin_slug . "."; |
|
| 1006 | - $option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string; |
|
| 1007 | - $old_option_value = get_option($option_name); |
|
| 1008 | - if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) { |
|
| 1009 | - $script_array_for_saving = $array_or_migration_obj->properties_as_array(); |
|
| 1010 | - if ($old_option_value != $script_array_for_saving) { |
|
| 1011 | - $successful_updates = update_option($option_name, $script_array_for_saving); |
|
| 1012 | - } |
|
| 1013 | - } else {// we don't know what this array-thing is. So just save it as-is |
|
| 1014 | - if ($old_option_value != $array_or_migration_obj) { |
|
| 1015 | - $successful_updates = update_option($option_name, $array_or_migration_obj); |
|
| 1016 | - } |
|
| 1017 | - } |
|
| 1018 | - if (! $successful_updates) { |
|
| 1019 | - global $wpdb; |
|
| 1020 | - return $wpdb->last_error; |
|
| 1021 | - } |
|
| 1022 | - } |
|
| 1023 | - } |
|
| 1024 | - return true; |
|
| 1025 | - // $updated = update_option(self::data_migrations_option_name, $array_of_migrations); |
|
| 1026 | - // if ($updated !== true) { |
|
| 1027 | - // global $wpdb; |
|
| 1028 | - // return $wpdb->last_error; |
|
| 1029 | - // } else { |
|
| 1030 | - // return true; |
|
| 1031 | - // } |
|
| 1032 | - // wp_mail( |
|
| 1033 | - // "[email protected]", |
|
| 1034 | - // time() . " price debug info", |
|
| 1035 | - // "updated: $updated, last error: $last_error, byte length of option: " . strlen( |
|
| 1036 | - // serialize($array_of_migrations) |
|
| 1037 | - // ) |
|
| 1038 | - // ); |
|
| 1039 | - } |
|
| 1040 | - |
|
| 1041 | - /** |
|
| 1042 | - * Takes an array of data migration script properties and re-creates the class from |
|
| 1043 | - * them. The argument $properties_array is assumed to have been made by |
|
| 1044 | - * EE_Data_Migration_Script_Base::properties_as_array() |
|
| 1045 | - * |
|
| 1046 | - * @param array $properties_array |
|
| 1047 | - * @return EE_Data_Migration_Script_Base |
|
| 1048 | - * @throws EE_Error |
|
| 1049 | - */ |
|
| 1050 | - public function _instantiate_script_from_properties_array($properties_array) |
|
| 1051 | - { |
|
| 1052 | - if (! isset($properties_array['class'])) { |
|
| 1053 | - throw new EE_Error( |
|
| 1054 | - sprintf( |
|
| 1055 | - __("Properties array has no 'class' properties. Here's what it has: %s", "event_espresso"), |
|
| 1056 | - implode(",", $properties_array) |
|
| 1057 | - ) |
|
| 1058 | - ); |
|
| 1059 | - } |
|
| 1060 | - $class_name = $properties_array['class']; |
|
| 1061 | - if (! class_exists($class_name)) { |
|
| 1062 | - throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name)); |
|
| 1063 | - } |
|
| 1064 | - $class = new $class_name(); |
|
| 1065 | - if (! $class instanceof EE_Data_Migration_Script_Base) { |
|
| 1066 | - throw new EE_Error( |
|
| 1067 | - sprintf( |
|
| 1068 | - __("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"), |
|
| 1069 | - $class_name, |
|
| 1070 | - get_class($class) |
|
| 1071 | - ) |
|
| 1072 | - ); |
|
| 1073 | - } |
|
| 1074 | - $class->instantiate_from_array_of_properties($properties_array); |
|
| 1075 | - return $class; |
|
| 1076 | - } |
|
| 1077 | - |
|
| 1078 | - |
|
| 1079 | - /** |
|
| 1080 | - * Gets the classname for the most up-to-date DMS (ie, the one that will finally |
|
| 1081 | - * leave the DB in a state usable by the current plugin code). |
|
| 1082 | - * |
|
| 1083 | - * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core' |
|
| 1084 | - * @return string |
|
| 1085 | - * @throws EE_Error |
|
| 1086 | - */ |
|
| 1087 | - public function get_most_up_to_date_dms($plugin_slug = 'Core') |
|
| 1088 | - { |
|
| 1089 | - $class_to_filepath_map = $this->get_all_data_migration_scripts_available(); |
|
| 1090 | - $most_up_to_date_dms_classname = null; |
|
| 1091 | - foreach ($class_to_filepath_map as $classname => $filepath) { |
|
| 1092 | - if ($most_up_to_date_dms_classname === null) { |
|
| 1093 | - $migrates_to = $this->script_migrates_to_version($classname); |
|
| 1094 | - $this_plugin_slug = $migrates_to['slug']; |
|
| 1095 | - if ($this_plugin_slug == $plugin_slug) { |
|
| 1096 | - // if it's for core, it wins |
|
| 1097 | - $most_up_to_date_dms_classname = $classname; |
|
| 1098 | - } |
|
| 1099 | - // if it wasn't for core, we must keep searching for one that is! |
|
| 1100 | - continue; |
|
| 1101 | - } else { |
|
| 1102 | - $champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname); |
|
| 1103 | - $contender_migrates_to = $this->script_migrates_to_version($classname); |
|
| 1104 | - if ( |
|
| 1105 | - $contender_migrates_to['slug'] == $plugin_slug |
|
| 1106 | - && version_compare( |
|
| 1107 | - $champion_migrates_to['version'], |
|
| 1108 | - $contender_migrates_to['version'], |
|
| 1109 | - '<' |
|
| 1110 | - ) |
|
| 1111 | - ) { |
|
| 1112 | - // so the contenders version is higher and its for Core |
|
| 1113 | - $most_up_to_date_dms_classname = $classname; |
|
| 1114 | - } |
|
| 1115 | - } |
|
| 1116 | - } |
|
| 1117 | - return $most_up_to_date_dms_classname; |
|
| 1118 | - } |
|
| 1119 | - |
|
| 1120 | - |
|
| 1121 | - /** |
|
| 1122 | - * Gets the migration script specified but ONLY if it has already ran. |
|
| 1123 | - * |
|
| 1124 | - * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has ran, you would run the following code: |
|
| 1125 | - * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !== |
|
| 1126 | - * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or |
|
| 1127 | - * other addon) DMS has ran, in case the current DMS depends on it. |
|
| 1128 | - * |
|
| 1129 | - * @param string $version the version the DMS searched for migrates to. Usually just the content before the 3rd |
|
| 1130 | - * period. Eg '4.1.0' |
|
| 1131 | - * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc |
|
| 1132 | - * @return EE_Data_Migration_Script_Base |
|
| 1133 | - * @throws EE_Error |
|
| 1134 | - * @throws EE_Error |
|
| 1135 | - */ |
|
| 1136 | - public function get_migration_ran($version, $plugin_slug = 'Core') |
|
| 1137 | - { |
|
| 1138 | - $migrations_ran = $this->get_data_migrations_ran(); |
|
| 1139 | - if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) { |
|
| 1140 | - return $migrations_ran[ $plugin_slug ][ $version ]; |
|
| 1141 | - } else { |
|
| 1142 | - return null; |
|
| 1143 | - } |
|
| 1144 | - } |
|
| 1145 | - |
|
| 1146 | - /** |
|
| 1147 | - * Resets the borked data migration scripts so they're no longer borked |
|
| 1148 | - * so we can again attempt to migrate |
|
| 1149 | - * |
|
| 1150 | - * @return bool |
|
| 1151 | - * @throws EE_Error |
|
| 1152 | - */ |
|
| 1153 | - public function reattempt() |
|
| 1154 | - { |
|
| 1155 | - // find if the last-ran script was borked |
|
| 1156 | - // set it as being non-borked (we shouldn't ever get DMSs that we don't recognize) |
|
| 1157 | - // add an 'error' saying that we attempted to reset |
|
| 1158 | - // does it have a stage that was borked too? if so make it no longer borked |
|
| 1159 | - // add an 'error' saying we attempted to reset |
|
| 1160 | - $last_ran_script = $this->get_last_ran_script(); |
|
| 1161 | - if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) { |
|
| 1162 | - // if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it) |
|
| 1163 | - $last_ran_script->set_completed(); |
|
| 1164 | - } elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) { |
|
| 1165 | - $last_ran_script->reattempt(); |
|
| 1166 | - } else { |
|
| 1167 | - throw new EE_Error( |
|
| 1168 | - sprintf( |
|
| 1169 | - __( |
|
| 1170 | - 'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s', |
|
| 1171 | - 'event_espresso' |
|
| 1172 | - ), |
|
| 1173 | - print_r($last_ran_script, true) |
|
| 1174 | - ) |
|
| 1175 | - ); |
|
| 1176 | - } |
|
| 1177 | - return $this->_save_migrations_ran(); |
|
| 1178 | - } |
|
| 1179 | - |
|
| 1180 | - |
|
| 1181 | - /** |
|
| 1182 | - * Gets whether or not this particular migration has run or not |
|
| 1183 | - * |
|
| 1184 | - * @param string $version the version the DMS searched for migrates to. Usually just the content before the 3rd |
|
| 1185 | - * period. Eg '4.1.0' |
|
| 1186 | - * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc |
|
| 1187 | - * @return boolean |
|
| 1188 | - * @throws EE_Error |
|
| 1189 | - */ |
|
| 1190 | - public function migration_has_ran($version, $plugin_slug = 'Core') |
|
| 1191 | - { |
|
| 1192 | - return $this->get_migration_ran($version, $plugin_slug) !== null; |
|
| 1193 | - } |
|
| 1194 | - |
|
| 1195 | - /** |
|
| 1196 | - * Enqueues this ee plugin to have its data initialized |
|
| 1197 | - * |
|
| 1198 | - * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value |
|
| 1199 | - */ |
|
| 1200 | - public function enqueue_db_initialization_for($plugin_slug) |
|
| 1201 | - { |
|
| 1202 | - $queue = $this->get_db_initialization_queue(); |
|
| 1203 | - if (! in_array($plugin_slug, $queue)) { |
|
| 1204 | - $queue[] = $plugin_slug; |
|
| 1205 | - } |
|
| 1206 | - update_option(self::db_init_queue_option_name, $queue); |
|
| 1207 | - } |
|
| 1208 | - |
|
| 1209 | - |
|
| 1210 | - /** |
|
| 1211 | - * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon |
|
| 1212 | - * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is |
|
| 1213 | - * in the queue, calls EE_System::initialize_db_if_no_migrations_required(). |
|
| 1214 | - * |
|
| 1215 | - * @throws EE_Error |
|
| 1216 | - */ |
|
| 1217 | - public function initialize_db_for_enqueued_ee_plugins() |
|
| 1218 | - { |
|
| 1219 | - $queue = $this->get_db_initialization_queue(); |
|
| 1220 | - foreach ($queue as $plugin_slug) { |
|
| 1221 | - $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug); |
|
| 1222 | - if (! $most_up_to_date_dms) { |
|
| 1223 | - // if there is NO DMS for this plugin, obviously there's no schema to verify anyways |
|
| 1224 | - $verify_db = false; |
|
| 1225 | - } else { |
|
| 1226 | - $most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms); |
|
| 1227 | - $verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to); |
|
| 1228 | - } |
|
| 1229 | - if ($plugin_slug == 'Core') { |
|
| 1230 | - EE_System::instance()->initialize_db_if_no_migrations_required( |
|
| 1231 | - false, |
|
| 1232 | - $verify_db |
|
| 1233 | - ); |
|
| 1234 | - } else { |
|
| 1235 | - // just loop through the addons to make sure their database is setup |
|
| 1236 | - foreach (EE_Registry::instance()->addons as $addon) { |
|
| 1237 | - if ($addon->name() == $plugin_slug) { |
|
| 1238 | - $addon->initialize_db_if_no_migrations_required($verify_db); |
|
| 1239 | - break; |
|
| 1240 | - } |
|
| 1241 | - } |
|
| 1242 | - } |
|
| 1243 | - } |
|
| 1244 | - // because we just initialized the DBs for the enqueued ee plugins |
|
| 1245 | - // we don't need to keep remembering which ones needed to be initialized |
|
| 1246 | - delete_option(self::db_init_queue_option_name); |
|
| 1247 | - } |
|
| 1248 | - |
|
| 1249 | - /** |
|
| 1250 | - * Gets a numerically-indexed array of plugin slugs that need to have their databases |
|
| 1251 | - * (re-)initialized after migrations are complete. ie, each element should be either |
|
| 1252 | - * 'Core', or the return value of EE_Addon::name() for an addon |
|
| 1253 | - * |
|
| 1254 | - * @return array |
|
| 1255 | - */ |
|
| 1256 | - public function get_db_initialization_queue() |
|
| 1257 | - { |
|
| 1258 | - return get_option(self::db_init_queue_option_name, array()); |
|
| 1259 | - } |
|
| 1260 | - |
|
| 1261 | - /** |
|
| 1262 | - * Gets the injected table analyzer, or throws an exception |
|
| 1263 | - * |
|
| 1264 | - * @return TableAnalysis |
|
| 1265 | - * @throws EE_Error |
|
| 1266 | - */ |
|
| 1267 | - protected function _get_table_analysis() |
|
| 1268 | - { |
|
| 1269 | - if ($this->_table_analysis instanceof TableAnalysis) { |
|
| 1270 | - return $this->_table_analysis; |
|
| 1271 | - } else { |
|
| 1272 | - throw new EE_Error( |
|
| 1273 | - sprintf( |
|
| 1274 | - __('Table analysis class on class %1$s is not set properly.', 'event_espresso'), |
|
| 1275 | - get_class($this) |
|
| 1276 | - ) |
|
| 1277 | - ); |
|
| 1278 | - } |
|
| 1279 | - } |
|
| 1280 | - |
|
| 1281 | - /** |
|
| 1282 | - * Gets the injected table manager, or throws an exception |
|
| 1283 | - * |
|
| 1284 | - * @return TableManager |
|
| 1285 | - * @throws EE_Error |
|
| 1286 | - */ |
|
| 1287 | - protected function _get_table_manager() |
|
| 1288 | - { |
|
| 1289 | - if ($this->_table_manager instanceof TableManager) { |
|
| 1290 | - return $this->_table_manager; |
|
| 1291 | - } else { |
|
| 1292 | - throw new EE_Error( |
|
| 1293 | - sprintf( |
|
| 1294 | - __('Table manager class on class %1$s is not set properly.', 'event_espresso'), |
|
| 1295 | - get_class($this) |
|
| 1296 | - ) |
|
| 1297 | - ); |
|
| 1298 | - } |
|
| 1299 | - } |
|
| 35 | + /** |
|
| 36 | + * |
|
| 37 | + * @var EE_Registry |
|
| 38 | + */ |
|
| 39 | + // protected $EE; |
|
| 40 | + /** |
|
| 41 | + * name of the wordpress option which stores an array of data about |
|
| 42 | + */ |
|
| 43 | + const data_migrations_option_name = 'ee_data_migration'; |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + const data_migration_script_option_prefix = 'ee_data_migration_script_'; |
|
| 47 | + |
|
| 48 | + const data_migration_script_mapping_option_prefix = 'ee_dms_map_'; |
|
| 49 | + |
|
| 50 | + /** |
|
| 51 | + * name of the wordpress option which stores the database' current version. IE, the code may be at version 4.2.0, |
|
| 52 | + * but as migrations are performed the database will progress from 3.1.35 to 4.1.0 etc. |
|
| 53 | + */ |
|
| 54 | + const current_database_state = 'ee_data_migration_current_db_state'; |
|
| 55 | + |
|
| 56 | + /** |
|
| 57 | + * Special status string returned when we're positive there are no more data migration |
|
| 58 | + * scripts that can be run. |
|
| 59 | + */ |
|
| 60 | + const status_no_more_migration_scripts = 'no_more_migration_scripts'; |
|
| 61 | + /** |
|
| 62 | + * string indicating the migration should continue |
|
| 63 | + */ |
|
| 64 | + const status_continue = 'status_continue'; |
|
| 65 | + /** |
|
| 66 | + * string indicating the migration has completed and should be ended |
|
| 67 | + */ |
|
| 68 | + const status_completed = 'status_completed'; |
|
| 69 | + /** |
|
| 70 | + * string indicating a fatal error occurred and the data migration should be completely aborted |
|
| 71 | + */ |
|
| 72 | + const status_fatal_error = 'status_fatal_error'; |
|
| 73 | + |
|
| 74 | + /** |
|
| 75 | + * the number of 'items' (usually DB rows) to migrate on each 'step' (ajax request sent |
|
| 76 | + * during migration) |
|
| 77 | + */ |
|
| 78 | + const step_size = 50; |
|
| 79 | + |
|
| 80 | + /** |
|
| 81 | + * option name that stores the queue of ee plugins needing to have |
|
| 82 | + * their data initialized (or re-initialized) once we are done migrations |
|
| 83 | + */ |
|
| 84 | + const db_init_queue_option_name = 'ee_db_init_queue'; |
|
| 85 | + /** |
|
| 86 | + * Array of information concerning data migrations that have ran in the history |
|
| 87 | + * of this EE installation. Keys should be the name of the version the script upgraded to |
|
| 88 | + * |
|
| 89 | + * @var EE_Data_Migration_Script_Base[] |
|
| 90 | + */ |
|
| 91 | + private $_data_migrations_ran = null; |
|
| 92 | + /** |
|
| 93 | + * The last ran script. It's nice to store this somewhere accessible, as its easiest |
|
| 94 | + * to know which was the last run by which is the newest wp option; but in most of the code |
|
| 95 | + * we just use the local $_data_migration_ran array, which organized the scripts differently |
|
| 96 | + * |
|
| 97 | + * @var EE_Data_Migration_Script_Base |
|
| 98 | + */ |
|
| 99 | + private $_last_ran_script = null; |
|
| 100 | + |
|
| 101 | + /** |
|
| 102 | + * Similarly to _last_ran_script, but this is the last INCOMPLETE migration script. |
|
| 103 | + * |
|
| 104 | + * @var EE_Data_Migration_Script_Base |
|
| 105 | + */ |
|
| 106 | + private $_last_ran_incomplete_script = null; |
|
| 107 | + /** |
|
| 108 | + * array where keys are classnames, and values are filepaths of all the known migration scripts |
|
| 109 | + * |
|
| 110 | + * @var array |
|
| 111 | + */ |
|
| 112 | + private $_data_migration_class_to_filepath_map; |
|
| 113 | + |
|
| 114 | + /** |
|
| 115 | + * the following 4 properties are fully set on construction. |
|
| 116 | + * Note: the first two apply to whether to continue running ALL migration scripts (ie, even though we're finished |
|
| 117 | + * one, we may want to start the next one); whereas the last two indicate whether to continue running a single |
|
| 118 | + * data migration script |
|
| 119 | + * |
|
| 120 | + * @var array |
|
| 121 | + */ |
|
| 122 | + public $stati_that_indicate_to_continue_migrations = array(); |
|
| 123 | + |
|
| 124 | + public $stati_that_indicate_to_stop_migrations = array(); |
|
| 125 | + |
|
| 126 | + public $stati_that_indicate_to_continue_single_migration_script = array(); |
|
| 127 | + |
|
| 128 | + public $stati_that_indicate_to_stop_single_migration_script = array(); |
|
| 129 | + |
|
| 130 | + /** |
|
| 131 | + * @var TableManager $table_manager |
|
| 132 | + */ |
|
| 133 | + protected $_table_manager; |
|
| 134 | + |
|
| 135 | + /** |
|
| 136 | + * @var TableAnalysis $table_analysis |
|
| 137 | + */ |
|
| 138 | + protected $_table_analysis; |
|
| 139 | + |
|
| 140 | + /** |
|
| 141 | + * @var array $script_migration_versions |
|
| 142 | + */ |
|
| 143 | + protected $script_migration_versions; |
|
| 144 | + |
|
| 145 | + /** |
|
| 146 | + * @var array $dms_folders |
|
| 147 | + */ |
|
| 148 | + protected $dms_folders; |
|
| 149 | + |
|
| 150 | + /** |
|
| 151 | + * @var EE_Data_Migration_Manager $_instance |
|
| 152 | + * @access private |
|
| 153 | + */ |
|
| 154 | + private static $_instance; |
|
| 155 | + |
|
| 156 | + |
|
| 157 | + /** |
|
| 158 | + * @singleton method used to instantiate class object |
|
| 159 | + * @access public |
|
| 160 | + * @return EE_Data_Migration_Manager instance |
|
| 161 | + */ |
|
| 162 | + public static function instance() |
|
| 163 | + { |
|
| 164 | + // check if class object is instantiated |
|
| 165 | + if (! self::$_instance instanceof EE_Data_Migration_Manager) { |
|
| 166 | + self::$_instance = new self(); |
|
| 167 | + } |
|
| 168 | + return self::$_instance; |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + /** |
|
| 172 | + * resets the singleton to its brand-new state (but does NOT delete old references to the old singleton. Meaning, |
|
| 173 | + * all new usages of the singleton should be made with Classname::instance()) and returns it |
|
| 174 | + * |
|
| 175 | + * @return EE_Data_Migration_Manager |
|
| 176 | + */ |
|
| 177 | + public static function reset() |
|
| 178 | + { |
|
| 179 | + self::$_instance = null; |
|
| 180 | + return self::instance(); |
|
| 181 | + } |
|
| 182 | + |
|
| 183 | + |
|
| 184 | + /** |
|
| 185 | + * @throws EE_Error |
|
| 186 | + * @throws ReflectionException |
|
| 187 | + */ |
|
| 188 | + private function __construct() |
|
| 189 | + { |
|
| 190 | + $this->stati_that_indicate_to_continue_migrations = array( |
|
| 191 | + self::status_continue, |
|
| 192 | + self::status_completed, |
|
| 193 | + ); |
|
| 194 | + $this->stati_that_indicate_to_stop_migrations = array( |
|
| 195 | + self::status_fatal_error, |
|
| 196 | + self::status_no_more_migration_scripts, |
|
| 197 | + ); |
|
| 198 | + $this->stati_that_indicate_to_continue_single_migration_script = array( |
|
| 199 | + self::status_continue, |
|
| 200 | + ); |
|
| 201 | + $this->stati_that_indicate_to_stop_single_migration_script = array( |
|
| 202 | + self::status_completed, |
|
| 203 | + self::status_fatal_error |
|
| 204 | + // note: status_no_more_migration_scripts doesn't apply |
|
| 205 | + ); |
|
| 206 | + // make sure we've included the base migration script, because we may need the EE_DMS_Unknown_1_0_0 class |
|
| 207 | + // to be defined, because right now it doesn't get autoloaded on its own |
|
| 208 | + EE_Registry::instance()->load_core('Data_Migration_Class_Base', array(), true); |
|
| 209 | + EE_Registry::instance()->load_core('Data_Migration_Script_Base', array(), true); |
|
| 210 | + EE_Registry::instance()->load_core('DMS_Unknown_1_0_0', array(), true); |
|
| 211 | + EE_Registry::instance()->load_core('Data_Migration_Script_Stage', array(), true); |
|
| 212 | + EE_Registry::instance()->load_core('Data_Migration_Script_Stage_Table', array(), true); |
|
| 213 | + $this->_table_manager = EE_Registry::instance()->create('TableManager', array(), true); |
|
| 214 | + $this->_table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true); |
|
| 215 | + } |
|
| 216 | + |
|
| 217 | + |
|
| 218 | + /** |
|
| 219 | + * Deciphers, from an option's name, what plugin and version it relates to (see _save_migrations_ran to see what |
|
| 220 | + * the option names are like, but generally they're like |
|
| 221 | + * 'ee_data_migration_script_Core.4.1.0' in 4.2 or 'ee_data_migration_script_4.1.0' before that). |
|
| 222 | + * The option name shouldn't ever be like 'ee_data_migration_script_Core.4.1.0.reg' because it's derived, |
|
| 223 | + * indirectly, from the data migration's classname, which should always be like EE_DMS_%s_%d_%d_%d.dms.php (eg |
|
| 224 | + * EE_DMS_Core_4_1_0.dms.php) |
|
| 225 | + * |
|
| 226 | + * @param string $option_name (see EE_Data_Migration_Manage::_save_migrations_ran() where the option name is set) |
|
| 227 | + * @return array where the first item is the plugin slug (eg 'Core','Calendar',etc) and the 2nd is the version of |
|
| 228 | + * that plugin (eg '4.1.0') |
|
| 229 | + */ |
|
| 230 | + private function _get_plugin_slug_and_version_string_from_dms_option_name($option_name) |
|
| 231 | + { |
|
| 232 | + $plugin_slug_and_version_string = str_replace( |
|
| 233 | + EE_Data_Migration_Manager::data_migration_script_option_prefix, |
|
| 234 | + "", |
|
| 235 | + $option_name |
|
| 236 | + ); |
|
| 237 | + // check if $plugin_slug_and_version_string is like '4.1.0' (4.1-style) or 'Core.4.1.0' (4.2-style) |
|
| 238 | + $parts = explode(".", $plugin_slug_and_version_string); |
|
| 239 | + |
|
| 240 | + if (count($parts) == 4) { |
|
| 241 | + // it's 4.2-style.eg Core.4.1.0 |
|
| 242 | + $plugin_slug = $parts[0];// eg Core |
|
| 243 | + $version_string = $parts[1] . "." . $parts[2] . "." . $parts[3]; // eg 4.1.0 |
|
| 244 | + } else { |
|
| 245 | + // it's 4.1-style: eg 4.1.0 |
|
| 246 | + $plugin_slug = 'Core'; |
|
| 247 | + $version_string = $plugin_slug_and_version_string;// eg 4.1.0 |
|
| 248 | + } |
|
| 249 | + return array($plugin_slug, $version_string); |
|
| 250 | + } |
|
| 251 | + |
|
| 252 | + /** |
|
| 253 | + * Gets the DMS class from the wordpress option, otherwise throws an EE_Error if it's not |
|
| 254 | + * for a known DMS class. |
|
| 255 | + * |
|
| 256 | + * @param string $dms_option_name |
|
| 257 | + * @param string $dms_option_value (serialized) |
|
| 258 | + * @return EE_Data_Migration_Script_Base |
|
| 259 | + * @throws EE_Error |
|
| 260 | + */ |
|
| 261 | + private function _get_dms_class_from_wp_option($dms_option_name, $dms_option_value) |
|
| 262 | + { |
|
| 263 | + $data_migration_data = maybe_unserialize($dms_option_value); |
|
| 264 | + if (isset($data_migration_data['class']) && class_exists($data_migration_data['class'])) { |
|
| 265 | + $class = LoaderFactory::getLoader()->getShared($data_migration_data['class']); |
|
| 266 | + if ($class instanceof EE_Data_Migration_Script_Base) { |
|
| 267 | + $class->instantiate_from_array_of_properties($data_migration_data); |
|
| 268 | + return $class; |
|
| 269 | + } else { |
|
| 270 | + // huh, so its an object but not a data migration script?? that shouldn't happen |
|
| 271 | + // just leave it as an array (which will probably just get ignored) |
|
| 272 | + throw new EE_Error( |
|
| 273 | + sprintf( |
|
| 274 | + __( |
|
| 275 | + "Trying to retrieve DMS class from wp option. No DMS by the name '%s' exists", |
|
| 276 | + 'event_espresso' |
|
| 277 | + ), |
|
| 278 | + $data_migration_data['class'] |
|
| 279 | + ) |
|
| 280 | + ); |
|
| 281 | + } |
|
| 282 | + } else { |
|
| 283 | + // so the data doesn't specify a class. So it must either be a legacy array of info or some array (which we'll probably just ignore), or a class that no longer exists |
|
| 284 | + throw new EE_Error( |
|
| 285 | + sprintf(__("The wp option with key '%s' does not represent a DMS", 'event_espresso'), $dms_option_name) |
|
| 286 | + ); |
|
| 287 | + } |
|
| 288 | + } |
|
| 289 | + |
|
| 290 | + |
|
| 291 | + /** |
|
| 292 | + * Gets the array describing what data migrations have run. Also has a side-effect of recording which was the last |
|
| 293 | + * ran, and which was the last ran which hasn't finished yet |
|
| 294 | + * |
|
| 295 | + * @return array where each element should be an array of EE_Data_Migration_Script_Base (but also has a few legacy |
|
| 296 | + * arrays in there - which should probably be ignored) |
|
| 297 | + * @throws EE_Error |
|
| 298 | + */ |
|
| 299 | + public function get_data_migrations_ran() |
|
| 300 | + { |
|
| 301 | + if (! $this->_data_migrations_ran) { |
|
| 302 | + // setup autoloaders for each of the scripts in there |
|
| 303 | + $this->get_all_data_migration_scripts_available(); |
|
| 304 | + $data_migrations_options = $this->get_all_migration_script_options( |
|
| 305 | + );// get_option(EE_Data_Migration_Manager::data_migrations_option_name,get_option('espresso_data_migrations',array())); |
|
| 306 | + |
|
| 307 | + $data_migrations_ran = array(); |
|
| 308 | + // convert into data migration script classes where possible |
|
| 309 | + foreach ($data_migrations_options as $data_migration_option) { |
|
| 310 | + list($plugin_slug, $version_string) = $this->_get_plugin_slug_and_version_string_from_dms_option_name( |
|
| 311 | + $data_migration_option['option_name'] |
|
| 312 | + ); |
|
| 313 | + |
|
| 314 | + try { |
|
| 315 | + $class = $this->_get_dms_class_from_wp_option( |
|
| 316 | + $data_migration_option['option_name'], |
|
| 317 | + $data_migration_option['option_value'] |
|
| 318 | + ); |
|
| 319 | + $data_migrations_ran[ $plugin_slug ][ $version_string ] = $class; |
|
| 320 | + // ok so far THIS is the 'last-ran-script'... unless we find another on next iteration |
|
| 321 | + $this->_last_ran_script = $class; |
|
| 322 | + if (! $class->is_completed()) { |
|
| 323 | + // sometimes we also like to know which was the last incomplete script (or if there are any at all) |
|
| 324 | + $this->_last_ran_incomplete_script = $class; |
|
| 325 | + } |
|
| 326 | + } catch (EE_Error $e) { |
|
| 327 | + // ok so its not a DMS. We'll just keep it, although other code will need to expect non-DMSs |
|
| 328 | + $data_migrations_ran[ $plugin_slug ][ $version_string ] = maybe_unserialize( |
|
| 329 | + $data_migration_option['option_value'] |
|
| 330 | + ); |
|
| 331 | + } |
|
| 332 | + } |
|
| 333 | + // so here the array of $data_migrations_ran is actually a mix of classes and a few legacy arrays |
|
| 334 | + $this->_data_migrations_ran = $data_migrations_ran; |
|
| 335 | + if (! $this->_data_migrations_ran || ! is_array($this->_data_migrations_ran)) { |
|
| 336 | + $this->_data_migrations_ran = array(); |
|
| 337 | + } |
|
| 338 | + } |
|
| 339 | + return $this->_data_migrations_ran; |
|
| 340 | + } |
|
| 341 | + |
|
| 342 | + |
|
| 343 | + /** |
|
| 344 | + * |
|
| 345 | + * @param string $script_name eg 'DMS_Core_4_1_0' |
|
| 346 | + * @param string $old_table eg 'wp_events_detail' |
|
| 347 | + * @param string $old_pk eg 'wp_esp_posts' |
|
| 348 | + * @param $new_table |
|
| 349 | + * @return mixed string or int |
|
| 350 | + * @throws EE_Error |
|
| 351 | + * @throws ReflectionException |
|
| 352 | + */ |
|
| 353 | + public function get_mapping_new_pk($script_name, $old_table, $old_pk, $new_table) |
|
| 354 | + { |
|
| 355 | + $script = EE_Registry::instance()->load_dms($script_name); |
|
| 356 | + return $script->get_mapping_new_pk($old_table, $old_pk, $new_table); |
|
| 357 | + } |
|
| 358 | + |
|
| 359 | + /** |
|
| 360 | + * Gets all the options containing migration scripts that have been run. Ordering is important: it's assumed that |
|
| 361 | + * the last option returned in this array is the most-recently ran DMS option |
|
| 362 | + * |
|
| 363 | + * @return array |
|
| 364 | + */ |
|
| 365 | + public function get_all_migration_script_options() |
|
| 366 | + { |
|
| 367 | + global $wpdb; |
|
| 368 | + return $wpdb->get_results( |
|
| 369 | + "SELECT * FROM {$wpdb->options} WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id ASC", |
|
| 370 | + ARRAY_A |
|
| 371 | + ); |
|
| 372 | + } |
|
| 373 | + |
|
| 374 | + /** |
|
| 375 | + * Gets the array of folders which contain data migration scripts. Also adds them to be auto-loaded |
|
| 376 | + * |
|
| 377 | + * @return array where each value is the full folder path of a folder containing data migration scripts, WITH |
|
| 378 | + * slashes at the end of the folder name. |
|
| 379 | + */ |
|
| 380 | + public function get_data_migration_script_folders() |
|
| 381 | + { |
|
| 382 | + if (empty($this->dms_folders)) { |
|
| 383 | + $this->dms_folders = apply_filters( |
|
| 384 | + 'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders', |
|
| 385 | + array('Core' => EE_CORE . 'data_migration_scripts') |
|
| 386 | + ); |
|
| 387 | + } |
|
| 388 | + return $this->dms_folders; |
|
| 389 | + } |
|
| 390 | + |
|
| 391 | + /** |
|
| 392 | + * Gets the version the migration script upgrades to |
|
| 393 | + * |
|
| 394 | + * @param string $migration_script_name eg 'EE_DMS_Core_4_1_0' |
|
| 395 | + * @return array { |
|
| 396 | + * @type string $slug like 'Core','Calendar',etc |
|
| 397 | + * @type string $version like 4.3.0 |
|
| 398 | + * } |
|
| 399 | + * @throws EE_Error |
|
| 400 | + */ |
|
| 401 | + public function script_migrates_to_version($migration_script_name, $eeAddonClass = '') |
|
| 402 | + { |
|
| 403 | + if (isset($this->script_migration_versions[ $migration_script_name ])) { |
|
| 404 | + return $this->script_migration_versions[ $migration_script_name ]; |
|
| 405 | + } |
|
| 406 | + $dms_info = $this->parse_dms_classname($migration_script_name); |
|
| 407 | + $this->script_migration_versions[ $migration_script_name ] = array( |
|
| 408 | + 'slug' => $eeAddonClass !== '' ? $eeAddonClass : $dms_info['slug'], |
|
| 409 | + 'version' => $dms_info['major_version'] . "." . $dms_info['minor_version'] . "." . $dms_info['micro_version'], |
|
| 410 | + ); |
|
| 411 | + return $this->script_migration_versions[ $migration_script_name ]; |
|
| 412 | + } |
|
| 413 | + |
|
| 414 | + /** |
|
| 415 | + * Gets the juicy details out of a dms filename like 'EE_DMS_Core_4_1_0' |
|
| 416 | + * |
|
| 417 | + * @param string $classname |
|
| 418 | + * @return array with keys 'slug','major_version','minor_version', and 'micro_version' (the last 3 are ints) |
|
| 419 | + * @throws EE_Error |
|
| 420 | + */ |
|
| 421 | + public function parse_dms_classname($classname) |
|
| 422 | + { |
|
| 423 | + $matches = array(); |
|
| 424 | + preg_match('~EE_DMS_(.*)_([0-9]*)_([0-9]*)_([0-9]*)~', $classname, $matches); |
|
| 425 | + if (! $matches || ! (isset($matches[1]) && isset($matches[2]) && isset($matches[3]))) { |
|
| 426 | + throw new EE_Error( |
|
| 427 | + sprintf( |
|
| 428 | + __( |
|
| 429 | + "%s is not a valid Data Migration Script. The classname should be like EE_DMS_w_x_y_z, where w is either 'Core' or the slug of an addon and x, y and z are numbers, ", |
|
| 430 | + "event_espresso" |
|
| 431 | + ), |
|
| 432 | + $classname |
|
| 433 | + ) |
|
| 434 | + ); |
|
| 435 | + } |
|
| 436 | + return array( |
|
| 437 | + 'slug' => $matches[1], |
|
| 438 | + 'major_version' => intval($matches[2]), |
|
| 439 | + 'minor_version' => intval($matches[3]), |
|
| 440 | + 'micro_version' => intval($matches[4]), |
|
| 441 | + ); |
|
| 442 | + } |
|
| 443 | + |
|
| 444 | + /** |
|
| 445 | + * Ensures that the option indicating the current DB version is set. This should only be |
|
| 446 | + * a concern when activating EE for the first time, THEORETICALLY. |
|
| 447 | + * If we detect that we're activating EE4 over top of EE3.1, then we set the current db state to 3.1.x, otherwise |
|
| 448 | + * to 4.1.x. |
|
| 449 | + * |
|
| 450 | + * @return string of current db state |
|
| 451 | + */ |
|
| 452 | + public function ensure_current_database_state_is_set() |
|
| 453 | + { |
|
| 454 | + $espresso_db_core_updates = get_option('espresso_db_update', array()); |
|
| 455 | + $db_state = get_option(EE_Data_Migration_Manager::current_database_state); |
|
| 456 | + if (! $db_state) { |
|
| 457 | + // mark the DB as being in the state as the last version in there. |
|
| 458 | + // this is done to trigger maintenance mode and do data migration scripts |
|
| 459 | + // if the admin installed this version of EE over 3.1.x or 4.0.x |
|
| 460 | + // otherwise, the normal maintenance mode code is fine |
|
| 461 | + $previous_versions_installed = array_keys($espresso_db_core_updates); |
|
| 462 | + $previous_version_installed = end($previous_versions_installed); |
|
| 463 | + if (version_compare('4.1.0', $previous_version_installed)) { |
|
| 464 | + // last installed version was less than 4.1 |
|
| 465 | + // so we want the data migrations to happen. SO, we're going to say the DB is at that state |
|
| 466 | + $db_state = array('Core' => $previous_version_installed); |
|
| 467 | + } else { |
|
| 468 | + $db_state = array('Core' => EVENT_ESPRESSO_VERSION); |
|
| 469 | + } |
|
| 470 | + update_option(EE_Data_Migration_Manager::current_database_state, $db_state); |
|
| 471 | + } |
|
| 472 | + // in 4.1, $db_state would have only been a simple string like '4.1.0', |
|
| 473 | + // but in 4.2+ it should be an array with at least key 'Core' and the value of that plugin's |
|
| 474 | + // db, and possibly other keys for other addons like 'Calendar','Permissions',etc |
|
| 475 | + if (! is_array($db_state)) { |
|
| 476 | + $db_state = array('Core' => $db_state); |
|
| 477 | + update_option(EE_Data_Migration_Manager::current_database_state, $db_state); |
|
| 478 | + } |
|
| 479 | + return $db_state; |
|
| 480 | + } |
|
| 481 | + |
|
| 482 | + |
|
| 483 | + /** |
|
| 484 | + * Checks if there are any data migration scripts that ought to be run. If found, |
|
| 485 | + * returns the instantiated classes. If none are found (ie, they've all already been run |
|
| 486 | + * or they don't apply), returns an empty array |
|
| 487 | + * |
|
| 488 | + * @return EE_Data_Migration_Script_Base[] |
|
| 489 | + * @throws EE_Error |
|
| 490 | + */ |
|
| 491 | + public function check_for_applicable_data_migration_scripts() |
|
| 492 | + { |
|
| 493 | + // get the option describing what options have already run |
|
| 494 | + $scripts_ran = $this->get_data_migrations_ran(); |
|
| 495 | + // $scripts_ran = array('4.1.0.core'=>array('monkey'=>null)); |
|
| 496 | + $script_class_and_filepaths_available = $this->get_all_data_migration_scripts_available(); |
|
| 497 | + |
|
| 498 | + |
|
| 499 | + $current_database_state = $this->ensure_current_database_state_is_set(); |
|
| 500 | + // determine which have already been run |
|
| 501 | + $script_classes_that_should_run_per_iteration = array(); |
|
| 502 | + $iteration = 0; |
|
| 503 | + $next_database_state_to_consider = $current_database_state; |
|
| 504 | + $theoretical_database_state = null; |
|
| 505 | + do { |
|
| 506 | + // the next state after the currently-considered one will start off looking the same as the current, but we may make additions... |
|
| 507 | + $theoretical_database_state = $next_database_state_to_consider; |
|
| 508 | + // the next db state to consider is "what would the DB be like had we run all the scripts we found that applied last time?) |
|
| 509 | + foreach ($script_class_and_filepaths_available as $classname => $filepath) { |
|
| 510 | + $migrates_to_version = $this->script_migrates_to_version($classname); |
|
| 511 | + $script_converts_plugin_slug = $migrates_to_version['slug']; |
|
| 512 | + $script_converts_to_version = $migrates_to_version['version']; |
|
| 513 | + // check if this version script is DONE or not; or if it's never been ran |
|
| 514 | + if ( |
|
| 515 | + ! $scripts_ran || |
|
| 516 | + ! isset($scripts_ran[ $script_converts_plugin_slug ]) || |
|
| 517 | + ! isset($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]) |
|
| 518 | + ) { |
|
| 519 | + // we haven't ran this conversion script before |
|
| 520 | + // now check if it applies... note that we've added an autoloader for it on get_all_data_migration_scripts_available |
|
| 521 | + $script = LoaderFactory::getLoader()->load($classname); |
|
| 522 | + /* @var $script EE_Data_Migration_Script_Base */ |
|
| 523 | + $can_migrate = $script->can_migrate_from_version($theoretical_database_state); |
|
| 524 | + if ($can_migrate) { |
|
| 525 | + $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script; |
|
| 526 | + $migrates_to_version = $script->migrates_to_version(); |
|
| 527 | + $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version']; |
|
| 528 | + unset($script_class_and_filepaths_available[ $classname ]); |
|
| 529 | + } |
|
| 530 | + } elseif ($scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ] instanceof EE_Data_Migration_Script_Base) { |
|
| 531 | + // this script has been ran, or at least started |
|
| 532 | + $script = $scripts_ran[ $script_converts_plugin_slug ][ $script_converts_to_version ]; |
|
| 533 | + if ($script->get_status() != self::status_completed) { |
|
| 534 | + // this script is already underway... keep going with it |
|
| 535 | + $script_classes_that_should_run_per_iteration[ $iteration ][ $script->priority() ][] = $script; |
|
| 536 | + $migrates_to_version = $script->migrates_to_version(); |
|
| 537 | + $next_database_state_to_consider[ $migrates_to_version['slug'] ] = $migrates_to_version['version']; |
|
| 538 | + unset($script_class_and_filepaths_available[ $classname ]); |
|
| 539 | + } |
|
| 540 | + // else it must have a status that indicates it has finished, so we don't want to try and run it again |
|
| 541 | + } |
|
| 542 | + // else it exists but it's not a proper data migration script |
|
| 543 | + // maybe the script got renamed? or was simply removed from EE? |
|
| 544 | + // either way, its certainly not runnable! |
|
| 545 | + } |
|
| 546 | + $iteration++; |
|
| 547 | + } while ($next_database_state_to_consider != $theoretical_database_state && $iteration < 6); |
|
| 548 | + // ok we have all the scripts that should run, now let's make them into flat array |
|
| 549 | + $scripts_that_should_run = array(); |
|
| 550 | + foreach ($script_classes_that_should_run_per_iteration as $scripts_at_priority) { |
|
| 551 | + ksort($scripts_at_priority); |
|
| 552 | + foreach ($scripts_at_priority as $scripts) { |
|
| 553 | + foreach ($scripts as $script) { |
|
| 554 | + $scripts_that_should_run[ get_class($script) ] = $script; |
|
| 555 | + } |
|
| 556 | + } |
|
| 557 | + } |
|
| 558 | + |
|
| 559 | + do_action( |
|
| 560 | + 'AHEE__EE_Data_Migration_Manager__check_for_applicable_data_migration_scripts__scripts_that_should_run', |
|
| 561 | + $scripts_that_should_run |
|
| 562 | + ); |
|
| 563 | + return $scripts_that_should_run; |
|
| 564 | + } |
|
| 565 | + |
|
| 566 | + |
|
| 567 | + /** |
|
| 568 | + * Gets the script which is currently being ran, if there is one. If $include_completed_scripts is set to TRUE |
|
| 569 | + * it will return the last ran script even if its complete. |
|
| 570 | + * This means: if you want to find the currently-executing script, leave it as FALSE. |
|
| 571 | + * If you really just want to find the script which ran most recently, regardless of status, leave it as TRUE. |
|
| 572 | + * |
|
| 573 | + * @param bool $include_completed_scripts |
|
| 574 | + * @return EE_Data_Migration_Script_Base |
|
| 575 | + * @throws EE_Error |
|
| 576 | + * @throws EE_Error |
|
| 577 | + */ |
|
| 578 | + public function get_last_ran_script($include_completed_scripts = false) |
|
| 579 | + { |
|
| 580 | + // make sure we've setup the class properties _last_ran_script and _last_ran_incomplete_script |
|
| 581 | + if (! $this->_data_migrations_ran) { |
|
| 582 | + $this->get_data_migrations_ran(); |
|
| 583 | + } |
|
| 584 | + if ($include_completed_scripts) { |
|
| 585 | + return $this->_last_ran_script; |
|
| 586 | + } else { |
|
| 587 | + return $this->_last_ran_incomplete_script; |
|
| 588 | + } |
|
| 589 | + } |
|
| 590 | + |
|
| 591 | + |
|
| 592 | + /** |
|
| 593 | + * Runs the data migration scripts (well, each request to this method calls one of the |
|
| 594 | + * data migration scripts' migration_step() functions). |
|
| 595 | + * |
|
| 596 | + * @param int $step_size |
|
| 597 | + * @throws EE_Error |
|
| 598 | + * @return array { |
|
| 599 | + * // where the first item is one EE_Data_Migration_Script_Base's stati, |
|
| 600 | + * //and the second item is a string describing what was done |
|
| 601 | + * @type int $records_to_migrate from the current migration script |
|
| 602 | + * @type int $records_migrated |
|
| 603 | + * @type string $status one of EE_Data_Migration_Manager::status_* |
|
| 604 | + * @type string $script verbose name of the current DMS |
|
| 605 | + * @type string $message string describing what was done during this step |
|
| 606 | + * } |
|
| 607 | + */ |
|
| 608 | + public function migration_step($step_size = 0) |
|
| 609 | + { |
|
| 610 | + |
|
| 611 | + // bandaid fix for issue https://events.codebasehq.com/projects/event-espresso/tickets/7535 |
|
| 612 | + if (class_exists('EE_CPT_Strategy')) { |
|
| 613 | + remove_action('pre_get_posts', array(EE_CPT_Strategy::instance(), 'pre_get_posts'), 5); |
|
| 614 | + } |
|
| 615 | + |
|
| 616 | + try { |
|
| 617 | + $currently_executing_script = $this->get_last_ran_script(); |
|
| 618 | + if (! $currently_executing_script) { |
|
| 619 | + // Find the next script that needs to execute |
|
| 620 | + $scripts = $this->check_for_applicable_data_migration_scripts(); |
|
| 621 | + if (! $scripts) { |
|
| 622 | + // huh, no more scripts to run... apparently we're done! |
|
| 623 | + // but dont forget to make sure initial data is there |
|
| 624 | + // we should be good to allow them to exit maintenance mode now |
|
| 625 | + EE_Maintenance_Mode::instance()->set_maintenance_level( |
|
| 626 | + intval(EE_Maintenance_Mode::level_0_not_in_maintenance) |
|
| 627 | + ); |
|
| 628 | + // saving migrations ran should actually be unnecessary, but leaving in place just in case |
|
| 629 | + // remember this migration was finished (even if we timeout initing db for core and plugins) |
|
| 630 | + $this->_save_migrations_ran(); |
|
| 631 | + // make sure DB was updated AFTER we've recorded the migration was done |
|
| 632 | + $this->initialize_db_for_enqueued_ee_plugins(); |
|
| 633 | + return array( |
|
| 634 | + 'records_to_migrate' => 1, |
|
| 635 | + 'records_migrated' => 1, |
|
| 636 | + 'status' => self::status_no_more_migration_scripts, |
|
| 637 | + 'script' => __("Data Migration Completed Successfully", "event_espresso"), |
|
| 638 | + 'message' => __("All done!", "event_espresso"), |
|
| 639 | + ); |
|
| 640 | + } |
|
| 641 | + $currently_executing_script = array_shift($scripts); |
|
| 642 | + // and add to the array/wp option showing the scripts ran |
|
| 643 | + |
|
| 644 | + $migrates_to = $this->script_migrates_to_version(get_class($currently_executing_script)); |
|
| 645 | + $plugin_slug = $migrates_to['slug']; |
|
| 646 | + $version = $migrates_to['version']; |
|
| 647 | + $this->_data_migrations_ran[ $plugin_slug ][ $version ] = $currently_executing_script; |
|
| 648 | + } |
|
| 649 | + $current_script_name = get_class($currently_executing_script); |
|
| 650 | + } catch (Exception $e) { |
|
| 651 | + // an exception occurred while trying to get migration scripts |
|
| 652 | + |
|
| 653 | + $message = sprintf( |
|
| 654 | + __("Error Message: %sStack Trace:%s", "event_espresso"), |
|
| 655 | + $e->getMessage() . '<br>', |
|
| 656 | + $e->getTraceAsString() |
|
| 657 | + ); |
|
| 658 | + // record it on the array of data migration scripts ran. This will be overwritten next time we try and try to run data migrations |
|
| 659 | + // but that's ok-- it's just an FYI to support that we couldn't even run any data migrations |
|
| 660 | + $this->add_error_to_migrations_ran( |
|
| 661 | + sprintf(__("Could not run data migrations because: %s", "event_espresso"), $message) |
|
| 662 | + ); |
|
| 663 | + return array( |
|
| 664 | + 'records_to_migrate' => 1, |
|
| 665 | + 'records_migrated' => 0, |
|
| 666 | + 'status' => self::status_fatal_error, |
|
| 667 | + 'script' => __("Error loading data migration scripts", "event_espresso"), |
|
| 668 | + 'message' => $message, |
|
| 669 | + ); |
|
| 670 | + } |
|
| 671 | + // ok so we definitely have a data migration script |
|
| 672 | + try { |
|
| 673 | + $init_dbs = false; |
|
| 674 | + // how big of a bite do we want to take? Allow users to easily override via their wp-config |
|
| 675 | + if (absint($step_size) < 1) { |
|
| 676 | + $step_size = defined('EE_MIGRATION_STEP_SIZE') && absint(EE_MIGRATION_STEP_SIZE) |
|
| 677 | + ? EE_MIGRATION_STEP_SIZE : EE_Data_Migration_Manager::step_size; |
|
| 678 | + } |
|
| 679 | + // do what we came to do! |
|
| 680 | + $currently_executing_script->migration_step($step_size); |
|
| 681 | + // can we wrap it up and verify default data? |
|
| 682 | + switch ($currently_executing_script->get_status()) { |
|
| 683 | + case EE_Data_Migration_Manager::status_continue: |
|
| 684 | + $response_array = array( |
|
| 685 | + 'records_to_migrate' => $currently_executing_script->count_records_to_migrate(), |
|
| 686 | + 'records_migrated' => $currently_executing_script->count_records_migrated(), |
|
| 687 | + 'status' => EE_Data_Migration_Manager::status_continue, |
|
| 688 | + 'message' => $currently_executing_script->get_feedback_message(), |
|
| 689 | + 'script' => $currently_executing_script->pretty_name(), |
|
| 690 | + ); |
|
| 691 | + break; |
|
| 692 | + case EE_Data_Migration_Manager::status_completed: |
|
| 693 | + // ok so THAT script has completed |
|
| 694 | + $this->update_current_database_state_to($this->script_migrates_to_version($current_script_name)); |
|
| 695 | + $response_array = array( |
|
| 696 | + 'records_to_migrate' => $currently_executing_script->count_records_to_migrate(), |
|
| 697 | + 'records_migrated' => $currently_executing_script->count_records_migrated(), |
|
| 698 | + 'status' => EE_Data_Migration_Manager::status_completed, |
|
| 699 | + 'message' => $currently_executing_script->get_feedback_message(), |
|
| 700 | + 'script' => sprintf( |
|
| 701 | + __("%s Completed", 'event_espresso'), |
|
| 702 | + $currently_executing_script->pretty_name() |
|
| 703 | + ), |
|
| 704 | + ); |
|
| 705 | + // check if there are any more after this one. |
|
| 706 | + $scripts_remaining = $this->check_for_applicable_data_migration_scripts(); |
|
| 707 | + if (! $scripts_remaining) { |
|
| 708 | + // we should be good to allow them to exit maintenance mode now |
|
| 709 | + EE_Maintenance_Mode::instance()->set_maintenance_level( |
|
| 710 | + intval(EE_Maintenance_Mode::level_0_not_in_maintenance) |
|
| 711 | + ); |
|
| 712 | + // huh, no more scripts to run... apparently we're done! |
|
| 713 | + // but dont forget to make sure initial data is there |
|
| 714 | + $init_dbs = true; |
|
| 715 | + $response_array['status'] = self::status_no_more_migration_scripts; |
|
| 716 | + } |
|
| 717 | + break; |
|
| 718 | + default: |
|
| 719 | + $response_array = array( |
|
| 720 | + 'records_to_migrate' => $currently_executing_script->count_records_to_migrate(), |
|
| 721 | + 'records_migrated' => $currently_executing_script->count_records_migrated(), |
|
| 722 | + 'status' => $currently_executing_script->get_status(), |
|
| 723 | + 'message' => sprintf( |
|
| 724 | + __("Minor errors occurred during %s: %s", "event_espresso"), |
|
| 725 | + $currently_executing_script->pretty_name(), |
|
| 726 | + implode(", ", $currently_executing_script->get_errors()) |
|
| 727 | + ), |
|
| 728 | + 'script' => $currently_executing_script->pretty_name(), |
|
| 729 | + ); |
|
| 730 | + break; |
|
| 731 | + } |
|
| 732 | + } catch (Exception $e) { |
|
| 733 | + // ok so some exception was thrown which killed the data migration script |
|
| 734 | + // double-check we have a real script |
|
| 735 | + if ($currently_executing_script instanceof EE_Data_Migration_Script_Base) { |
|
| 736 | + $script_name = $currently_executing_script->pretty_name(); |
|
| 737 | + $currently_executing_script->set_broken(); |
|
| 738 | + $currently_executing_script->add_error($e->getMessage()); |
|
| 739 | + } else { |
|
| 740 | + $script_name = __("Error getting Migration Script", "event_espresso"); |
|
| 741 | + } |
|
| 742 | + $response_array = array( |
|
| 743 | + 'records_to_migrate' => 1, |
|
| 744 | + 'records_migrated' => 0, |
|
| 745 | + 'status' => self::status_fatal_error, |
|
| 746 | + 'message' => sprintf( |
|
| 747 | + __("A fatal error occurred during the migration: %s", "event_espresso"), |
|
| 748 | + $e->getMessage() |
|
| 749 | + ), |
|
| 750 | + 'script' => $script_name, |
|
| 751 | + ); |
|
| 752 | + } |
|
| 753 | + $successful_save = $this->_save_migrations_ran(); |
|
| 754 | + if ($successful_save !== true) { |
|
| 755 | + // ok so the current wp option didn't save. that's tricky, because we'd like to update it |
|
| 756 | + // and mark it as having a fatal error, but remember- WE CAN'T SAVE THIS WP OPTION! |
|
| 757 | + // however, if we throw an exception, and return that, then the next request |
|
| 758 | + // won't have as much info in it, and it may be able to save |
|
| 759 | + throw new EE_Error( |
|
| 760 | + sprintf( |
|
| 761 | + __( |
|
| 762 | + "The error '%s' occurred updating the status of the migration. This is a FATAL ERROR, but the error is preventing the system from remembering that. Please contact event espresso support.", |
|
| 763 | + "event_espresso" |
|
| 764 | + ), |
|
| 765 | + $successful_save |
|
| 766 | + ) |
|
| 767 | + ); |
|
| 768 | + } |
|
| 769 | + // if we're all done, initialize EE plugins' default data etc. |
|
| 770 | + if ($init_dbs) { |
|
| 771 | + $this->initialize_db_for_enqueued_ee_plugins(); |
|
| 772 | + } |
|
| 773 | + return $response_array; |
|
| 774 | + } |
|
| 775 | + |
|
| 776 | + |
|
| 777 | + /** |
|
| 778 | + * Echo out JSON response to migration script AJAX requests. Takes precautions |
|
| 779 | + * to buffer output so that we don't throw junk into our json. |
|
| 780 | + * |
|
| 781 | + * @return array with keys: |
|
| 782 | + * 'records_to_migrate' which counts ALL the records for the current migration, and should remain constant. (ie, |
|
| 783 | + * it's NOT the count of hwo many remain) |
|
| 784 | + * 'records_migrated' which also counts ALL the records which have been migrated (ie, percent_complete = |
|
| 785 | + * records_migrated/records_to_migrate) |
|
| 786 | + * 'status'=>a string, one of EE_Data_migration_Manager::status_* |
|
| 787 | + * 'message'=>a string, containing any message you want to show to the user. We may decide to split this up into |
|
| 788 | + * errors, notifications, and successes |
|
| 789 | + * 'script'=>a pretty name of the script currently running |
|
| 790 | + */ |
|
| 791 | + public function response_to_migration_ajax_request() |
|
| 792 | + { |
|
| 793 | + ob_start(); |
|
| 794 | + try { |
|
| 795 | + $response = $this->migration_step(); |
|
| 796 | + } catch (Exception $e) { |
|
| 797 | + $response = array( |
|
| 798 | + 'records_to_migrate' => 0, |
|
| 799 | + 'records_migrated' => 0, |
|
| 800 | + 'status' => EE_Data_Migration_Manager::status_fatal_error, |
|
| 801 | + 'message' => sprintf( |
|
| 802 | + __("Unknown fatal error occurred: %s", "event_espresso"), |
|
| 803 | + $e->getMessage() |
|
| 804 | + ), |
|
| 805 | + 'script' => 'Unknown', |
|
| 806 | + ); |
|
| 807 | + $this->add_error_to_migrations_ran($e->getMessage() . "; Stack trace:" . $e->getTraceAsString()); |
|
| 808 | + } |
|
| 809 | + $warnings_etc = @ob_get_contents(); |
|
| 810 | + ob_end_clean(); |
|
| 811 | + $response['message'] .= $warnings_etc; |
|
| 812 | + return $response; |
|
| 813 | + } |
|
| 814 | + |
|
| 815 | + /** |
|
| 816 | + * Updates the wordpress option that keeps track of which which EE version the database |
|
| 817 | + * is at (ie, the code may be at 4.1.0, but the database is still at 3.1.35) |
|
| 818 | + * |
|
| 819 | + * @param array $slug_and_version { |
|
| 820 | + * @type string $slug like 'Core' or 'Calendar', |
|
| 821 | + * @type string $version like '4.1.0' |
|
| 822 | + * } |
|
| 823 | + * @return void |
|
| 824 | + */ |
|
| 825 | + public function update_current_database_state_to($slug_and_version = null) |
|
| 826 | + { |
|
| 827 | + if (! $slug_and_version) { |
|
| 828 | + // no version was provided, assume it should be at the current code version |
|
| 829 | + $slug_and_version = array('slug' => 'Core', 'version' => espresso_version()); |
|
| 830 | + } |
|
| 831 | + $current_database_state = get_option(self::current_database_state); |
|
| 832 | + $current_database_state[ $slug_and_version['slug'] ] = $slug_and_version['version']; |
|
| 833 | + update_option(self::current_database_state, $current_database_state); |
|
| 834 | + } |
|
| 835 | + |
|
| 836 | + /** |
|
| 837 | + * Determines if the database is currently at a state matching what's indicated in $slug and $version. |
|
| 838 | + * |
|
| 839 | + * @param array $slug_and_version { |
|
| 840 | + * @type string $slug like 'Core' or 'Calendar', |
|
| 841 | + * @type string $version like '4.1.0' |
|
| 842 | + * } |
|
| 843 | + * @return boolean |
|
| 844 | + */ |
|
| 845 | + public function database_needs_updating_to($slug_and_version) |
|
| 846 | + { |
|
| 847 | + |
|
| 848 | + $slug = $slug_and_version['slug']; |
|
| 849 | + $version = $slug_and_version['version']; |
|
| 850 | + $current_database_state = get_option(self::current_database_state); |
|
| 851 | + if (! isset($current_database_state[ $slug ])) { |
|
| 852 | + return true; |
|
| 853 | + } else { |
|
| 854 | + // just compare the first 3 parts of version string, eg "4.7.1", not "4.7.1.dev.032" because DBs shouldn't change on nano version changes |
|
| 855 | + $version_parts_current_db_state = array_slice(explode('.', $current_database_state[ $slug ]), 0, 3); |
|
| 856 | + $version_parts_of_provided_db_state = array_slice(explode('.', $version), 0, 3); |
|
| 857 | + $needs_updating = false; |
|
| 858 | + foreach ($version_parts_current_db_state as $offset => $version_part_in_current_db_state) { |
|
| 859 | + if ($version_part_in_current_db_state < $version_parts_of_provided_db_state[ $offset ]) { |
|
| 860 | + $needs_updating = true; |
|
| 861 | + break; |
|
| 862 | + } |
|
| 863 | + } |
|
| 864 | + return $needs_updating; |
|
| 865 | + } |
|
| 866 | + } |
|
| 867 | + |
|
| 868 | + |
|
| 869 | + /** |
|
| 870 | + * Gets all the data migration scripts available in the core folder and folders |
|
| 871 | + * in addons. Has the side effect of adding them for autoloading |
|
| 872 | + * |
|
| 873 | + * @return array keys are expected classnames, values are their filepaths |
|
| 874 | + * @throws InvalidInterfaceException |
|
| 875 | + * @throws InvalidDataTypeException |
|
| 876 | + * @throws EE_Error |
|
| 877 | + * @throws InvalidArgumentException |
|
| 878 | + */ |
|
| 879 | + public function get_all_data_migration_scripts_available() |
|
| 880 | + { |
|
| 881 | + if (! $this->_data_migration_class_to_filepath_map) { |
|
| 882 | + $this->_data_migration_class_to_filepath_map = array(); |
|
| 883 | + foreach ($this->get_data_migration_script_folders() as $eeAddonClass => $folder_path) { |
|
| 884 | + // strip any placeholders added to classname to make it a unique array key |
|
| 885 | + $eeAddonClass = trim($eeAddonClass, '*'); |
|
| 886 | + $eeAddonClass = $eeAddonClass === 'Core' || class_exists($eeAddonClass) |
|
| 887 | + ? $eeAddonClass |
|
| 888 | + : ''; |
|
| 889 | + $folder_path = EEH_File::end_with_directory_separator($folder_path); |
|
| 890 | + $files = glob($folder_path . '*.dms.php'); |
|
| 891 | + if (empty($files)) { |
|
| 892 | + continue; |
|
| 893 | + } |
|
| 894 | + foreach ($files as $file) { |
|
| 895 | + $pos_of_last_slash = strrpos($file, '/'); |
|
| 896 | + $classname = str_replace('.dms.php', '', substr($file, $pos_of_last_slash + 1)); |
|
| 897 | + $migrates_to = $this->script_migrates_to_version($classname, $eeAddonClass); |
|
| 898 | + $slug = $migrates_to['slug']; |
|
| 899 | + // check that the slug as contained in the DMS is associated with |
|
| 900 | + // the slug of an addon or core |
|
| 901 | + if ($slug !== 'Core' && EE_Registry::instance()->get_addon_by_name($slug) === null) { |
|
| 902 | + EE_Error::doing_it_wrong( |
|
| 903 | + __FUNCTION__, |
|
| 904 | + sprintf( |
|
| 905 | + esc_html__( |
|
| 906 | + 'The data migration script "%s" migrates the "%s" data, but there is no EE addon with that name. There is only: %s. ', |
|
| 907 | + 'event_espresso' |
|
| 908 | + ), |
|
| 909 | + $classname, |
|
| 910 | + $slug, |
|
| 911 | + implode(', ', array_keys(EE_Registry::instance()->get_addons_by_name())) |
|
| 912 | + ), |
|
| 913 | + '4.3.0.alpha.019' |
|
| 914 | + ); |
|
| 915 | + } |
|
| 916 | + $this->_data_migration_class_to_filepath_map[ $classname ] = $file; |
|
| 917 | + } |
|
| 918 | + } |
|
| 919 | + EEH_Autoloader::register_autoloader($this->_data_migration_class_to_filepath_map); |
|
| 920 | + } |
|
| 921 | + return $this->_data_migration_class_to_filepath_map; |
|
| 922 | + } |
|
| 923 | + |
|
| 924 | + |
|
| 925 | + /** |
|
| 926 | + * Once we have an addon that works with EE4.1, we will actually want to fetch the PUE slugs |
|
| 927 | + * from each addon, and check if they need updating, |
|
| 928 | + * |
|
| 929 | + * @return boolean |
|
| 930 | + */ |
|
| 931 | + public function addons_need_updating() |
|
| 932 | + { |
|
| 933 | + return false; |
|
| 934 | + } |
|
| 935 | + |
|
| 936 | + |
|
| 937 | + /** |
|
| 938 | + * Adds this error string to the data_migrations_ran array, but we dont necessarily know |
|
| 939 | + * where to put it, so we just throw it in there... better than nothing... |
|
| 940 | + * |
|
| 941 | + * @param string $error_message |
|
| 942 | + */ |
|
| 943 | + public function add_error_to_migrations_ran($error_message) |
|
| 944 | + { |
|
| 945 | + // get last-ran migration script |
|
| 946 | + global $wpdb; |
|
| 947 | + $last_migration_script_option = $wpdb->get_row( |
|
| 948 | + "SELECT * FROM $wpdb->options WHERE option_name like '" . EE_Data_Migration_Manager::data_migration_script_option_prefix . "%' ORDER BY option_id DESC LIMIT 1", |
|
| 949 | + ARRAY_A |
|
| 950 | + ); |
|
| 951 | + |
|
| 952 | + $last_ran_migration_script_properties = isset($last_migration_script_option['option_value']) |
|
| 953 | + ? maybe_unserialize($last_migration_script_option['option_value']) : null; |
|
| 954 | + // now, tread lightly because we're here because a FATAL non-catchable error |
|
| 955 | + // was thrown last time when we were trying to run a data migration script |
|
| 956 | + // so the fatal error could have happened while getting the migration script |
|
| 957 | + // or doing running it... |
|
| 958 | + $versions_migrated_to = isset($last_migration_script_option['option_name']) ? str_replace( |
|
| 959 | + EE_Data_Migration_Manager::data_migration_script_option_prefix, |
|
| 960 | + "", |
|
| 961 | + $last_migration_script_option['option_name'] |
|
| 962 | + ) : null; |
|
| 963 | + |
|
| 964 | + // check if it THINKS its a data migration script and especially if it's one that HASN'T finished yet |
|
| 965 | + // because if it has finished, then it obviously couldn't be the cause of this error, right? (because its all done) |
|
| 966 | + if (isset($last_ran_migration_script_properties['class']) && isset($last_ran_migration_script_properties['_status']) && $last_ran_migration_script_properties['_status'] != self::status_completed) { |
|
| 967 | + // ok then just add this error to its list of errors |
|
| 968 | + $last_ran_migration_script_properties['_errors'][] = $error_message; |
|
| 969 | + $last_ran_migration_script_properties['_status'] = self::status_fatal_error; |
|
| 970 | + } else { |
|
| 971 | + // so we don't even know which script was last running |
|
| 972 | + // use the data migration error stub, which is designed specifically for this type of thing |
|
| 973 | + $general_migration_error = new EE_DMS_Unknown_1_0_0(); |
|
| 974 | + $general_migration_error->add_error($error_message); |
|
| 975 | + $general_migration_error->set_broken(); |
|
| 976 | + $last_ran_migration_script_properties = $general_migration_error->properties_as_array(); |
|
| 977 | + $versions_migrated_to = 'Unknown.1.0.0'; |
|
| 978 | + // now just to make sure appears as last (in case the were previously a fatal error like this) |
|
| 979 | + // delete the old one |
|
| 980 | + delete_option(self::data_migration_script_option_prefix . $versions_migrated_to); |
|
| 981 | + } |
|
| 982 | + update_option( |
|
| 983 | + self::data_migration_script_option_prefix . $versions_migrated_to, |
|
| 984 | + $last_ran_migration_script_properties |
|
| 985 | + ); |
|
| 986 | + } |
|
| 987 | + |
|
| 988 | + |
|
| 989 | + /** |
|
| 990 | + * saves what data migrations have ran to the database |
|
| 991 | + * |
|
| 992 | + * @return mixed TRUE if successfully saved migrations ran, string if an error occurred |
|
| 993 | + * @throws EE_Error |
|
| 994 | + * @throws EE_Error |
|
| 995 | + */ |
|
| 996 | + protected function _save_migrations_ran() |
|
| 997 | + { |
|
| 998 | + if ($this->_data_migrations_ran == null) { |
|
| 999 | + $this->get_data_migrations_ran(); |
|
| 1000 | + } |
|
| 1001 | + // now, we don't want to save actual classes to the DB because that's messy |
|
| 1002 | + $successful_updates = true; |
|
| 1003 | + foreach ($this->_data_migrations_ran as $plugin_slug => $migrations_ran_for_plugin) { |
|
| 1004 | + foreach ($migrations_ran_for_plugin as $version_string => $array_or_migration_obj) { |
|
| 1005 | + $plugin_slug_for_use_in_option_name = $plugin_slug . "."; |
|
| 1006 | + $option_name = self::data_migration_script_option_prefix . $plugin_slug_for_use_in_option_name . $version_string; |
|
| 1007 | + $old_option_value = get_option($option_name); |
|
| 1008 | + if ($array_or_migration_obj instanceof EE_Data_Migration_Script_Base) { |
|
| 1009 | + $script_array_for_saving = $array_or_migration_obj->properties_as_array(); |
|
| 1010 | + if ($old_option_value != $script_array_for_saving) { |
|
| 1011 | + $successful_updates = update_option($option_name, $script_array_for_saving); |
|
| 1012 | + } |
|
| 1013 | + } else {// we don't know what this array-thing is. So just save it as-is |
|
| 1014 | + if ($old_option_value != $array_or_migration_obj) { |
|
| 1015 | + $successful_updates = update_option($option_name, $array_or_migration_obj); |
|
| 1016 | + } |
|
| 1017 | + } |
|
| 1018 | + if (! $successful_updates) { |
|
| 1019 | + global $wpdb; |
|
| 1020 | + return $wpdb->last_error; |
|
| 1021 | + } |
|
| 1022 | + } |
|
| 1023 | + } |
|
| 1024 | + return true; |
|
| 1025 | + // $updated = update_option(self::data_migrations_option_name, $array_of_migrations); |
|
| 1026 | + // if ($updated !== true) { |
|
| 1027 | + // global $wpdb; |
|
| 1028 | + // return $wpdb->last_error; |
|
| 1029 | + // } else { |
|
| 1030 | + // return true; |
|
| 1031 | + // } |
|
| 1032 | + // wp_mail( |
|
| 1033 | + // "[email protected]", |
|
| 1034 | + // time() . " price debug info", |
|
| 1035 | + // "updated: $updated, last error: $last_error, byte length of option: " . strlen( |
|
| 1036 | + // serialize($array_of_migrations) |
|
| 1037 | + // ) |
|
| 1038 | + // ); |
|
| 1039 | + } |
|
| 1040 | + |
|
| 1041 | + /** |
|
| 1042 | + * Takes an array of data migration script properties and re-creates the class from |
|
| 1043 | + * them. The argument $properties_array is assumed to have been made by |
|
| 1044 | + * EE_Data_Migration_Script_Base::properties_as_array() |
|
| 1045 | + * |
|
| 1046 | + * @param array $properties_array |
|
| 1047 | + * @return EE_Data_Migration_Script_Base |
|
| 1048 | + * @throws EE_Error |
|
| 1049 | + */ |
|
| 1050 | + public function _instantiate_script_from_properties_array($properties_array) |
|
| 1051 | + { |
|
| 1052 | + if (! isset($properties_array['class'])) { |
|
| 1053 | + throw new EE_Error( |
|
| 1054 | + sprintf( |
|
| 1055 | + __("Properties array has no 'class' properties. Here's what it has: %s", "event_espresso"), |
|
| 1056 | + implode(",", $properties_array) |
|
| 1057 | + ) |
|
| 1058 | + ); |
|
| 1059 | + } |
|
| 1060 | + $class_name = $properties_array['class']; |
|
| 1061 | + if (! class_exists($class_name)) { |
|
| 1062 | + throw new EE_Error(sprintf(__("There is no migration script named %s", "event_espresso"), $class_name)); |
|
| 1063 | + } |
|
| 1064 | + $class = new $class_name(); |
|
| 1065 | + if (! $class instanceof EE_Data_Migration_Script_Base) { |
|
| 1066 | + throw new EE_Error( |
|
| 1067 | + sprintf( |
|
| 1068 | + __("Class '%s' is supposed to be a migration script. Its not, its a '%s'", "event_espresso"), |
|
| 1069 | + $class_name, |
|
| 1070 | + get_class($class) |
|
| 1071 | + ) |
|
| 1072 | + ); |
|
| 1073 | + } |
|
| 1074 | + $class->instantiate_from_array_of_properties($properties_array); |
|
| 1075 | + return $class; |
|
| 1076 | + } |
|
| 1077 | + |
|
| 1078 | + |
|
| 1079 | + /** |
|
| 1080 | + * Gets the classname for the most up-to-date DMS (ie, the one that will finally |
|
| 1081 | + * leave the DB in a state usable by the current plugin code). |
|
| 1082 | + * |
|
| 1083 | + * @param string $plugin_slug the slug for the ee plugin we are searching for. Default is 'Core' |
|
| 1084 | + * @return string |
|
| 1085 | + * @throws EE_Error |
|
| 1086 | + */ |
|
| 1087 | + public function get_most_up_to_date_dms($plugin_slug = 'Core') |
|
| 1088 | + { |
|
| 1089 | + $class_to_filepath_map = $this->get_all_data_migration_scripts_available(); |
|
| 1090 | + $most_up_to_date_dms_classname = null; |
|
| 1091 | + foreach ($class_to_filepath_map as $classname => $filepath) { |
|
| 1092 | + if ($most_up_to_date_dms_classname === null) { |
|
| 1093 | + $migrates_to = $this->script_migrates_to_version($classname); |
|
| 1094 | + $this_plugin_slug = $migrates_to['slug']; |
|
| 1095 | + if ($this_plugin_slug == $plugin_slug) { |
|
| 1096 | + // if it's for core, it wins |
|
| 1097 | + $most_up_to_date_dms_classname = $classname; |
|
| 1098 | + } |
|
| 1099 | + // if it wasn't for core, we must keep searching for one that is! |
|
| 1100 | + continue; |
|
| 1101 | + } else { |
|
| 1102 | + $champion_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms_classname); |
|
| 1103 | + $contender_migrates_to = $this->script_migrates_to_version($classname); |
|
| 1104 | + if ( |
|
| 1105 | + $contender_migrates_to['slug'] == $plugin_slug |
|
| 1106 | + && version_compare( |
|
| 1107 | + $champion_migrates_to['version'], |
|
| 1108 | + $contender_migrates_to['version'], |
|
| 1109 | + '<' |
|
| 1110 | + ) |
|
| 1111 | + ) { |
|
| 1112 | + // so the contenders version is higher and its for Core |
|
| 1113 | + $most_up_to_date_dms_classname = $classname; |
|
| 1114 | + } |
|
| 1115 | + } |
|
| 1116 | + } |
|
| 1117 | + return $most_up_to_date_dms_classname; |
|
| 1118 | + } |
|
| 1119 | + |
|
| 1120 | + |
|
| 1121 | + /** |
|
| 1122 | + * Gets the migration script specified but ONLY if it has already ran. |
|
| 1123 | + * |
|
| 1124 | + * Eg, if you wanted to see if 'EE_DMS_Core_4_1_0' has ran, you would run the following code: |
|
| 1125 | + * <code> $core_4_1_0_dms_ran = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.1.0', 'Core' ) !== |
|
| 1126 | + * NULL;</code> This is especially useful in addons' data migration scripts, this way they can tell if a core (or |
|
| 1127 | + * other addon) DMS has ran, in case the current DMS depends on it. |
|
| 1128 | + * |
|
| 1129 | + * @param string $version the version the DMS searched for migrates to. Usually just the content before the 3rd |
|
| 1130 | + * period. Eg '4.1.0' |
|
| 1131 | + * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc |
|
| 1132 | + * @return EE_Data_Migration_Script_Base |
|
| 1133 | + * @throws EE_Error |
|
| 1134 | + * @throws EE_Error |
|
| 1135 | + */ |
|
| 1136 | + public function get_migration_ran($version, $plugin_slug = 'Core') |
|
| 1137 | + { |
|
| 1138 | + $migrations_ran = $this->get_data_migrations_ran(); |
|
| 1139 | + if (isset($migrations_ran[ $plugin_slug ]) && isset($migrations_ran[ $plugin_slug ][ $version ])) { |
|
| 1140 | + return $migrations_ran[ $plugin_slug ][ $version ]; |
|
| 1141 | + } else { |
|
| 1142 | + return null; |
|
| 1143 | + } |
|
| 1144 | + } |
|
| 1145 | + |
|
| 1146 | + /** |
|
| 1147 | + * Resets the borked data migration scripts so they're no longer borked |
|
| 1148 | + * so we can again attempt to migrate |
|
| 1149 | + * |
|
| 1150 | + * @return bool |
|
| 1151 | + * @throws EE_Error |
|
| 1152 | + */ |
|
| 1153 | + public function reattempt() |
|
| 1154 | + { |
|
| 1155 | + // find if the last-ran script was borked |
|
| 1156 | + // set it as being non-borked (we shouldn't ever get DMSs that we don't recognize) |
|
| 1157 | + // add an 'error' saying that we attempted to reset |
|
| 1158 | + // does it have a stage that was borked too? if so make it no longer borked |
|
| 1159 | + // add an 'error' saying we attempted to reset |
|
| 1160 | + $last_ran_script = $this->get_last_ran_script(); |
|
| 1161 | + if ($last_ran_script instanceof EE_DMS_Unknown_1_0_0) { |
|
| 1162 | + // if it was an error DMS, just mark it as complete (if another error occurs it will overwrite it) |
|
| 1163 | + $last_ran_script->set_completed(); |
|
| 1164 | + } elseif ($last_ran_script instanceof EE_Data_Migration_Script_Base) { |
|
| 1165 | + $last_ran_script->reattempt(); |
|
| 1166 | + } else { |
|
| 1167 | + throw new EE_Error( |
|
| 1168 | + sprintf( |
|
| 1169 | + __( |
|
| 1170 | + 'Unable to reattempt the last ran migration script because it was not a valid migration script. || It was %s', |
|
| 1171 | + 'event_espresso' |
|
| 1172 | + ), |
|
| 1173 | + print_r($last_ran_script, true) |
|
| 1174 | + ) |
|
| 1175 | + ); |
|
| 1176 | + } |
|
| 1177 | + return $this->_save_migrations_ran(); |
|
| 1178 | + } |
|
| 1179 | + |
|
| 1180 | + |
|
| 1181 | + /** |
|
| 1182 | + * Gets whether or not this particular migration has run or not |
|
| 1183 | + * |
|
| 1184 | + * @param string $version the version the DMS searched for migrates to. Usually just the content before the 3rd |
|
| 1185 | + * period. Eg '4.1.0' |
|
| 1186 | + * @param string $plugin_slug like 'Core', 'Mailchimp', 'Calendar', etc |
|
| 1187 | + * @return boolean |
|
| 1188 | + * @throws EE_Error |
|
| 1189 | + */ |
|
| 1190 | + public function migration_has_ran($version, $plugin_slug = 'Core') |
|
| 1191 | + { |
|
| 1192 | + return $this->get_migration_ran($version, $plugin_slug) !== null; |
|
| 1193 | + } |
|
| 1194 | + |
|
| 1195 | + /** |
|
| 1196 | + * Enqueues this ee plugin to have its data initialized |
|
| 1197 | + * |
|
| 1198 | + * @param string $plugin_slug either 'Core' or EE_Addon::name()'s return value |
|
| 1199 | + */ |
|
| 1200 | + public function enqueue_db_initialization_for($plugin_slug) |
|
| 1201 | + { |
|
| 1202 | + $queue = $this->get_db_initialization_queue(); |
|
| 1203 | + if (! in_array($plugin_slug, $queue)) { |
|
| 1204 | + $queue[] = $plugin_slug; |
|
| 1205 | + } |
|
| 1206 | + update_option(self::db_init_queue_option_name, $queue); |
|
| 1207 | + } |
|
| 1208 | + |
|
| 1209 | + |
|
| 1210 | + /** |
|
| 1211 | + * Calls EE_Addon::initialize_db_if_no_migrations_required() on each addon |
|
| 1212 | + * specified in EE_Data_Migration_Manager::get_db_init_queue(), and if 'Core' is |
|
| 1213 | + * in the queue, calls EE_System::initialize_db_if_no_migrations_required(). |
|
| 1214 | + * |
|
| 1215 | + * @throws EE_Error |
|
| 1216 | + */ |
|
| 1217 | + public function initialize_db_for_enqueued_ee_plugins() |
|
| 1218 | + { |
|
| 1219 | + $queue = $this->get_db_initialization_queue(); |
|
| 1220 | + foreach ($queue as $plugin_slug) { |
|
| 1221 | + $most_up_to_date_dms = $this->get_most_up_to_date_dms($plugin_slug); |
|
| 1222 | + if (! $most_up_to_date_dms) { |
|
| 1223 | + // if there is NO DMS for this plugin, obviously there's no schema to verify anyways |
|
| 1224 | + $verify_db = false; |
|
| 1225 | + } else { |
|
| 1226 | + $most_up_to_date_dms_migrates_to = $this->script_migrates_to_version($most_up_to_date_dms); |
|
| 1227 | + $verify_db = $this->database_needs_updating_to($most_up_to_date_dms_migrates_to); |
|
| 1228 | + } |
|
| 1229 | + if ($plugin_slug == 'Core') { |
|
| 1230 | + EE_System::instance()->initialize_db_if_no_migrations_required( |
|
| 1231 | + false, |
|
| 1232 | + $verify_db |
|
| 1233 | + ); |
|
| 1234 | + } else { |
|
| 1235 | + // just loop through the addons to make sure their database is setup |
|
| 1236 | + foreach (EE_Registry::instance()->addons as $addon) { |
|
| 1237 | + if ($addon->name() == $plugin_slug) { |
|
| 1238 | + $addon->initialize_db_if_no_migrations_required($verify_db); |
|
| 1239 | + break; |
|
| 1240 | + } |
|
| 1241 | + } |
|
| 1242 | + } |
|
| 1243 | + } |
|
| 1244 | + // because we just initialized the DBs for the enqueued ee plugins |
|
| 1245 | + // we don't need to keep remembering which ones needed to be initialized |
|
| 1246 | + delete_option(self::db_init_queue_option_name); |
|
| 1247 | + } |
|
| 1248 | + |
|
| 1249 | + /** |
|
| 1250 | + * Gets a numerically-indexed array of plugin slugs that need to have their databases |
|
| 1251 | + * (re-)initialized after migrations are complete. ie, each element should be either |
|
| 1252 | + * 'Core', or the return value of EE_Addon::name() for an addon |
|
| 1253 | + * |
|
| 1254 | + * @return array |
|
| 1255 | + */ |
|
| 1256 | + public function get_db_initialization_queue() |
|
| 1257 | + { |
|
| 1258 | + return get_option(self::db_init_queue_option_name, array()); |
|
| 1259 | + } |
|
| 1260 | + |
|
| 1261 | + /** |
|
| 1262 | + * Gets the injected table analyzer, or throws an exception |
|
| 1263 | + * |
|
| 1264 | + * @return TableAnalysis |
|
| 1265 | + * @throws EE_Error |
|
| 1266 | + */ |
|
| 1267 | + protected function _get_table_analysis() |
|
| 1268 | + { |
|
| 1269 | + if ($this->_table_analysis instanceof TableAnalysis) { |
|
| 1270 | + return $this->_table_analysis; |
|
| 1271 | + } else { |
|
| 1272 | + throw new EE_Error( |
|
| 1273 | + sprintf( |
|
| 1274 | + __('Table analysis class on class %1$s is not set properly.', 'event_espresso'), |
|
| 1275 | + get_class($this) |
|
| 1276 | + ) |
|
| 1277 | + ); |
|
| 1278 | + } |
|
| 1279 | + } |
|
| 1280 | + |
|
| 1281 | + /** |
|
| 1282 | + * Gets the injected table manager, or throws an exception |
|
| 1283 | + * |
|
| 1284 | + * @return TableManager |
|
| 1285 | + * @throws EE_Error |
|
| 1286 | + */ |
|
| 1287 | + protected function _get_table_manager() |
|
| 1288 | + { |
|
| 1289 | + if ($this->_table_manager instanceof TableManager) { |
|
| 1290 | + return $this->_table_manager; |
|
| 1291 | + } else { |
|
| 1292 | + throw new EE_Error( |
|
| 1293 | + sprintf( |
|
| 1294 | + __('Table manager class on class %1$s is not set properly.', 'event_espresso'), |
|
| 1295 | + get_class($this) |
|
| 1296 | + ) |
|
| 1297 | + ); |
|
| 1298 | + } |
|
| 1299 | + } |
|
| 1300 | 1300 | } |
@@ -15,175 +15,175 @@ |
||
| 15 | 15 | { |
| 16 | 16 | |
| 17 | 17 | |
| 18 | - /** |
|
| 19 | - * @type EE_Message_Factory $_instance |
|
| 20 | - */ |
|
| 21 | - protected static $_instance; |
|
| 22 | - |
|
| 23 | - |
|
| 24 | - /** |
|
| 25 | - * @type EE_Message_Resource_Manager $_message_resource_manager |
|
| 26 | - */ |
|
| 27 | - protected $_message_resource_manager; |
|
| 28 | - |
|
| 29 | - |
|
| 30 | - |
|
| 31 | - /** |
|
| 32 | - * EE_Message_Factory constructor. |
|
| 33 | - * |
|
| 34 | - * @access protected |
|
| 35 | - * @param \EE_Message_Resource_Manager $Message_Resource_Manager |
|
| 36 | - */ |
|
| 37 | - protected function __construct( |
|
| 38 | - EE_Message_Resource_Manager $Message_Resource_Manager |
|
| 39 | - ) { |
|
| 40 | - $this->_message_resource_manager = $Message_Resource_Manager; |
|
| 41 | - } |
|
| 42 | - |
|
| 43 | - |
|
| 44 | - |
|
| 45 | - /** |
|
| 46 | - * @singleton method used to instantiate class object |
|
| 47 | - * @access public |
|
| 48 | - * @param \EE_Message_Resource_Manager $Message_Resource_Manager |
|
| 49 | - * @return \EE_Message_Factory instance |
|
| 50 | - */ |
|
| 51 | - public static function instance(EE_Message_Resource_Manager $Message_Resource_Manager) |
|
| 52 | - { |
|
| 53 | - // check if class object is instantiated, and instantiated properly |
|
| 54 | - if (! self::$_instance instanceof EE_Message_Factory) { |
|
| 55 | - self::$_instance = new EE_Message_Factory($Message_Resource_Manager); |
|
| 56 | - } |
|
| 57 | - return self::$_instance; |
|
| 58 | - } |
|
| 59 | - |
|
| 60 | - |
|
| 61 | - |
|
| 62 | - /** |
|
| 63 | - * @access public |
|
| 64 | - * @param array $props_n_values |
|
| 65 | - * @return EE_Message |
|
| 66 | - */ |
|
| 67 | - public static function create($props_n_values = array()) |
|
| 68 | - { |
|
| 69 | - /** @type EE_Message_Factory $Message_Factory */ |
|
| 70 | - $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 71 | - return $Message_Factory->_create($props_n_values); |
|
| 72 | - } |
|
| 73 | - |
|
| 74 | - |
|
| 75 | - |
|
| 76 | - /** |
|
| 77 | - * @access public |
|
| 78 | - * @param \EE_Message $message |
|
| 79 | - * @return \EE_Message |
|
| 80 | - * @throws \EE_Error |
|
| 81 | - */ |
|
| 82 | - public static function set_messenger_and_message_type(EE_Message $message) |
|
| 83 | - { |
|
| 84 | - /** @type EE_Message_Factory $Message_Factory */ |
|
| 85 | - $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 86 | - return $Message_Factory->_set_messenger_and_message_type($message); |
|
| 87 | - } |
|
| 88 | - |
|
| 89 | - |
|
| 90 | - |
|
| 91 | - /** |
|
| 92 | - * @access public |
|
| 93 | - * @param \EE_Message $message |
|
| 94 | - * @return \EE_Message |
|
| 95 | - * @throws \EE_Error |
|
| 96 | - */ |
|
| 97 | - public static function set_messenger(EE_Message $message) |
|
| 98 | - { |
|
| 99 | - /** @type EE_Message_Factory $Message_Factory */ |
|
| 100 | - $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 101 | - return $Message_Factory->_set_messenger($message); |
|
| 102 | - } |
|
| 103 | - |
|
| 104 | - |
|
| 105 | - |
|
| 106 | - /** |
|
| 107 | - * @access public |
|
| 108 | - * @param \EE_Message $message |
|
| 109 | - * @return \EE_Message |
|
| 110 | - * @throws \EE_Error |
|
| 111 | - */ |
|
| 112 | - public static function set_message_type(EE_Message $message) |
|
| 113 | - { |
|
| 114 | - /** @type EE_Message_Factory $Message_Factory */ |
|
| 115 | - $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 116 | - return $Message_Factory->_set_message_type($message); |
|
| 117 | - } |
|
| 118 | - |
|
| 119 | - |
|
| 120 | - |
|
| 121 | - /** |
|
| 122 | - * @access protected |
|
| 123 | - * @param array $props_n_values |
|
| 124 | - * @return \EE_Message |
|
| 125 | - * @throws \EE_Error |
|
| 126 | - */ |
|
| 127 | - protected function _create($props_n_values = array()) |
|
| 128 | - { |
|
| 129 | - $new_instance = false; |
|
| 130 | - if (! empty($props_n_values['MSG_ID'])) { |
|
| 131 | - $message = EE_Message::new_instance_from_db($props_n_values); |
|
| 132 | - } else { |
|
| 133 | - $message = EE_Message::new_instance($props_n_values); |
|
| 134 | - $new_instance = true; |
|
| 135 | - } |
|
| 136 | - return $this->_set_messenger_and_message_type($message, $new_instance); |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - |
|
| 140 | - |
|
| 141 | - /** |
|
| 142 | - * @access public |
|
| 143 | - * @param \EE_Message $message |
|
| 144 | - * @param bool $new_instance Whether the message type was setup from the database (false) or not (true) |
|
| 145 | - * @return \EE_Message |
|
| 146 | - * @throws \EE_Error |
|
| 147 | - */ |
|
| 148 | - protected function _set_messenger_and_message_type(EE_Message $message, $new_instance = false) |
|
| 149 | - { |
|
| 150 | - $message = $this->_set_messenger($message); |
|
| 151 | - $message = $this->_set_message_type($message, $new_instance); |
|
| 152 | - return $message; |
|
| 153 | - } |
|
| 154 | - |
|
| 155 | - |
|
| 156 | - |
|
| 157 | - /** |
|
| 158 | - * @access protected |
|
| 159 | - * @param \EE_Message $message |
|
| 160 | - * @return \EE_Message |
|
| 161 | - * @throws \EE_Error |
|
| 162 | - */ |
|
| 163 | - protected function _set_messenger(EE_Message $message) |
|
| 164 | - { |
|
| 165 | - $messenger = $this->_message_resource_manager->get_messenger($message->messenger()); |
|
| 166 | - if ($messenger instanceof EE_messenger) { |
|
| 167 | - $message->set_messenger_object($messenger); |
|
| 168 | - } |
|
| 169 | - return $message; |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - |
|
| 173 | - |
|
| 174 | - /** |
|
| 175 | - * @access protected |
|
| 176 | - * @param \EE_Message $message |
|
| 177 | - * @param bool $new_instance Whether the message type was setup from the database (false) or not (true) |
|
| 178 | - * @return \EE_Message |
|
| 179 | - * @throws \EE_Error |
|
| 180 | - */ |
|
| 181 | - protected function _set_message_type(EE_Message $message, $new_instance = false) |
|
| 182 | - { |
|
| 183 | - $message_type = $this->_message_resource_manager->get_message_type($message->message_type()); |
|
| 184 | - if ($message_type instanceof EE_message_type) { |
|
| 185 | - $message->set_message_type_object($message_type, $new_instance); |
|
| 186 | - } |
|
| 187 | - return $message; |
|
| 188 | - } |
|
| 18 | + /** |
|
| 19 | + * @type EE_Message_Factory $_instance |
|
| 20 | + */ |
|
| 21 | + protected static $_instance; |
|
| 22 | + |
|
| 23 | + |
|
| 24 | + /** |
|
| 25 | + * @type EE_Message_Resource_Manager $_message_resource_manager |
|
| 26 | + */ |
|
| 27 | + protected $_message_resource_manager; |
|
| 28 | + |
|
| 29 | + |
|
| 30 | + |
|
| 31 | + /** |
|
| 32 | + * EE_Message_Factory constructor. |
|
| 33 | + * |
|
| 34 | + * @access protected |
|
| 35 | + * @param \EE_Message_Resource_Manager $Message_Resource_Manager |
|
| 36 | + */ |
|
| 37 | + protected function __construct( |
|
| 38 | + EE_Message_Resource_Manager $Message_Resource_Manager |
|
| 39 | + ) { |
|
| 40 | + $this->_message_resource_manager = $Message_Resource_Manager; |
|
| 41 | + } |
|
| 42 | + |
|
| 43 | + |
|
| 44 | + |
|
| 45 | + /** |
|
| 46 | + * @singleton method used to instantiate class object |
|
| 47 | + * @access public |
|
| 48 | + * @param \EE_Message_Resource_Manager $Message_Resource_Manager |
|
| 49 | + * @return \EE_Message_Factory instance |
|
| 50 | + */ |
|
| 51 | + public static function instance(EE_Message_Resource_Manager $Message_Resource_Manager) |
|
| 52 | + { |
|
| 53 | + // check if class object is instantiated, and instantiated properly |
|
| 54 | + if (! self::$_instance instanceof EE_Message_Factory) { |
|
| 55 | + self::$_instance = new EE_Message_Factory($Message_Resource_Manager); |
|
| 56 | + } |
|
| 57 | + return self::$_instance; |
|
| 58 | + } |
|
| 59 | + |
|
| 60 | + |
|
| 61 | + |
|
| 62 | + /** |
|
| 63 | + * @access public |
|
| 64 | + * @param array $props_n_values |
|
| 65 | + * @return EE_Message |
|
| 66 | + */ |
|
| 67 | + public static function create($props_n_values = array()) |
|
| 68 | + { |
|
| 69 | + /** @type EE_Message_Factory $Message_Factory */ |
|
| 70 | + $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 71 | + return $Message_Factory->_create($props_n_values); |
|
| 72 | + } |
|
| 73 | + |
|
| 74 | + |
|
| 75 | + |
|
| 76 | + /** |
|
| 77 | + * @access public |
|
| 78 | + * @param \EE_Message $message |
|
| 79 | + * @return \EE_Message |
|
| 80 | + * @throws \EE_Error |
|
| 81 | + */ |
|
| 82 | + public static function set_messenger_and_message_type(EE_Message $message) |
|
| 83 | + { |
|
| 84 | + /** @type EE_Message_Factory $Message_Factory */ |
|
| 85 | + $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 86 | + return $Message_Factory->_set_messenger_and_message_type($message); |
|
| 87 | + } |
|
| 88 | + |
|
| 89 | + |
|
| 90 | + |
|
| 91 | + /** |
|
| 92 | + * @access public |
|
| 93 | + * @param \EE_Message $message |
|
| 94 | + * @return \EE_Message |
|
| 95 | + * @throws \EE_Error |
|
| 96 | + */ |
|
| 97 | + public static function set_messenger(EE_Message $message) |
|
| 98 | + { |
|
| 99 | + /** @type EE_Message_Factory $Message_Factory */ |
|
| 100 | + $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 101 | + return $Message_Factory->_set_messenger($message); |
|
| 102 | + } |
|
| 103 | + |
|
| 104 | + |
|
| 105 | + |
|
| 106 | + /** |
|
| 107 | + * @access public |
|
| 108 | + * @param \EE_Message $message |
|
| 109 | + * @return \EE_Message |
|
| 110 | + * @throws \EE_Error |
|
| 111 | + */ |
|
| 112 | + public static function set_message_type(EE_Message $message) |
|
| 113 | + { |
|
| 114 | + /** @type EE_Message_Factory $Message_Factory */ |
|
| 115 | + $Message_Factory = EE_Registry::instance()->load_lib('Message_Factory'); |
|
| 116 | + return $Message_Factory->_set_message_type($message); |
|
| 117 | + } |
|
| 118 | + |
|
| 119 | + |
|
| 120 | + |
|
| 121 | + /** |
|
| 122 | + * @access protected |
|
| 123 | + * @param array $props_n_values |
|
| 124 | + * @return \EE_Message |
|
| 125 | + * @throws \EE_Error |
|
| 126 | + */ |
|
| 127 | + protected function _create($props_n_values = array()) |
|
| 128 | + { |
|
| 129 | + $new_instance = false; |
|
| 130 | + if (! empty($props_n_values['MSG_ID'])) { |
|
| 131 | + $message = EE_Message::new_instance_from_db($props_n_values); |
|
| 132 | + } else { |
|
| 133 | + $message = EE_Message::new_instance($props_n_values); |
|
| 134 | + $new_instance = true; |
|
| 135 | + } |
|
| 136 | + return $this->_set_messenger_and_message_type($message, $new_instance); |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + |
|
| 140 | + |
|
| 141 | + /** |
|
| 142 | + * @access public |
|
| 143 | + * @param \EE_Message $message |
|
| 144 | + * @param bool $new_instance Whether the message type was setup from the database (false) or not (true) |
|
| 145 | + * @return \EE_Message |
|
| 146 | + * @throws \EE_Error |
|
| 147 | + */ |
|
| 148 | + protected function _set_messenger_and_message_type(EE_Message $message, $new_instance = false) |
|
| 149 | + { |
|
| 150 | + $message = $this->_set_messenger($message); |
|
| 151 | + $message = $this->_set_message_type($message, $new_instance); |
|
| 152 | + return $message; |
|
| 153 | + } |
|
| 154 | + |
|
| 155 | + |
|
| 156 | + |
|
| 157 | + /** |
|
| 158 | + * @access protected |
|
| 159 | + * @param \EE_Message $message |
|
| 160 | + * @return \EE_Message |
|
| 161 | + * @throws \EE_Error |
|
| 162 | + */ |
|
| 163 | + protected function _set_messenger(EE_Message $message) |
|
| 164 | + { |
|
| 165 | + $messenger = $this->_message_resource_manager->get_messenger($message->messenger()); |
|
| 166 | + if ($messenger instanceof EE_messenger) { |
|
| 167 | + $message->set_messenger_object($messenger); |
|
| 168 | + } |
|
| 169 | + return $message; |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + |
|
| 173 | + |
|
| 174 | + /** |
|
| 175 | + * @access protected |
|
| 176 | + * @param \EE_Message $message |
|
| 177 | + * @param bool $new_instance Whether the message type was setup from the database (false) or not (true) |
|
| 178 | + * @return \EE_Message |
|
| 179 | + * @throws \EE_Error |
|
| 180 | + */ |
|
| 181 | + protected function _set_message_type(EE_Message $message, $new_instance = false) |
|
| 182 | + { |
|
| 183 | + $message_type = $this->_message_resource_manager->get_message_type($message->message_type()); |
|
| 184 | + if ($message_type instanceof EE_message_type) { |
|
| 185 | + $message->set_message_type_object($message_type, $new_instance); |
|
| 186 | + } |
|
| 187 | + return $message; |
|
| 188 | + } |
|
| 189 | 189 | } |
@@ -10,203 +10,203 @@ |
||
| 10 | 10 | class EEM_Price_Type extends EEM_Soft_Delete_Base |
| 11 | 11 | { |
| 12 | 12 | |
| 13 | - /** |
|
| 14 | - * @var EEM_Price_Type |
|
| 15 | - */ |
|
| 16 | - protected static $_instance; |
|
| 17 | - |
|
| 18 | - // An array of the price type objects |
|
| 19 | - |
|
| 20 | - /** |
|
| 21 | - * @var string |
|
| 22 | - */ |
|
| 23 | - public $type; |
|
| 24 | - |
|
| 25 | - /** |
|
| 26 | - * Price Base types |
|
| 27 | - * Keys are INTs which are used in the database, |
|
| 28 | - * values are text-representations of the base type. |
|
| 29 | - * |
|
| 30 | - * @var string[] |
|
| 31 | - */ |
|
| 32 | - public $base_types; |
|
| 33 | - |
|
| 34 | - |
|
| 35 | - /** |
|
| 36 | - * return an array of Base types. |
|
| 37 | - * |
|
| 38 | - * @return string[] |
|
| 39 | - */ |
|
| 40 | - public function get_base_types(): array |
|
| 41 | - { |
|
| 42 | - return $this->base_types; |
|
| 43 | - } |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - /** |
|
| 47 | - * Gets the name of the base |
|
| 48 | - * |
|
| 49 | - * @param int $base_type_int |
|
| 50 | - * @return string |
|
| 51 | - */ |
|
| 52 | - public function get_base_type_name(int $base_type_int): string |
|
| 53 | - { |
|
| 54 | - return $this->base_types[ $base_type_int ]; |
|
| 55 | - } |
|
| 56 | - |
|
| 57 | - |
|
| 58 | - /** |
|
| 59 | - * constants for price base types. In the DB, we decided to store the price base type |
|
| 60 | - * as an integer. So, to avoid just having magic numbers everywhere (eg, querying for |
|
| 61 | - * all price types with PBT_ID = 2), we define these constants, to make code more understandable. |
|
| 62 | - * So, as an example, to query for all price types that are a tax, we'd do |
|
| 63 | - * EEM_PRice_Type::instance()->get_all(array(array('PBT_ID'=>EEM_Price_Type::base_type_tax))) |
|
| 64 | - * instead of |
|
| 65 | - * EEM_Price_Type::instance()->get_all(array(array('PBT_ID'=>2))) |
|
| 66 | - * Although the 2nd is shorter, it's much less obvious what it's doing. Also, should these magic IDs ever |
|
| 67 | - * change, we can continue to use the constant, by simply change its value. |
|
| 68 | - */ |
|
| 69 | - const base_type_base_price = 1; |
|
| 70 | - |
|
| 71 | - const base_type_discount = 2; |
|
| 72 | - |
|
| 73 | - const base_type_surcharge = 3; |
|
| 74 | - |
|
| 75 | - const base_type_tax = 4; |
|
| 76 | - |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * EEM_Price_Type constructor. |
|
| 80 | - * |
|
| 81 | - * @param string $timezone |
|
| 82 | - * @throws EE_Error |
|
| 83 | - */ |
|
| 84 | - protected function __construct(string $timezone = '') |
|
| 85 | - { |
|
| 86 | - $this->base_types = [ |
|
| 87 | - EEM_Price_Type::base_type_base_price => esc_html__('Price', 'event_espresso'), |
|
| 88 | - EEM_Price_Type::base_type_discount => esc_html__('Discount', 'event_espresso'), |
|
| 89 | - EEM_Price_Type::base_type_surcharge => esc_html__('Surcharge', 'event_espresso'), |
|
| 90 | - EEM_Price_Type::base_type_tax => esc_html__('Tax', 'event_espresso'), |
|
| 91 | - ]; |
|
| 92 | - $this->singular_item = esc_html__('Price Type', 'event_espresso'); |
|
| 93 | - $this->plural_item = esc_html__('Price Types', 'event_espresso'); |
|
| 94 | - |
|
| 95 | - $this->_tables = [ |
|
| 96 | - 'Price_Type' => new EE_Primary_Table('esp_price_type', 'PRT_ID'), |
|
| 97 | - ]; |
|
| 98 | - $this->_fields = [ |
|
| 99 | - 'Price_Type' => [ |
|
| 100 | - 'PRT_ID' => new EE_Primary_Key_Int_Field( |
|
| 101 | - 'PRT_ID', |
|
| 102 | - esc_html__('Price Type ID', 'event_espresso') |
|
| 103 | - ), |
|
| 104 | - 'PRT_name' => new EE_Plain_Text_Field( |
|
| 105 | - 'PRT_name', |
|
| 106 | - esc_html__('Price Type Name', 'event_espresso'), |
|
| 107 | - false, |
|
| 108 | - '' |
|
| 109 | - ), |
|
| 110 | - 'PBT_ID' => new EE_Enum_Integer_Field( |
|
| 111 | - 'PBT_ID', |
|
| 112 | - esc_html__( |
|
| 113 | - 'Price Base type ID, 1 = Price , 2 = Discount , 3 = Surcharge , 4 = Tax', |
|
| 114 | - 'event_espresso' |
|
| 115 | - ), |
|
| 116 | - false, |
|
| 117 | - EEM_Price_Type::base_type_base_price, |
|
| 118 | - $this->base_types |
|
| 119 | - ), |
|
| 120 | - 'PRT_is_percent' => new EE_Boolean_Field( |
|
| 121 | - 'PRT_is_percent', |
|
| 122 | - esc_html__('Flag indicating price is a percentage', 'event_espresso'), |
|
| 123 | - false, |
|
| 124 | - false |
|
| 125 | - ), |
|
| 126 | - 'PRT_order' => new EE_Integer_Field( |
|
| 127 | - 'PRT_order', |
|
| 128 | - esc_html__('Order in which price should be applied. ', 'event_espresso'), |
|
| 129 | - false, |
|
| 130 | - 0 |
|
| 131 | - ), |
|
| 132 | - 'PRT_deleted' => new EE_Trashed_Flag_Field( |
|
| 133 | - 'PRT_deleted', |
|
| 134 | - esc_html__('Flag indicating price type has been trashed', 'event_espresso'), |
|
| 135 | - false, |
|
| 136 | - false |
|
| 137 | - ), |
|
| 138 | - 'PRT_wp_user' => new EE_WP_User_Field( |
|
| 139 | - 'PRT_wp_user', |
|
| 140 | - esc_html__('Price Type Creator ID', 'event_espresso'), |
|
| 141 | - false |
|
| 142 | - ), |
|
| 143 | - ], |
|
| 144 | - ]; |
|
| 145 | - $this->_model_relations = [ |
|
| 146 | - 'Price' => new EE_Has_Many_Relation(), |
|
| 147 | - 'WP_User' => new EE_Belongs_To_Relation(), |
|
| 148 | - ]; |
|
| 149 | - // this model is generally available for reading |
|
| 150 | - $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public(); |
|
| 151 | - // all price types are "default" in terms of capability names |
|
| 152 | - $this->_caps_slug = 'default_price_types'; |
|
| 153 | - parent::__construct($timezone); |
|
| 154 | - } |
|
| 155 | - |
|
| 156 | - |
|
| 157 | - /** |
|
| 158 | - * instantiate a new price type object with blank/empty properties |
|
| 159 | - * |
|
| 160 | - * @return EE_Price_Type |
|
| 161 | - * @throws EE_Error |
|
| 162 | - * @throws ReflectionException |
|
| 163 | - */ |
|
| 164 | - public function get_new_price_type(): EE_Price_Type |
|
| 165 | - { |
|
| 166 | - return EE_Price_Type::new_instance(); |
|
| 167 | - } |
|
| 168 | - |
|
| 169 | - |
|
| 170 | - /** |
|
| 171 | - * |
|
| 172 | - * @param array $query_params |
|
| 173 | - * @param boolean $allow_blocking if TRUE, matched objects will only be deleted |
|
| 174 | - * if there is no related model info that blocks it |
|
| 175 | - * (ie, there' sno other data that depends on this data); |
|
| 176 | - * if false, deletes regardless of other objects which may depend on it. |
|
| 177 | - * Its generally advisable to always leave this as TRUE, |
|
| 178 | - * otherwise you could easily corrupt your DB |
|
| 179 | - * @return boolean |
|
| 180 | - * @throws EE_Error |
|
| 181 | - * @throws ReflectionException |
|
| 182 | - */ |
|
| 183 | - public function delete_permanently($query_params = [], $allow_blocking = true): bool |
|
| 184 | - { |
|
| 185 | - |
|
| 186 | - $would_be_deleted_price_types = $this->get_all_deleted_and_undeleted($query_params); |
|
| 187 | - $would_be_deleted_price_type_ids = array_keys($would_be_deleted_price_types); |
|
| 188 | - |
|
| 189 | - $ID = $query_params[0][ $this->get_primary_key_field()->get_name() ]; |
|
| 190 | - |
|
| 191 | - // check if any prices use this price type |
|
| 192 | - $prc_query_params = [['PRT_ID' => ['IN', $would_be_deleted_price_type_ids]]]; |
|
| 193 | - if ($prices = $this->get_all_related($ID, 'Price', $prc_query_params)) { |
|
| 194 | - $prices_names_and_ids = []; |
|
| 195 | - foreach ($prices as $price) { |
|
| 196 | - /* @var $price EE_Price */ |
|
| 197 | - $prices_names_and_ids[] = $price->name() . "(" . $price->ID() . ")"; |
|
| 198 | - } |
|
| 199 | - $msg = sprintf( |
|
| 200 | - esc_html__( |
|
| 201 | - 'The Price Type(s) could not be deleted because there are existing Prices that currently use this Price Type. If you still wish to delete this Price Type, then either delete those Prices or change them to use other Price Types.The prices are: %s', |
|
| 202 | - 'event_espresso' |
|
| 203 | - ), |
|
| 204 | - implode(",", $prices_names_and_ids) |
|
| 205 | - ); |
|
| 206 | - EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 207 | - return false; |
|
| 208 | - } |
|
| 209 | - |
|
| 210 | - return parent::delete_permanently($query_params); |
|
| 211 | - } |
|
| 13 | + /** |
|
| 14 | + * @var EEM_Price_Type |
|
| 15 | + */ |
|
| 16 | + protected static $_instance; |
|
| 17 | + |
|
| 18 | + // An array of the price type objects |
|
| 19 | + |
|
| 20 | + /** |
|
| 21 | + * @var string |
|
| 22 | + */ |
|
| 23 | + public $type; |
|
| 24 | + |
|
| 25 | + /** |
|
| 26 | + * Price Base types |
|
| 27 | + * Keys are INTs which are used in the database, |
|
| 28 | + * values are text-representations of the base type. |
|
| 29 | + * |
|
| 30 | + * @var string[] |
|
| 31 | + */ |
|
| 32 | + public $base_types; |
|
| 33 | + |
|
| 34 | + |
|
| 35 | + /** |
|
| 36 | + * return an array of Base types. |
|
| 37 | + * |
|
| 38 | + * @return string[] |
|
| 39 | + */ |
|
| 40 | + public function get_base_types(): array |
|
| 41 | + { |
|
| 42 | + return $this->base_types; |
|
| 43 | + } |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + /** |
|
| 47 | + * Gets the name of the base |
|
| 48 | + * |
|
| 49 | + * @param int $base_type_int |
|
| 50 | + * @return string |
|
| 51 | + */ |
|
| 52 | + public function get_base_type_name(int $base_type_int): string |
|
| 53 | + { |
|
| 54 | + return $this->base_types[ $base_type_int ]; |
|
| 55 | + } |
|
| 56 | + |
|
| 57 | + |
|
| 58 | + /** |
|
| 59 | + * constants for price base types. In the DB, we decided to store the price base type |
|
| 60 | + * as an integer. So, to avoid just having magic numbers everywhere (eg, querying for |
|
| 61 | + * all price types with PBT_ID = 2), we define these constants, to make code more understandable. |
|
| 62 | + * So, as an example, to query for all price types that are a tax, we'd do |
|
| 63 | + * EEM_PRice_Type::instance()->get_all(array(array('PBT_ID'=>EEM_Price_Type::base_type_tax))) |
|
| 64 | + * instead of |
|
| 65 | + * EEM_Price_Type::instance()->get_all(array(array('PBT_ID'=>2))) |
|
| 66 | + * Although the 2nd is shorter, it's much less obvious what it's doing. Also, should these magic IDs ever |
|
| 67 | + * change, we can continue to use the constant, by simply change its value. |
|
| 68 | + */ |
|
| 69 | + const base_type_base_price = 1; |
|
| 70 | + |
|
| 71 | + const base_type_discount = 2; |
|
| 72 | + |
|
| 73 | + const base_type_surcharge = 3; |
|
| 74 | + |
|
| 75 | + const base_type_tax = 4; |
|
| 76 | + |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * EEM_Price_Type constructor. |
|
| 80 | + * |
|
| 81 | + * @param string $timezone |
|
| 82 | + * @throws EE_Error |
|
| 83 | + */ |
|
| 84 | + protected function __construct(string $timezone = '') |
|
| 85 | + { |
|
| 86 | + $this->base_types = [ |
|
| 87 | + EEM_Price_Type::base_type_base_price => esc_html__('Price', 'event_espresso'), |
|
| 88 | + EEM_Price_Type::base_type_discount => esc_html__('Discount', 'event_espresso'), |
|
| 89 | + EEM_Price_Type::base_type_surcharge => esc_html__('Surcharge', 'event_espresso'), |
|
| 90 | + EEM_Price_Type::base_type_tax => esc_html__('Tax', 'event_espresso'), |
|
| 91 | + ]; |
|
| 92 | + $this->singular_item = esc_html__('Price Type', 'event_espresso'); |
|
| 93 | + $this->plural_item = esc_html__('Price Types', 'event_espresso'); |
|
| 94 | + |
|
| 95 | + $this->_tables = [ |
|
| 96 | + 'Price_Type' => new EE_Primary_Table('esp_price_type', 'PRT_ID'), |
|
| 97 | + ]; |
|
| 98 | + $this->_fields = [ |
|
| 99 | + 'Price_Type' => [ |
|
| 100 | + 'PRT_ID' => new EE_Primary_Key_Int_Field( |
|
| 101 | + 'PRT_ID', |
|
| 102 | + esc_html__('Price Type ID', 'event_espresso') |
|
| 103 | + ), |
|
| 104 | + 'PRT_name' => new EE_Plain_Text_Field( |
|
| 105 | + 'PRT_name', |
|
| 106 | + esc_html__('Price Type Name', 'event_espresso'), |
|
| 107 | + false, |
|
| 108 | + '' |
|
| 109 | + ), |
|
| 110 | + 'PBT_ID' => new EE_Enum_Integer_Field( |
|
| 111 | + 'PBT_ID', |
|
| 112 | + esc_html__( |
|
| 113 | + 'Price Base type ID, 1 = Price , 2 = Discount , 3 = Surcharge , 4 = Tax', |
|
| 114 | + 'event_espresso' |
|
| 115 | + ), |
|
| 116 | + false, |
|
| 117 | + EEM_Price_Type::base_type_base_price, |
|
| 118 | + $this->base_types |
|
| 119 | + ), |
|
| 120 | + 'PRT_is_percent' => new EE_Boolean_Field( |
|
| 121 | + 'PRT_is_percent', |
|
| 122 | + esc_html__('Flag indicating price is a percentage', 'event_espresso'), |
|
| 123 | + false, |
|
| 124 | + false |
|
| 125 | + ), |
|
| 126 | + 'PRT_order' => new EE_Integer_Field( |
|
| 127 | + 'PRT_order', |
|
| 128 | + esc_html__('Order in which price should be applied. ', 'event_espresso'), |
|
| 129 | + false, |
|
| 130 | + 0 |
|
| 131 | + ), |
|
| 132 | + 'PRT_deleted' => new EE_Trashed_Flag_Field( |
|
| 133 | + 'PRT_deleted', |
|
| 134 | + esc_html__('Flag indicating price type has been trashed', 'event_espresso'), |
|
| 135 | + false, |
|
| 136 | + false |
|
| 137 | + ), |
|
| 138 | + 'PRT_wp_user' => new EE_WP_User_Field( |
|
| 139 | + 'PRT_wp_user', |
|
| 140 | + esc_html__('Price Type Creator ID', 'event_espresso'), |
|
| 141 | + false |
|
| 142 | + ), |
|
| 143 | + ], |
|
| 144 | + ]; |
|
| 145 | + $this->_model_relations = [ |
|
| 146 | + 'Price' => new EE_Has_Many_Relation(), |
|
| 147 | + 'WP_User' => new EE_Belongs_To_Relation(), |
|
| 148 | + ]; |
|
| 149 | + // this model is generally available for reading |
|
| 150 | + $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public(); |
|
| 151 | + // all price types are "default" in terms of capability names |
|
| 152 | + $this->_caps_slug = 'default_price_types'; |
|
| 153 | + parent::__construct($timezone); |
|
| 154 | + } |
|
| 155 | + |
|
| 156 | + |
|
| 157 | + /** |
|
| 158 | + * instantiate a new price type object with blank/empty properties |
|
| 159 | + * |
|
| 160 | + * @return EE_Price_Type |
|
| 161 | + * @throws EE_Error |
|
| 162 | + * @throws ReflectionException |
|
| 163 | + */ |
|
| 164 | + public function get_new_price_type(): EE_Price_Type |
|
| 165 | + { |
|
| 166 | + return EE_Price_Type::new_instance(); |
|
| 167 | + } |
|
| 168 | + |
|
| 169 | + |
|
| 170 | + /** |
|
| 171 | + * |
|
| 172 | + * @param array $query_params |
|
| 173 | + * @param boolean $allow_blocking if TRUE, matched objects will only be deleted |
|
| 174 | + * if there is no related model info that blocks it |
|
| 175 | + * (ie, there' sno other data that depends on this data); |
|
| 176 | + * if false, deletes regardless of other objects which may depend on it. |
|
| 177 | + * Its generally advisable to always leave this as TRUE, |
|
| 178 | + * otherwise you could easily corrupt your DB |
|
| 179 | + * @return boolean |
|
| 180 | + * @throws EE_Error |
|
| 181 | + * @throws ReflectionException |
|
| 182 | + */ |
|
| 183 | + public function delete_permanently($query_params = [], $allow_blocking = true): bool |
|
| 184 | + { |
|
| 185 | + |
|
| 186 | + $would_be_deleted_price_types = $this->get_all_deleted_and_undeleted($query_params); |
|
| 187 | + $would_be_deleted_price_type_ids = array_keys($would_be_deleted_price_types); |
|
| 188 | + |
|
| 189 | + $ID = $query_params[0][ $this->get_primary_key_field()->get_name() ]; |
|
| 190 | + |
|
| 191 | + // check if any prices use this price type |
|
| 192 | + $prc_query_params = [['PRT_ID' => ['IN', $would_be_deleted_price_type_ids]]]; |
|
| 193 | + if ($prices = $this->get_all_related($ID, 'Price', $prc_query_params)) { |
|
| 194 | + $prices_names_and_ids = []; |
|
| 195 | + foreach ($prices as $price) { |
|
| 196 | + /* @var $price EE_Price */ |
|
| 197 | + $prices_names_and_ids[] = $price->name() . "(" . $price->ID() . ")"; |
|
| 198 | + } |
|
| 199 | + $msg = sprintf( |
|
| 200 | + esc_html__( |
|
| 201 | + 'The Price Type(s) could not be deleted because there are existing Prices that currently use this Price Type. If you still wish to delete this Price Type, then either delete those Prices or change them to use other Price Types.The prices are: %s', |
|
| 202 | + 'event_espresso' |
|
| 203 | + ), |
|
| 204 | + implode(",", $prices_names_and_ids) |
|
| 205 | + ); |
|
| 206 | + EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__); |
|
| 207 | + return false; |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + return parent::delete_permanently($query_params); |
|
| 211 | + } |
|
| 212 | 212 | } |
@@ -51,7 +51,7 @@ discard block |
||
| 51 | 51 | */ |
| 52 | 52 | public function get_base_type_name(int $base_type_int): string |
| 53 | 53 | { |
| 54 | - return $this->base_types[ $base_type_int ]; |
|
| 54 | + return $this->base_types[$base_type_int]; |
|
| 55 | 55 | } |
| 56 | 56 | |
| 57 | 57 | |
@@ -83,7 +83,7 @@ discard block |
||
| 83 | 83 | */ |
| 84 | 84 | protected function __construct(string $timezone = '') |
| 85 | 85 | { |
| 86 | - $this->base_types = [ |
|
| 86 | + $this->base_types = [ |
|
| 87 | 87 | EEM_Price_Type::base_type_base_price => esc_html__('Price', 'event_espresso'), |
| 88 | 88 | EEM_Price_Type::base_type_discount => esc_html__('Discount', 'event_espresso'), |
| 89 | 89 | EEM_Price_Type::base_type_surcharge => esc_html__('Surcharge', 'event_espresso'), |
@@ -147,7 +147,7 @@ discard block |
||
| 147 | 147 | 'WP_User' => new EE_Belongs_To_Relation(), |
| 148 | 148 | ]; |
| 149 | 149 | // this model is generally available for reading |
| 150 | - $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public(); |
|
| 150 | + $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public(); |
|
| 151 | 151 | // all price types are "default" in terms of capability names |
| 152 | 152 | $this->_caps_slug = 'default_price_types'; |
| 153 | 153 | parent::__construct($timezone); |
@@ -186,7 +186,7 @@ discard block |
||
| 186 | 186 | $would_be_deleted_price_types = $this->get_all_deleted_and_undeleted($query_params); |
| 187 | 187 | $would_be_deleted_price_type_ids = array_keys($would_be_deleted_price_types); |
| 188 | 188 | |
| 189 | - $ID = $query_params[0][ $this->get_primary_key_field()->get_name() ]; |
|
| 189 | + $ID = $query_params[0][$this->get_primary_key_field()->get_name()]; |
|
| 190 | 190 | |
| 191 | 191 | // check if any prices use this price type |
| 192 | 192 | $prc_query_params = [['PRT_ID' => ['IN', $would_be_deleted_price_type_ids]]]; |
@@ -194,7 +194,7 @@ discard block |
||
| 194 | 194 | $prices_names_and_ids = []; |
| 195 | 195 | foreach ($prices as $price) { |
| 196 | 196 | /* @var $price EE_Price */ |
| 197 | - $prices_names_and_ids[] = $price->name() . "(" . $price->ID() . ")"; |
|
| 197 | + $prices_names_and_ids[] = $price->name()."(".$price->ID().")"; |
|
| 198 | 198 | } |
| 199 | 199 | $msg = sprintf( |
| 200 | 200 | esc_html__( |
@@ -10,144 +10,144 @@ |
||
| 10 | 10 | class EEM_Term_Taxonomy extends EEM_Base |
| 11 | 11 | { |
| 12 | 12 | |
| 13 | - /** |
|
| 14 | - * @var EEM_Term_Taxonomy |
|
| 15 | - */ |
|
| 16 | - protected static $_instance; |
|
| 13 | + /** |
|
| 14 | + * @var EEM_Term_Taxonomy |
|
| 15 | + */ |
|
| 16 | + protected static $_instance; |
|
| 17 | 17 | |
| 18 | 18 | |
| 19 | - /** |
|
| 20 | - * EEM_Term_Taxonomy constructor. |
|
| 21 | - * |
|
| 22 | - * @param string $timezone |
|
| 23 | - * @throws EE_Error |
|
| 24 | - */ |
|
| 25 | - protected function __construct(string $timezone = '') |
|
| 26 | - { |
|
| 27 | - $this->singular_item = esc_html__('Term Taxonomy', 'event_espresso'); |
|
| 28 | - $this->plural_item = esc_html__('Term Taxonomy', 'event_espresso'); |
|
| 29 | - $this->_tables = [ |
|
| 30 | - 'Term_Taxonomy' => new EE_Primary_Table('term_taxonomy', 'term_taxonomy_id'), |
|
| 31 | - ]; |
|
| 32 | - $this->_fields = [ |
|
| 33 | - 'Term_Taxonomy' => [ |
|
| 34 | - 'term_taxonomy_id' => new EE_Primary_Key_Int_Field( |
|
| 35 | - 'term_taxonomy_id', |
|
| 36 | - esc_html__('Term-Taxonomy ID', 'event_espresso') |
|
| 37 | - ), |
|
| 38 | - 'term_id' => new EE_Foreign_Key_Int_Field( |
|
| 39 | - 'term_id', |
|
| 40 | - esc_html__("Term Id", "event_espresso"), |
|
| 41 | - false, |
|
| 42 | - 0, |
|
| 43 | - 'Term' |
|
| 44 | - ), |
|
| 45 | - 'taxonomy' => new EE_Plain_Text_Field( |
|
| 46 | - 'taxonomy', |
|
| 47 | - esc_html__('Taxonomy Name', 'event_espresso'), |
|
| 48 | - false, |
|
| 49 | - 'category' |
|
| 50 | - ), |
|
| 51 | - 'description' => new EE_Post_Content_Field( |
|
| 52 | - 'description', |
|
| 53 | - esc_html__("Description of Term", "event_espresso"), |
|
| 54 | - false, |
|
| 55 | - '' |
|
| 56 | - ), |
|
| 57 | - 'parent' => new EE_Integer_Field( |
|
| 58 | - 'parent', |
|
| 59 | - esc_html__("Parent Term ID", "event_espresso"), |
|
| 60 | - false, |
|
| 61 | - 0 |
|
| 62 | - ), |
|
| 63 | - 'term_count' => new EE_Integer_Field( |
|
| 64 | - 'count', |
|
| 65 | - esc_html__("Count of Objects attached", 'event_espresso'), |
|
| 66 | - false, |
|
| 67 | - 0 |
|
| 68 | - ), |
|
| 69 | - ], |
|
| 70 | - ]; |
|
| 71 | - $this->_model_relations = [ |
|
| 72 | - 'Term_Relationship' => new EE_Has_Many_Relation(), |
|
| 73 | - 'Term' => new EE_Belongs_To_Relation(), |
|
| 74 | - ]; |
|
| 75 | - $cpt_models = array_keys(EE_Registry::instance()->cpt_models()); |
|
| 76 | - foreach ($cpt_models as $model_name) { |
|
| 77 | - $this->_model_relations[ $model_name ] = new EE_HABTM_Relation('Term_Relationship'); |
|
| 78 | - } |
|
| 79 | - $this->_wp_core_model = true; |
|
| 80 | - $this->_indexes = [ |
|
| 81 | - 'term_id_taxonomy' => new EE_Unique_Index(['term_id', 'taxonomy']), |
|
| 82 | - ]; |
|
| 83 | - $path_to_tax_model = ''; |
|
| 84 | - $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public(); |
|
| 85 | - $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] |
|
| 86 | - = new EE_Restriction_Generator_Taxonomy_Protected( |
|
| 87 | - $path_to_tax_model |
|
| 88 | - ); |
|
| 89 | - $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = false; |
|
| 90 | - $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = false; |
|
| 91 | - // add cap restrictions for editing relating to the "ee_edit_*" |
|
| 92 | - $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_event_category'] = new EE_Default_Where_Conditions( |
|
| 93 | - [ |
|
| 94 | - $path_to_tax_model . 'taxonomy*ee_edit_event_category' => ['!=', 'espresso_event_categories'], |
|
| 95 | - ] |
|
| 96 | - ); |
|
| 97 | - $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_venue_category'] = new EE_Default_Where_Conditions( |
|
| 98 | - [ |
|
| 99 | - $path_to_tax_model . 'taxonomy*ee_edit_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 100 | - ] |
|
| 101 | - ); |
|
| 102 | - $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_event_type'] = new EE_Default_Where_Conditions( |
|
| 103 | - [ |
|
| 104 | - $path_to_tax_model . 'taxonomy*ee_edit_event_type' => ['!=', 'espresso_event_type'], |
|
| 105 | - ] |
|
| 106 | - ); |
|
| 107 | - // add cap restrictions for deleting relating to the "ee_deleting_*" |
|
| 108 | - $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_event_category'] = new EE_Default_Where_Conditions( |
|
| 109 | - [ |
|
| 110 | - $path_to_tax_model . 'taxonomy*ee_delete_event_category' => ['!=', 'espresso_event_categories'], |
|
| 111 | - ] |
|
| 112 | - ); |
|
| 113 | - $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_venue_category'] = new EE_Default_Where_Conditions( |
|
| 114 | - [ |
|
| 115 | - $path_to_tax_model . 'taxonomy*ee_delete_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 116 | - ] |
|
| 117 | - ); |
|
| 118 | - $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_event_type'] = new EE_Default_Where_Conditions( |
|
| 119 | - [ |
|
| 120 | - $path_to_tax_model . 'taxonomy*ee_delete_event_type' => ['!=', 'espresso_event_type'], |
|
| 121 | - ] |
|
| 122 | - ); |
|
| 123 | - parent::__construct($timezone); |
|
| 124 | - add_filter('FHEE__Read__create_model_query_params', ['EEM_Term_Taxonomy', 'rest_api_query_params'], 10, 3); |
|
| 125 | - } |
|
| 19 | + /** |
|
| 20 | + * EEM_Term_Taxonomy constructor. |
|
| 21 | + * |
|
| 22 | + * @param string $timezone |
|
| 23 | + * @throws EE_Error |
|
| 24 | + */ |
|
| 25 | + protected function __construct(string $timezone = '') |
|
| 26 | + { |
|
| 27 | + $this->singular_item = esc_html__('Term Taxonomy', 'event_espresso'); |
|
| 28 | + $this->plural_item = esc_html__('Term Taxonomy', 'event_espresso'); |
|
| 29 | + $this->_tables = [ |
|
| 30 | + 'Term_Taxonomy' => new EE_Primary_Table('term_taxonomy', 'term_taxonomy_id'), |
|
| 31 | + ]; |
|
| 32 | + $this->_fields = [ |
|
| 33 | + 'Term_Taxonomy' => [ |
|
| 34 | + 'term_taxonomy_id' => new EE_Primary_Key_Int_Field( |
|
| 35 | + 'term_taxonomy_id', |
|
| 36 | + esc_html__('Term-Taxonomy ID', 'event_espresso') |
|
| 37 | + ), |
|
| 38 | + 'term_id' => new EE_Foreign_Key_Int_Field( |
|
| 39 | + 'term_id', |
|
| 40 | + esc_html__("Term Id", "event_espresso"), |
|
| 41 | + false, |
|
| 42 | + 0, |
|
| 43 | + 'Term' |
|
| 44 | + ), |
|
| 45 | + 'taxonomy' => new EE_Plain_Text_Field( |
|
| 46 | + 'taxonomy', |
|
| 47 | + esc_html__('Taxonomy Name', 'event_espresso'), |
|
| 48 | + false, |
|
| 49 | + 'category' |
|
| 50 | + ), |
|
| 51 | + 'description' => new EE_Post_Content_Field( |
|
| 52 | + 'description', |
|
| 53 | + esc_html__("Description of Term", "event_espresso"), |
|
| 54 | + false, |
|
| 55 | + '' |
|
| 56 | + ), |
|
| 57 | + 'parent' => new EE_Integer_Field( |
|
| 58 | + 'parent', |
|
| 59 | + esc_html__("Parent Term ID", "event_espresso"), |
|
| 60 | + false, |
|
| 61 | + 0 |
|
| 62 | + ), |
|
| 63 | + 'term_count' => new EE_Integer_Field( |
|
| 64 | + 'count', |
|
| 65 | + esc_html__("Count of Objects attached", 'event_espresso'), |
|
| 66 | + false, |
|
| 67 | + 0 |
|
| 68 | + ), |
|
| 69 | + ], |
|
| 70 | + ]; |
|
| 71 | + $this->_model_relations = [ |
|
| 72 | + 'Term_Relationship' => new EE_Has_Many_Relation(), |
|
| 73 | + 'Term' => new EE_Belongs_To_Relation(), |
|
| 74 | + ]; |
|
| 75 | + $cpt_models = array_keys(EE_Registry::instance()->cpt_models()); |
|
| 76 | + foreach ($cpt_models as $model_name) { |
|
| 77 | + $this->_model_relations[ $model_name ] = new EE_HABTM_Relation('Term_Relationship'); |
|
| 78 | + } |
|
| 79 | + $this->_wp_core_model = true; |
|
| 80 | + $this->_indexes = [ |
|
| 81 | + 'term_id_taxonomy' => new EE_Unique_Index(['term_id', 'taxonomy']), |
|
| 82 | + ]; |
|
| 83 | + $path_to_tax_model = ''; |
|
| 84 | + $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public(); |
|
| 85 | + $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] |
|
| 86 | + = new EE_Restriction_Generator_Taxonomy_Protected( |
|
| 87 | + $path_to_tax_model |
|
| 88 | + ); |
|
| 89 | + $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = false; |
|
| 90 | + $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = false; |
|
| 91 | + // add cap restrictions for editing relating to the "ee_edit_*" |
|
| 92 | + $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_event_category'] = new EE_Default_Where_Conditions( |
|
| 93 | + [ |
|
| 94 | + $path_to_tax_model . 'taxonomy*ee_edit_event_category' => ['!=', 'espresso_event_categories'], |
|
| 95 | + ] |
|
| 96 | + ); |
|
| 97 | + $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_venue_category'] = new EE_Default_Where_Conditions( |
|
| 98 | + [ |
|
| 99 | + $path_to_tax_model . 'taxonomy*ee_edit_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 100 | + ] |
|
| 101 | + ); |
|
| 102 | + $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_event_type'] = new EE_Default_Where_Conditions( |
|
| 103 | + [ |
|
| 104 | + $path_to_tax_model . 'taxonomy*ee_edit_event_type' => ['!=', 'espresso_event_type'], |
|
| 105 | + ] |
|
| 106 | + ); |
|
| 107 | + // add cap restrictions for deleting relating to the "ee_deleting_*" |
|
| 108 | + $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_event_category'] = new EE_Default_Where_Conditions( |
|
| 109 | + [ |
|
| 110 | + $path_to_tax_model . 'taxonomy*ee_delete_event_category' => ['!=', 'espresso_event_categories'], |
|
| 111 | + ] |
|
| 112 | + ); |
|
| 113 | + $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_venue_category'] = new EE_Default_Where_Conditions( |
|
| 114 | + [ |
|
| 115 | + $path_to_tax_model . 'taxonomy*ee_delete_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 116 | + ] |
|
| 117 | + ); |
|
| 118 | + $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_event_type'] = new EE_Default_Where_Conditions( |
|
| 119 | + [ |
|
| 120 | + $path_to_tax_model . 'taxonomy*ee_delete_event_type' => ['!=', 'espresso_event_type'], |
|
| 121 | + ] |
|
| 122 | + ); |
|
| 123 | + parent::__construct($timezone); |
|
| 124 | + add_filter('FHEE__Read__create_model_query_params', ['EEM_Term_Taxonomy', 'rest_api_query_params'], 10, 3); |
|
| 125 | + } |
|
| 126 | 126 | |
| 127 | 127 | |
| 128 | - /** |
|
| 129 | - * Makes sure that during REST API queries, we only return term-taxonomies |
|
| 130 | - * for term taxonomies which should be shown in the rest api |
|
| 131 | - * |
|
| 132 | - * @param array $model_query_params |
|
| 133 | - * @param array $querystring_query_params |
|
| 134 | - * @param EEM_Base $model |
|
| 135 | - * @return array |
|
| 136 | - * @throws EE_Error |
|
| 137 | - */ |
|
| 138 | - public static function rest_api_query_params( |
|
| 139 | - array $model_query_params, |
|
| 140 | - array $querystring_query_params, |
|
| 141 | - EEM_Base $model |
|
| 142 | - ): array { |
|
| 143 | - if ($model === EEM_Term_Taxonomy::instance()) { |
|
| 144 | - $taxonomies = get_taxonomies(['show_in_rest' => true]); |
|
| 145 | - if (! empty($taxonomies)) { |
|
| 146 | - $model_query_params[0]['taxonomy'] = ['IN', $taxonomies]; |
|
| 147 | - } |
|
| 148 | - } |
|
| 149 | - return $model_query_params; |
|
| 150 | - } |
|
| 128 | + /** |
|
| 129 | + * Makes sure that during REST API queries, we only return term-taxonomies |
|
| 130 | + * for term taxonomies which should be shown in the rest api |
|
| 131 | + * |
|
| 132 | + * @param array $model_query_params |
|
| 133 | + * @param array $querystring_query_params |
|
| 134 | + * @param EEM_Base $model |
|
| 135 | + * @return array |
|
| 136 | + * @throws EE_Error |
|
| 137 | + */ |
|
| 138 | + public static function rest_api_query_params( |
|
| 139 | + array $model_query_params, |
|
| 140 | + array $querystring_query_params, |
|
| 141 | + EEM_Base $model |
|
| 142 | + ): array { |
|
| 143 | + if ($model === EEM_Term_Taxonomy::instance()) { |
|
| 144 | + $taxonomies = get_taxonomies(['show_in_rest' => true]); |
|
| 145 | + if (! empty($taxonomies)) { |
|
| 146 | + $model_query_params[0]['taxonomy'] = ['IN', $taxonomies]; |
|
| 147 | + } |
|
| 148 | + } |
|
| 149 | + return $model_query_params; |
|
| 150 | + } |
|
| 151 | 151 | } |
| 152 | 152 | // End of file EEM_Term_Taxonomy.model.php |
| 153 | 153 | // Location: /includes/models/EEM_Term_Taxonomy.model.php |
@@ -72,52 +72,52 @@ discard block |
||
| 72 | 72 | 'Term_Relationship' => new EE_Has_Many_Relation(), |
| 73 | 73 | 'Term' => new EE_Belongs_To_Relation(), |
| 74 | 74 | ]; |
| 75 | - $cpt_models = array_keys(EE_Registry::instance()->cpt_models()); |
|
| 75 | + $cpt_models = array_keys(EE_Registry::instance()->cpt_models()); |
|
| 76 | 76 | foreach ($cpt_models as $model_name) { |
| 77 | - $this->_model_relations[ $model_name ] = new EE_HABTM_Relation('Term_Relationship'); |
|
| 77 | + $this->_model_relations[$model_name] = new EE_HABTM_Relation('Term_Relationship'); |
|
| 78 | 78 | } |
| 79 | 79 | $this->_wp_core_model = true; |
| 80 | 80 | $this->_indexes = [ |
| 81 | 81 | 'term_id_taxonomy' => new EE_Unique_Index(['term_id', 'taxonomy']), |
| 82 | 82 | ]; |
| 83 | 83 | $path_to_tax_model = ''; |
| 84 | - $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public(); |
|
| 85 | - $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] |
|
| 84 | + $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public(); |
|
| 85 | + $this->_cap_restriction_generators[EEM_Base::caps_read_admin] |
|
| 86 | 86 | = new EE_Restriction_Generator_Taxonomy_Protected( |
| 87 | 87 | $path_to_tax_model |
| 88 | 88 | ); |
| 89 | - $this->_cap_restriction_generators[ EEM_Base::caps_edit ] = false; |
|
| 90 | - $this->_cap_restriction_generators[ EEM_Base::caps_delete ] = false; |
|
| 89 | + $this->_cap_restriction_generators[EEM_Base::caps_edit] = false; |
|
| 90 | + $this->_cap_restriction_generators[EEM_Base::caps_delete] = false; |
|
| 91 | 91 | // add cap restrictions for editing relating to the "ee_edit_*" |
| 92 | - $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_event_category'] = new EE_Default_Where_Conditions( |
|
| 92 | + $this->_cap_restrictions[EEM_Base::caps_edit]['ee_edit_event_category'] = new EE_Default_Where_Conditions( |
|
| 93 | 93 | [ |
| 94 | - $path_to_tax_model . 'taxonomy*ee_edit_event_category' => ['!=', 'espresso_event_categories'], |
|
| 94 | + $path_to_tax_model.'taxonomy*ee_edit_event_category' => ['!=', 'espresso_event_categories'], |
|
| 95 | 95 | ] |
| 96 | 96 | ); |
| 97 | - $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_venue_category'] = new EE_Default_Where_Conditions( |
|
| 97 | + $this->_cap_restrictions[EEM_Base::caps_edit]['ee_edit_venue_category'] = new EE_Default_Where_Conditions( |
|
| 98 | 98 | [ |
| 99 | - $path_to_tax_model . 'taxonomy*ee_edit_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 99 | + $path_to_tax_model.'taxonomy*ee_edit_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 100 | 100 | ] |
| 101 | 101 | ); |
| 102 | - $this->_cap_restrictions[ EEM_Base::caps_edit ]['ee_edit_event_type'] = new EE_Default_Where_Conditions( |
|
| 102 | + $this->_cap_restrictions[EEM_Base::caps_edit]['ee_edit_event_type'] = new EE_Default_Where_Conditions( |
|
| 103 | 103 | [ |
| 104 | - $path_to_tax_model . 'taxonomy*ee_edit_event_type' => ['!=', 'espresso_event_type'], |
|
| 104 | + $path_to_tax_model.'taxonomy*ee_edit_event_type' => ['!=', 'espresso_event_type'], |
|
| 105 | 105 | ] |
| 106 | 106 | ); |
| 107 | 107 | // add cap restrictions for deleting relating to the "ee_deleting_*" |
| 108 | - $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_event_category'] = new EE_Default_Where_Conditions( |
|
| 108 | + $this->_cap_restrictions[EEM_Base::caps_delete]['ee_delete_event_category'] = new EE_Default_Where_Conditions( |
|
| 109 | 109 | [ |
| 110 | - $path_to_tax_model . 'taxonomy*ee_delete_event_category' => ['!=', 'espresso_event_categories'], |
|
| 110 | + $path_to_tax_model.'taxonomy*ee_delete_event_category' => ['!=', 'espresso_event_categories'], |
|
| 111 | 111 | ] |
| 112 | 112 | ); |
| 113 | - $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_venue_category'] = new EE_Default_Where_Conditions( |
|
| 113 | + $this->_cap_restrictions[EEM_Base::caps_delete]['ee_delete_venue_category'] = new EE_Default_Where_Conditions( |
|
| 114 | 114 | [ |
| 115 | - $path_to_tax_model . 'taxonomy*ee_delete_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 115 | + $path_to_tax_model.'taxonomy*ee_delete_venue_category' => ['!=', 'espresso_venue_categories'], |
|
| 116 | 116 | ] |
| 117 | 117 | ); |
| 118 | - $this->_cap_restrictions[ EEM_Base::caps_delete ]['ee_delete_event_type'] = new EE_Default_Where_Conditions( |
|
| 118 | + $this->_cap_restrictions[EEM_Base::caps_delete]['ee_delete_event_type'] = new EE_Default_Where_Conditions( |
|
| 119 | 119 | [ |
| 120 | - $path_to_tax_model . 'taxonomy*ee_delete_event_type' => ['!=', 'espresso_event_type'], |
|
| 120 | + $path_to_tax_model.'taxonomy*ee_delete_event_type' => ['!=', 'espresso_event_type'], |
|
| 121 | 121 | ] |
| 122 | 122 | ); |
| 123 | 123 | parent::__construct($timezone); |
@@ -142,7 +142,7 @@ discard block |
||
| 142 | 142 | ): array { |
| 143 | 143 | if ($model === EEM_Term_Taxonomy::instance()) { |
| 144 | 144 | $taxonomies = get_taxonomies(['show_in_rest' => true]); |
| 145 | - if (! empty($taxonomies)) { |
|
| 145 | + if ( ! empty($taxonomies)) { |
|
| 146 | 146 | $model_query_params[0]['taxonomy'] = ['IN', $taxonomies]; |
| 147 | 147 | } |
| 148 | 148 | } |