@@ -29,843 +29,843 @@ |
||
29 | 29 | { |
30 | 30 | |
31 | 31 | |
32 | - /** |
|
33 | - * @var EE_Datetime_Offset_Fix_Form |
|
34 | - */ |
|
35 | - protected $datetime_fix_offset_form; |
|
36 | - |
|
37 | - |
|
38 | - |
|
39 | - protected function _init_page_props() |
|
40 | - { |
|
41 | - $this->page_slug = EE_MAINTENANCE_PG_SLUG; |
|
42 | - $this->page_label = EE_MAINTENANCE_LABEL; |
|
43 | - $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL; |
|
44 | - $this->_admin_base_path = EE_MAINTENANCE_ADMIN; |
|
45 | - } |
|
46 | - |
|
47 | - |
|
48 | - |
|
49 | - protected function _ajax_hooks() |
|
50 | - { |
|
51 | - add_action('wp_ajax_migration_step', array($this, 'migration_step')); |
|
52 | - add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran')); |
|
53 | - } |
|
54 | - |
|
55 | - |
|
56 | - |
|
57 | - protected function _define_page_props() |
|
58 | - { |
|
59 | - $this->_admin_page_title = EE_MAINTENANCE_LABEL; |
|
60 | - $this->_labels = array( |
|
61 | - 'buttons' => array( |
|
62 | - 'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'), |
|
63 | - 'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'), |
|
64 | - ), |
|
65 | - ); |
|
66 | - } |
|
67 | - |
|
68 | - |
|
69 | - |
|
70 | - protected function _set_page_routes() |
|
71 | - { |
|
72 | - $this->_page_routes = array( |
|
73 | - 'default' => array( |
|
74 | - 'func' => '_maintenance', |
|
75 | - 'capability' => 'manage_options', |
|
76 | - ), |
|
77 | - 'change_maintenance_level' => array( |
|
78 | - 'func' => '_change_maintenance_level', |
|
79 | - 'capability' => 'manage_options', |
|
80 | - 'noheader' => true, |
|
81 | - ), |
|
82 | - 'system_status' => array( |
|
83 | - 'func' => '_system_status', |
|
84 | - 'capability' => 'manage_options', |
|
85 | - ), |
|
86 | - 'download_system_status' => array( |
|
87 | - 'func' => '_download_system_status', |
|
88 | - 'capability' => 'manage_options', |
|
89 | - 'noheader' => true, |
|
90 | - ), |
|
91 | - 'send_migration_crash_report' => array( |
|
92 | - 'func' => '_send_migration_crash_report', |
|
93 | - 'capability' => 'manage_options', |
|
94 | - 'noheader' => true, |
|
95 | - ), |
|
96 | - 'confirm_migration_crash_report_sent' => array( |
|
97 | - 'func' => '_confirm_migration_crash_report_sent', |
|
98 | - 'capability' => 'manage_options', |
|
99 | - ), |
|
100 | - 'data_reset' => array( |
|
101 | - 'func' => '_data_reset_and_delete', |
|
102 | - 'capability' => 'manage_options', |
|
103 | - ), |
|
104 | - 'reset_db' => array( |
|
105 | - 'func' => '_reset_db', |
|
106 | - 'capability' => 'manage_options', |
|
107 | - 'noheader' => true, |
|
108 | - 'args' => array('nuke_old_ee4_data' => true), |
|
109 | - ), |
|
110 | - 'start_with_fresh_ee4_db' => array( |
|
111 | - 'func' => '_reset_db', |
|
112 | - 'capability' => 'manage_options', |
|
113 | - 'noheader' => true, |
|
114 | - 'args' => array('nuke_old_ee4_data' => false), |
|
115 | - ), |
|
116 | - 'delete_db' => array( |
|
117 | - 'func' => '_delete_db', |
|
118 | - 'capability' => 'manage_options', |
|
119 | - 'noheader' => true, |
|
120 | - ), |
|
121 | - 'rerun_migration_from_ee3' => array( |
|
122 | - 'func' => '_rerun_migration_from_ee3', |
|
123 | - 'capability' => 'manage_options', |
|
124 | - 'noheader' => true, |
|
125 | - ), |
|
126 | - 'reset_reservations' => array( |
|
127 | - 'func' => '_reset_reservations', |
|
128 | - 'capability' => 'manage_options', |
|
129 | - 'noheader' => true, |
|
130 | - ), |
|
131 | - 'reset_capabilities' => array( |
|
132 | - 'func' => '_reset_capabilities', |
|
133 | - 'capability' => 'manage_options', |
|
134 | - 'noheader' => true, |
|
135 | - ), |
|
136 | - 'reattempt_migration' => array( |
|
137 | - 'func' => '_reattempt_migration', |
|
138 | - 'capability' => 'manage_options', |
|
139 | - 'noheader' => true, |
|
140 | - ), |
|
141 | - 'datetime_tools' => array( |
|
142 | - 'func' => '_datetime_tools', |
|
143 | - 'capability' => 'manage_options' |
|
144 | - ), |
|
145 | - 'run_datetime_offset_fix' => array( |
|
146 | - 'func' => '_apply_datetime_offset', |
|
147 | - 'noheader' => true, |
|
148 | - 'headers_sent_route' => 'datetime_tools', |
|
149 | - 'capability' => 'manage_options' |
|
150 | - ) |
|
151 | - ); |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - |
|
156 | - protected function _set_page_config() |
|
157 | - { |
|
158 | - $this->_page_config = array( |
|
159 | - 'default' => array( |
|
160 | - 'nav' => array( |
|
161 | - 'label' => esc_html__('Maintenance', 'event_espresso'), |
|
162 | - 'order' => 10, |
|
163 | - ), |
|
164 | - 'require_nonce' => false, |
|
165 | - ), |
|
166 | - 'data_reset' => array( |
|
167 | - 'nav' => array( |
|
168 | - 'label' => esc_html__('Reset/Delete Data', 'event_espresso'), |
|
169 | - 'order' => 20, |
|
170 | - ), |
|
171 | - 'require_nonce' => false, |
|
172 | - ), |
|
173 | - 'datetime_tools' => array( |
|
174 | - 'nav' => array( |
|
175 | - 'label' => esc_html__('Datetime Utilities', 'event_espresso'), |
|
176 | - 'order' => 25 |
|
177 | - ), |
|
178 | - 'require_nonce' => false, |
|
179 | - ), |
|
180 | - 'system_status' => array( |
|
181 | - 'nav' => array( |
|
182 | - 'label' => esc_html__("System Information", "event_espresso"), |
|
183 | - 'order' => 30, |
|
184 | - ), |
|
185 | - 'require_nonce' => false, |
|
186 | - ), |
|
187 | - ); |
|
188 | - } |
|
189 | - |
|
190 | - |
|
191 | - |
|
192 | - /** |
|
193 | - * default maintenance page. If we're in maintenance mode level 2, then we need to show |
|
194 | - * the migration scripts and all that UI. |
|
195 | - */ |
|
196 | - public function _maintenance() |
|
197 | - { |
|
198 | - //it all depends if we're in maintenance model level 1 (frontend-only) or |
|
199 | - //level 2 (everything except maintenance page) |
|
200 | - try { |
|
201 | - //get the current maintenance level and check if |
|
202 | - //we are removed |
|
203 | - $mm = EE_Maintenance_Mode::instance()->level(); |
|
204 | - $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
205 | - if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) { |
|
206 | - //we just took the site out of maintenance mode, so notify the user. |
|
207 | - //unfortunately this message appears to be echoed on the NEXT page load... |
|
208 | - //oh well, we should really be checking for this on addon deactivation anyways |
|
209 | - EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required', |
|
210 | - 'event_espresso')); |
|
211 | - $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false); |
|
212 | - } |
|
213 | - //in case an exception is thrown while trying to handle migrations |
|
214 | - switch (EE_Maintenance_Mode::instance()->level()) { |
|
215 | - case EE_Maintenance_Mode::level_0_not_in_maintenance: |
|
216 | - case EE_Maintenance_Mode::level_1_frontend_only_maintenance: |
|
217 | - $show_maintenance_switch = true; |
|
218 | - $show_backup_db_text = false; |
|
219 | - $show_migration_progress = false; |
|
220 | - $script_names = array(); |
|
221 | - $addons_should_be_upgraded_first = false; |
|
222 | - break; |
|
223 | - case EE_Maintenance_Mode::level_2_complete_maintenance: |
|
224 | - $show_maintenance_switch = false; |
|
225 | - $show_migration_progress = true; |
|
226 | - if (isset($this->_req_data['continue_migration'])) { |
|
227 | - $show_backup_db_text = false; |
|
228 | - } else { |
|
229 | - $show_backup_db_text = true; |
|
230 | - } |
|
231 | - $scripts_needing_to_run = EE_Data_Migration_Manager::instance() |
|
232 | - ->check_for_applicable_data_migration_scripts(); |
|
233 | - $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating(); |
|
234 | - $script_names = array(); |
|
235 | - $current_script = null; |
|
236 | - foreach ($scripts_needing_to_run as $script) { |
|
237 | - if ($script instanceof EE_Data_Migration_Script_Base) { |
|
238 | - if ( ! $current_script) { |
|
239 | - $current_script = $script; |
|
240 | - $current_script->migration_page_hooks(); |
|
241 | - } |
|
242 | - $script_names[] = $script->pretty_name(); |
|
243 | - } |
|
244 | - } |
|
245 | - break; |
|
246 | - } |
|
247 | - $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
248 | - $exception_thrown = false; |
|
249 | - } catch (EE_Error $e) { |
|
250 | - EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
251 | - //now, just so we can display the page correctly, make a error migration script stage object |
|
252 | - //and also put the error on it. It only persists for the duration of this request |
|
253 | - $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
254 | - $most_recent_migration->add_error($e->getMessage()); |
|
255 | - $exception_thrown = true; |
|
256 | - } |
|
257 | - $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set(); |
|
258 | - $current_db_state = str_replace('.decaf', '', $current_db_state); |
|
259 | - if ($exception_thrown |
|
260 | - || ($most_recent_migration |
|
261 | - && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
262 | - && $most_recent_migration->is_broken() |
|
263 | - ) |
|
264 | - ) { |
|
265 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php'; |
|
266 | - $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/'; |
|
267 | - $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action' => 'confirm_migration_crash_report_sent', |
|
268 | - 'success' => '0', |
|
269 | - ), EE_MAINTENANCE_ADMIN_URL); |
|
270 | - } elseif ($addons_should_be_upgraded_first) { |
|
271 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php'; |
|
272 | - } else { |
|
273 | - if ($most_recent_migration |
|
274 | - && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
275 | - && $most_recent_migration->can_continue() |
|
276 | - ) { |
|
277 | - $show_backup_db_text = false; |
|
278 | - $show_continue_current_migration_script = true; |
|
279 | - $show_most_recent_migration = true; |
|
280 | - } elseif (isset($this->_req_data['continue_migration'])) { |
|
281 | - $show_most_recent_migration = true; |
|
282 | - $show_continue_current_migration_script = false; |
|
283 | - } else { |
|
284 | - $show_most_recent_migration = false; |
|
285 | - $show_continue_current_migration_script = false; |
|
286 | - } |
|
287 | - if (isset($current_script)) { |
|
288 | - $migrates_to = $current_script->migrates_to_version(); |
|
289 | - $plugin_slug = $migrates_to['slug']; |
|
290 | - $new_version = $migrates_to['version']; |
|
291 | - $this->_template_args = array_merge($this->_template_args, array( |
|
292 | - 'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"), |
|
293 | - isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug), |
|
294 | - 'next_db_state' => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'), |
|
295 | - $new_version, $plugin_slug) : null, |
|
296 | - )); |
|
297 | - } else { |
|
298 | - $this->_template_args['current_db_state'] = null; |
|
299 | - $this->_template_args['next_db_state'] = null; |
|
300 | - } |
|
301 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php'; |
|
302 | - $this->_template_args = array_merge( |
|
303 | - $this->_template_args, |
|
304 | - array( |
|
305 | - 'show_most_recent_migration' => $show_most_recent_migration, |
|
306 | - //flag for showing the most recent migration's status and/or errors |
|
307 | - 'show_migration_progress' => $show_migration_progress, |
|
308 | - //flag for showing the option to run migrations and see their progress |
|
309 | - 'show_backup_db_text' => $show_backup_db_text, |
|
310 | - //flag for showing text telling the user to backup their DB |
|
311 | - 'show_maintenance_switch' => $show_maintenance_switch, |
|
312 | - //flag for showing the option to change maintenance mode between levels 0 and 1 |
|
313 | - 'script_names' => $script_names, |
|
314 | - //array of names of scripts that have run |
|
315 | - 'show_continue_current_migration_script' => $show_continue_current_migration_script, |
|
316 | - //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0 |
|
317 | - 'reset_db_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
318 | - EE_MAINTENANCE_ADMIN_URL), |
|
319 | - 'data_reset_page' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
320 | - EE_MAINTENANCE_ADMIN_URL), |
|
321 | - 'update_migration_script_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'), |
|
322 | - EE_MAINTENANCE_ADMIN_URL), |
|
323 | - 'ultimate_db_state' => sprintf(__("EE%s", 'event_espresso'), |
|
324 | - espresso_version()), |
|
325 | - ) |
|
326 | - ); |
|
327 | - //make sure we have the form fields helper available. It usually is, but sometimes it isn't |
|
328 | - } |
|
329 | - $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration |
|
330 | - //now render the migration options part, and put it in a variable |
|
331 | - $migration_options_template_file = apply_filters( |
|
332 | - 'FHEE__ee_migration_page__migration_options_template', |
|
333 | - EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php' |
|
334 | - ); |
|
335 | - $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true); |
|
336 | - $this->_template_args['migration_options_html'] = $migration_options_html; |
|
337 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
338 | - $this->_template_args, true); |
|
339 | - $this->display_admin_page_with_sidebar(); |
|
340 | - } |
|
341 | - |
|
342 | - |
|
343 | - |
|
344 | - /** |
|
345 | - * returns JSON and executes another step of the currently-executing data migration (called via ajax) |
|
346 | - */ |
|
347 | - public function migration_step() |
|
348 | - { |
|
349 | - $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request(); |
|
350 | - $this->_return_json(); |
|
351 | - } |
|
352 | - |
|
353 | - |
|
354 | - |
|
355 | - /** |
|
356 | - * Can be used by js when it notices a response with HTML in it in order |
|
357 | - * to log the malformed response |
|
358 | - */ |
|
359 | - public function add_error_to_migrations_ran() |
|
360 | - { |
|
361 | - EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']); |
|
362 | - $this->_template_args['data'] = array('ok' => true); |
|
363 | - $this->_return_json(); |
|
364 | - } |
|
365 | - |
|
366 | - |
|
367 | - |
|
368 | - /** |
|
369 | - * changes the maintenance level, provided there are still no migration scripts that should run |
|
370 | - */ |
|
371 | - public function _change_maintenance_level() |
|
372 | - { |
|
373 | - $new_level = absint($this->_req_data['maintenance_mode_level']); |
|
374 | - if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) { |
|
375 | - EE_Maintenance_Mode::instance()->set_maintenance_level($new_level); |
|
376 | - $success = true; |
|
377 | - } else { |
|
378 | - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
379 | - $success = false; |
|
380 | - } |
|
381 | - $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso")); |
|
382 | - } |
|
383 | - |
|
384 | - |
|
385 | - |
|
386 | - /** |
|
387 | - * a tab with options for resetting and/or deleting EE data |
|
388 | - * |
|
389 | - * @throws \EE_Error |
|
390 | - * @throws \DomainException |
|
391 | - */ |
|
392 | - public function _data_reset_and_delete() |
|
393 | - { |
|
394 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php'; |
|
395 | - $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button( |
|
396 | - 'reset_reservations', |
|
397 | - 'reset_reservations', |
|
398 | - array(), |
|
399 | - 'button button-primary ee-confirm', |
|
400 | - '', |
|
401 | - false |
|
402 | - ); |
|
403 | - $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button( |
|
404 | - 'reset_capabilities', |
|
405 | - 'reset_capabilities', |
|
406 | - array(), |
|
407 | - 'button button-primary ee-confirm', |
|
408 | - '', |
|
409 | - false |
|
410 | - ); |
|
411 | - $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
412 | - array('action' => 'delete_db'), |
|
413 | - EE_MAINTENANCE_ADMIN_URL |
|
414 | - ); |
|
415 | - $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
416 | - array('action' => 'reset_db'), |
|
417 | - EE_MAINTENANCE_ADMIN_URL |
|
418 | - ); |
|
419 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
420 | - $this->_template_path, |
|
421 | - $this->_template_args, |
|
422 | - true |
|
423 | - ); |
|
424 | - $this->display_admin_page_with_sidebar(); |
|
425 | - } |
|
426 | - |
|
427 | - |
|
428 | - |
|
429 | - protected function _reset_reservations() |
|
430 | - { |
|
431 | - if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) { |
|
432 | - EE_Error::add_success( |
|
433 | - __( |
|
434 | - 'Ticket and datetime reserved counts have been successfully reset.', |
|
435 | - 'event_espresso' |
|
436 | - ) |
|
437 | - ); |
|
438 | - } else { |
|
439 | - EE_Error::add_success( |
|
440 | - __( |
|
441 | - 'Ticket and datetime reserved counts were correct and did not need resetting.', |
|
442 | - 'event_espresso' |
|
443 | - ) |
|
444 | - ); |
|
445 | - } |
|
446 | - $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true); |
|
447 | - } |
|
448 | - |
|
449 | - |
|
450 | - |
|
451 | - protected function _reset_capabilities() |
|
452 | - { |
|
453 | - EE_Registry::instance()->CAP->init_caps(true); |
|
454 | - EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.', |
|
455 | - 'event_espresso')); |
|
456 | - $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true); |
|
457 | - } |
|
458 | - |
|
459 | - |
|
460 | - |
|
461 | - /** |
|
462 | - * resets the DMSs so we can attempt to continue migrating after a fatal error |
|
463 | - * (only a good idea when someone has somehow tried ot fix whatever caused |
|
464 | - * the fatal error in teh first place) |
|
465 | - */ |
|
466 | - protected function _reattempt_migration() |
|
467 | - { |
|
468 | - EE_Data_Migration_Manager::instance()->reattempt(); |
|
469 | - $this->_redirect_after_action(false, '', '', array('action' => 'default'), true); |
|
470 | - } |
|
471 | - |
|
472 | - |
|
473 | - |
|
474 | - /** |
|
475 | - * shows the big ol' System Information page |
|
476 | - */ |
|
477 | - public function _system_status() |
|
478 | - { |
|
479 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php'; |
|
480 | - $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati(); |
|
481 | - $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
482 | - array( |
|
483 | - 'action' => 'download_system_status', |
|
484 | - ), |
|
485 | - EE_MAINTENANCE_ADMIN_URL |
|
486 | - ); |
|
487 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
488 | - $this->_template_args, true); |
|
489 | - $this->display_admin_page_with_sidebar(); |
|
490 | - } |
|
491 | - |
|
492 | - /** |
|
493 | - * Downloads an HTML file of the system status that can be easily stored or emailed |
|
494 | - */ |
|
495 | - public function _download_system_status() |
|
496 | - { |
|
497 | - $status_info = EEM_System_Status::instance()->get_system_stati(); |
|
498 | - header( 'Content-Disposition: attachment' ); |
|
499 | - header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" ); |
|
500 | - echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>"; |
|
501 | - echo "<h1>System Information for " . site_url() . "</h1>"; |
|
502 | - echo EEH_Template::layout_array_as_table( $status_info ); |
|
503 | - die; |
|
504 | - } |
|
505 | - |
|
506 | - |
|
507 | - |
|
508 | - public function _send_migration_crash_report() |
|
509 | - { |
|
510 | - $from = $this->_req_data['from']; |
|
511 | - $from_name = $this->_req_data['from_name']; |
|
512 | - $body = $this->_req_data['body']; |
|
513 | - try { |
|
514 | - $success = wp_mail(EE_SUPPORT_EMAIL, |
|
515 | - 'Migration Crash Report', |
|
516 | - $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true), |
|
517 | - array( |
|
518 | - "from:$from_name<$from>", |
|
519 | - // 'content-type:text/html charset=UTF-8' |
|
520 | - )); |
|
521 | - } catch (Exception $e) { |
|
522 | - $success = false; |
|
523 | - } |
|
524 | - $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"), |
|
525 | - esc_html__("sent", "event_espresso"), |
|
526 | - array('success' => $success, 'action' => 'confirm_migration_crash_report_sent')); |
|
527 | - } |
|
528 | - |
|
529 | - |
|
530 | - |
|
531 | - public function _confirm_migration_crash_report_sent() |
|
532 | - { |
|
533 | - try { |
|
534 | - $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
535 | - } catch (EE_Error $e) { |
|
536 | - EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
537 | - //now, just so we can display the page correctly, make a error migration script stage object |
|
538 | - //and also put the error on it. It only persists for the duration of this request |
|
539 | - $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
540 | - $most_recent_migration->add_error($e->getMessage()); |
|
541 | - } |
|
542 | - $success = $this->_req_data['success'] == '1' ? true : false; |
|
543 | - $this->_template_args['success'] = $success; |
|
544 | - $this->_template_args['most_recent_migration'] = $most_recent_migration; |
|
545 | - $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
546 | - EE_MAINTENANCE_ADMIN_URL); |
|
547 | - $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
548 | - EE_MAINTENANCE_ADMIN_URL); |
|
549 | - $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'), |
|
550 | - EE_MAINTENANCE_ADMIN_URL); |
|
551 | - $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php'; |
|
552 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
553 | - $this->_template_args, true); |
|
554 | - $this->display_admin_page_with_sidebar(); |
|
555 | - } |
|
556 | - |
|
557 | - |
|
558 | - |
|
559 | - /** |
|
560 | - * Resets the entire EE4 database. |
|
561 | - * Currently basically only sets up ee4 database for a fresh install- doesn't |
|
562 | - * actually clean out the old wp options, or cpts (although does erase old ee table data) |
|
563 | - * |
|
564 | - * @param boolean $nuke_old_ee4_data controls whether or not we |
|
565 | - * destroy the old ee4 data, or just try initializing ee4 default data |
|
566 | - */ |
|
567 | - public function _reset_db($nuke_old_ee4_data = true) |
|
568 | - { |
|
569 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
570 | - if ($nuke_old_ee4_data) { |
|
571 | - EEH_Activation::delete_all_espresso_cpt_data(); |
|
572 | - EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
573 | - EEH_Activation::remove_cron_tasks(); |
|
574 | - } |
|
575 | - //make sure when we reset the registry's config that it |
|
576 | - //switches to using the new singleton |
|
577 | - EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true); |
|
578 | - EE_System::instance()->initialize_db_if_no_migrations_required(true); |
|
579 | - EE_System::instance()->redirect_to_about_ee(); |
|
580 | - } |
|
581 | - |
|
582 | - |
|
583 | - |
|
584 | - /** |
|
585 | - * Deletes ALL EE tables, Records, and Options from the database. |
|
586 | - */ |
|
587 | - public function _delete_db() |
|
588 | - { |
|
589 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
590 | - EEH_Activation::delete_all_espresso_cpt_data(); |
|
591 | - EEH_Activation::delete_all_espresso_tables_and_data(); |
|
592 | - EEH_Activation::remove_cron_tasks(); |
|
593 | - EEH_Activation::deactivate_event_espresso(); |
|
594 | - wp_safe_redirect(admin_url('plugins.php')); |
|
595 | - exit; |
|
596 | - } |
|
597 | - |
|
598 | - |
|
599 | - |
|
600 | - /** |
|
601 | - * sets up EE4 to rerun the migrations from ee3 to ee4 |
|
602 | - */ |
|
603 | - public function _rerun_migration_from_ee3() |
|
604 | - { |
|
605 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
606 | - EEH_Activation::delete_all_espresso_cpt_data(); |
|
607 | - EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
608 | - //set the db state to something that will require migrations |
|
609 | - update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0'); |
|
610 | - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance); |
|
611 | - $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso')); |
|
612 | - } |
|
613 | - |
|
614 | - |
|
615 | - |
|
616 | - //none of the below group are currently used for Gateway Settings |
|
617 | - protected function _add_screen_options() |
|
618 | - { |
|
619 | - } |
|
620 | - |
|
621 | - |
|
622 | - |
|
623 | - protected function _add_feature_pointers() |
|
624 | - { |
|
625 | - } |
|
626 | - |
|
32 | + /** |
|
33 | + * @var EE_Datetime_Offset_Fix_Form |
|
34 | + */ |
|
35 | + protected $datetime_fix_offset_form; |
|
36 | + |
|
37 | + |
|
38 | + |
|
39 | + protected function _init_page_props() |
|
40 | + { |
|
41 | + $this->page_slug = EE_MAINTENANCE_PG_SLUG; |
|
42 | + $this->page_label = EE_MAINTENANCE_LABEL; |
|
43 | + $this->_admin_base_url = EE_MAINTENANCE_ADMIN_URL; |
|
44 | + $this->_admin_base_path = EE_MAINTENANCE_ADMIN; |
|
45 | + } |
|
46 | + |
|
47 | + |
|
48 | + |
|
49 | + protected function _ajax_hooks() |
|
50 | + { |
|
51 | + add_action('wp_ajax_migration_step', array($this, 'migration_step')); |
|
52 | + add_action('wp_ajax_add_error_to_migrations_ran', array($this, 'add_error_to_migrations_ran')); |
|
53 | + } |
|
54 | + |
|
55 | + |
|
56 | + |
|
57 | + protected function _define_page_props() |
|
58 | + { |
|
59 | + $this->_admin_page_title = EE_MAINTENANCE_LABEL; |
|
60 | + $this->_labels = array( |
|
61 | + 'buttons' => array( |
|
62 | + 'reset_reservations' => esc_html__('Reset Ticket and Datetime Reserved Counts', 'event_espresso'), |
|
63 | + 'reset_capabilities' => esc_html__('Reset Event Espresso Capabilities', 'event_espresso'), |
|
64 | + ), |
|
65 | + ); |
|
66 | + } |
|
67 | + |
|
68 | + |
|
69 | + |
|
70 | + protected function _set_page_routes() |
|
71 | + { |
|
72 | + $this->_page_routes = array( |
|
73 | + 'default' => array( |
|
74 | + 'func' => '_maintenance', |
|
75 | + 'capability' => 'manage_options', |
|
76 | + ), |
|
77 | + 'change_maintenance_level' => array( |
|
78 | + 'func' => '_change_maintenance_level', |
|
79 | + 'capability' => 'manage_options', |
|
80 | + 'noheader' => true, |
|
81 | + ), |
|
82 | + 'system_status' => array( |
|
83 | + 'func' => '_system_status', |
|
84 | + 'capability' => 'manage_options', |
|
85 | + ), |
|
86 | + 'download_system_status' => array( |
|
87 | + 'func' => '_download_system_status', |
|
88 | + 'capability' => 'manage_options', |
|
89 | + 'noheader' => true, |
|
90 | + ), |
|
91 | + 'send_migration_crash_report' => array( |
|
92 | + 'func' => '_send_migration_crash_report', |
|
93 | + 'capability' => 'manage_options', |
|
94 | + 'noheader' => true, |
|
95 | + ), |
|
96 | + 'confirm_migration_crash_report_sent' => array( |
|
97 | + 'func' => '_confirm_migration_crash_report_sent', |
|
98 | + 'capability' => 'manage_options', |
|
99 | + ), |
|
100 | + 'data_reset' => array( |
|
101 | + 'func' => '_data_reset_and_delete', |
|
102 | + 'capability' => 'manage_options', |
|
103 | + ), |
|
104 | + 'reset_db' => array( |
|
105 | + 'func' => '_reset_db', |
|
106 | + 'capability' => 'manage_options', |
|
107 | + 'noheader' => true, |
|
108 | + 'args' => array('nuke_old_ee4_data' => true), |
|
109 | + ), |
|
110 | + 'start_with_fresh_ee4_db' => array( |
|
111 | + 'func' => '_reset_db', |
|
112 | + 'capability' => 'manage_options', |
|
113 | + 'noheader' => true, |
|
114 | + 'args' => array('nuke_old_ee4_data' => false), |
|
115 | + ), |
|
116 | + 'delete_db' => array( |
|
117 | + 'func' => '_delete_db', |
|
118 | + 'capability' => 'manage_options', |
|
119 | + 'noheader' => true, |
|
120 | + ), |
|
121 | + 'rerun_migration_from_ee3' => array( |
|
122 | + 'func' => '_rerun_migration_from_ee3', |
|
123 | + 'capability' => 'manage_options', |
|
124 | + 'noheader' => true, |
|
125 | + ), |
|
126 | + 'reset_reservations' => array( |
|
127 | + 'func' => '_reset_reservations', |
|
128 | + 'capability' => 'manage_options', |
|
129 | + 'noheader' => true, |
|
130 | + ), |
|
131 | + 'reset_capabilities' => array( |
|
132 | + 'func' => '_reset_capabilities', |
|
133 | + 'capability' => 'manage_options', |
|
134 | + 'noheader' => true, |
|
135 | + ), |
|
136 | + 'reattempt_migration' => array( |
|
137 | + 'func' => '_reattempt_migration', |
|
138 | + 'capability' => 'manage_options', |
|
139 | + 'noheader' => true, |
|
140 | + ), |
|
141 | + 'datetime_tools' => array( |
|
142 | + 'func' => '_datetime_tools', |
|
143 | + 'capability' => 'manage_options' |
|
144 | + ), |
|
145 | + 'run_datetime_offset_fix' => array( |
|
146 | + 'func' => '_apply_datetime_offset', |
|
147 | + 'noheader' => true, |
|
148 | + 'headers_sent_route' => 'datetime_tools', |
|
149 | + 'capability' => 'manage_options' |
|
150 | + ) |
|
151 | + ); |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + |
|
156 | + protected function _set_page_config() |
|
157 | + { |
|
158 | + $this->_page_config = array( |
|
159 | + 'default' => array( |
|
160 | + 'nav' => array( |
|
161 | + 'label' => esc_html__('Maintenance', 'event_espresso'), |
|
162 | + 'order' => 10, |
|
163 | + ), |
|
164 | + 'require_nonce' => false, |
|
165 | + ), |
|
166 | + 'data_reset' => array( |
|
167 | + 'nav' => array( |
|
168 | + 'label' => esc_html__('Reset/Delete Data', 'event_espresso'), |
|
169 | + 'order' => 20, |
|
170 | + ), |
|
171 | + 'require_nonce' => false, |
|
172 | + ), |
|
173 | + 'datetime_tools' => array( |
|
174 | + 'nav' => array( |
|
175 | + 'label' => esc_html__('Datetime Utilities', 'event_espresso'), |
|
176 | + 'order' => 25 |
|
177 | + ), |
|
178 | + 'require_nonce' => false, |
|
179 | + ), |
|
180 | + 'system_status' => array( |
|
181 | + 'nav' => array( |
|
182 | + 'label' => esc_html__("System Information", "event_espresso"), |
|
183 | + 'order' => 30, |
|
184 | + ), |
|
185 | + 'require_nonce' => false, |
|
186 | + ), |
|
187 | + ); |
|
188 | + } |
|
189 | + |
|
190 | + |
|
191 | + |
|
192 | + /** |
|
193 | + * default maintenance page. If we're in maintenance mode level 2, then we need to show |
|
194 | + * the migration scripts and all that UI. |
|
195 | + */ |
|
196 | + public function _maintenance() |
|
197 | + { |
|
198 | + //it all depends if we're in maintenance model level 1 (frontend-only) or |
|
199 | + //level 2 (everything except maintenance page) |
|
200 | + try { |
|
201 | + //get the current maintenance level and check if |
|
202 | + //we are removed |
|
203 | + $mm = EE_Maintenance_Mode::instance()->level(); |
|
204 | + $placed_in_mm = EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
205 | + if ($mm == EE_Maintenance_Mode::level_2_complete_maintenance && ! $placed_in_mm) { |
|
206 | + //we just took the site out of maintenance mode, so notify the user. |
|
207 | + //unfortunately this message appears to be echoed on the NEXT page load... |
|
208 | + //oh well, we should really be checking for this on addon deactivation anyways |
|
209 | + EE_Error::add_attention(__('Site taken out of maintenance mode because no data migration scripts are required', |
|
210 | + 'event_espresso')); |
|
211 | + $this->_process_notices(array('page' => 'espresso_maintenance_settings'), false); |
|
212 | + } |
|
213 | + //in case an exception is thrown while trying to handle migrations |
|
214 | + switch (EE_Maintenance_Mode::instance()->level()) { |
|
215 | + case EE_Maintenance_Mode::level_0_not_in_maintenance: |
|
216 | + case EE_Maintenance_Mode::level_1_frontend_only_maintenance: |
|
217 | + $show_maintenance_switch = true; |
|
218 | + $show_backup_db_text = false; |
|
219 | + $show_migration_progress = false; |
|
220 | + $script_names = array(); |
|
221 | + $addons_should_be_upgraded_first = false; |
|
222 | + break; |
|
223 | + case EE_Maintenance_Mode::level_2_complete_maintenance: |
|
224 | + $show_maintenance_switch = false; |
|
225 | + $show_migration_progress = true; |
|
226 | + if (isset($this->_req_data['continue_migration'])) { |
|
227 | + $show_backup_db_text = false; |
|
228 | + } else { |
|
229 | + $show_backup_db_text = true; |
|
230 | + } |
|
231 | + $scripts_needing_to_run = EE_Data_Migration_Manager::instance() |
|
232 | + ->check_for_applicable_data_migration_scripts(); |
|
233 | + $addons_should_be_upgraded_first = EE_Data_Migration_Manager::instance()->addons_need_updating(); |
|
234 | + $script_names = array(); |
|
235 | + $current_script = null; |
|
236 | + foreach ($scripts_needing_to_run as $script) { |
|
237 | + if ($script instanceof EE_Data_Migration_Script_Base) { |
|
238 | + if ( ! $current_script) { |
|
239 | + $current_script = $script; |
|
240 | + $current_script->migration_page_hooks(); |
|
241 | + } |
|
242 | + $script_names[] = $script->pretty_name(); |
|
243 | + } |
|
244 | + } |
|
245 | + break; |
|
246 | + } |
|
247 | + $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
248 | + $exception_thrown = false; |
|
249 | + } catch (EE_Error $e) { |
|
250 | + EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
251 | + //now, just so we can display the page correctly, make a error migration script stage object |
|
252 | + //and also put the error on it. It only persists for the duration of this request |
|
253 | + $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
254 | + $most_recent_migration->add_error($e->getMessage()); |
|
255 | + $exception_thrown = true; |
|
256 | + } |
|
257 | + $current_db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set(); |
|
258 | + $current_db_state = str_replace('.decaf', '', $current_db_state); |
|
259 | + if ($exception_thrown |
|
260 | + || ($most_recent_migration |
|
261 | + && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
262 | + && $most_recent_migration->is_broken() |
|
263 | + ) |
|
264 | + ) { |
|
265 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_was_borked_page.template.php'; |
|
266 | + $this->_template_args['support_url'] = 'http://eventespresso.com/support/forums/'; |
|
267 | + $this->_template_args['next_url'] = EEH_URL::add_query_args_and_nonce(array('action' => 'confirm_migration_crash_report_sent', |
|
268 | + 'success' => '0', |
|
269 | + ), EE_MAINTENANCE_ADMIN_URL); |
|
270 | + } elseif ($addons_should_be_upgraded_first) { |
|
271 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_upgrade_addons_before_migrating.template.php'; |
|
272 | + } else { |
|
273 | + if ($most_recent_migration |
|
274 | + && $most_recent_migration instanceof EE_Data_Migration_Script_Base |
|
275 | + && $most_recent_migration->can_continue() |
|
276 | + ) { |
|
277 | + $show_backup_db_text = false; |
|
278 | + $show_continue_current_migration_script = true; |
|
279 | + $show_most_recent_migration = true; |
|
280 | + } elseif (isset($this->_req_data['continue_migration'])) { |
|
281 | + $show_most_recent_migration = true; |
|
282 | + $show_continue_current_migration_script = false; |
|
283 | + } else { |
|
284 | + $show_most_recent_migration = false; |
|
285 | + $show_continue_current_migration_script = false; |
|
286 | + } |
|
287 | + if (isset($current_script)) { |
|
288 | + $migrates_to = $current_script->migrates_to_version(); |
|
289 | + $plugin_slug = $migrates_to['slug']; |
|
290 | + $new_version = $migrates_to['version']; |
|
291 | + $this->_template_args = array_merge($this->_template_args, array( |
|
292 | + 'current_db_state' => sprintf(__("EE%s (%s)", "event_espresso"), |
|
293 | + isset($current_db_state[$plugin_slug]) ? $current_db_state[$plugin_slug] : 3, $plugin_slug), |
|
294 | + 'next_db_state' => isset($current_script) ? sprintf(__("EE%s (%s)", 'event_espresso'), |
|
295 | + $new_version, $plugin_slug) : null, |
|
296 | + )); |
|
297 | + } else { |
|
298 | + $this->_template_args['current_db_state'] = null; |
|
299 | + $this->_template_args['next_db_state'] = null; |
|
300 | + } |
|
301 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_migration_page.template.php'; |
|
302 | + $this->_template_args = array_merge( |
|
303 | + $this->_template_args, |
|
304 | + array( |
|
305 | + 'show_most_recent_migration' => $show_most_recent_migration, |
|
306 | + //flag for showing the most recent migration's status and/or errors |
|
307 | + 'show_migration_progress' => $show_migration_progress, |
|
308 | + //flag for showing the option to run migrations and see their progress |
|
309 | + 'show_backup_db_text' => $show_backup_db_text, |
|
310 | + //flag for showing text telling the user to backup their DB |
|
311 | + 'show_maintenance_switch' => $show_maintenance_switch, |
|
312 | + //flag for showing the option to change maintenance mode between levels 0 and 1 |
|
313 | + 'script_names' => $script_names, |
|
314 | + //array of names of scripts that have run |
|
315 | + 'show_continue_current_migration_script' => $show_continue_current_migration_script, |
|
316 | + //flag to change wording to indicating that we're only CONTINUING a migration script (somehow it got interrupted0 |
|
317 | + 'reset_db_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
318 | + EE_MAINTENANCE_ADMIN_URL), |
|
319 | + 'data_reset_page' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
320 | + EE_MAINTENANCE_ADMIN_URL), |
|
321 | + 'update_migration_script_page_link' => EE_Admin_Page::add_query_args_and_nonce(array('action' => 'change_maintenance_level'), |
|
322 | + EE_MAINTENANCE_ADMIN_URL), |
|
323 | + 'ultimate_db_state' => sprintf(__("EE%s", 'event_espresso'), |
|
324 | + espresso_version()), |
|
325 | + ) |
|
326 | + ); |
|
327 | + //make sure we have the form fields helper available. It usually is, but sometimes it isn't |
|
328 | + } |
|
329 | + $this->_template_args['most_recent_migration'] = $most_recent_migration;//the actual most recently ran migration |
|
330 | + //now render the migration options part, and put it in a variable |
|
331 | + $migration_options_template_file = apply_filters( |
|
332 | + 'FHEE__ee_migration_page__migration_options_template', |
|
333 | + EE_MAINTENANCE_TEMPLATE_PATH . 'migration_options_from_ee4.template.php' |
|
334 | + ); |
|
335 | + $migration_options_html = EEH_Template::display_template($migration_options_template_file, $this->_template_args,true); |
|
336 | + $this->_template_args['migration_options_html'] = $migration_options_html; |
|
337 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
338 | + $this->_template_args, true); |
|
339 | + $this->display_admin_page_with_sidebar(); |
|
340 | + } |
|
341 | + |
|
342 | + |
|
343 | + |
|
344 | + /** |
|
345 | + * returns JSON and executes another step of the currently-executing data migration (called via ajax) |
|
346 | + */ |
|
347 | + public function migration_step() |
|
348 | + { |
|
349 | + $this->_template_args['data'] = EE_Data_Migration_Manager::instance()->response_to_migration_ajax_request(); |
|
350 | + $this->_return_json(); |
|
351 | + } |
|
352 | + |
|
353 | + |
|
354 | + |
|
355 | + /** |
|
356 | + * Can be used by js when it notices a response with HTML in it in order |
|
357 | + * to log the malformed response |
|
358 | + */ |
|
359 | + public function add_error_to_migrations_ran() |
|
360 | + { |
|
361 | + EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($this->_req_data['message']); |
|
362 | + $this->_template_args['data'] = array('ok' => true); |
|
363 | + $this->_return_json(); |
|
364 | + } |
|
365 | + |
|
366 | + |
|
367 | + |
|
368 | + /** |
|
369 | + * changes the maintenance level, provided there are still no migration scripts that should run |
|
370 | + */ |
|
371 | + public function _change_maintenance_level() |
|
372 | + { |
|
373 | + $new_level = absint($this->_req_data['maintenance_mode_level']); |
|
374 | + if ( ! EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts()) { |
|
375 | + EE_Maintenance_Mode::instance()->set_maintenance_level($new_level); |
|
376 | + $success = true; |
|
377 | + } else { |
|
378 | + EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); |
|
379 | + $success = false; |
|
380 | + } |
|
381 | + $this->_redirect_after_action($success, 'Maintenance Mode', esc_html__("Updated", "event_espresso")); |
|
382 | + } |
|
383 | + |
|
384 | + |
|
385 | + |
|
386 | + /** |
|
387 | + * a tab with options for resetting and/or deleting EE data |
|
388 | + * |
|
389 | + * @throws \EE_Error |
|
390 | + * @throws \DomainException |
|
391 | + */ |
|
392 | + public function _data_reset_and_delete() |
|
393 | + { |
|
394 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_data_reset_and_delete.template.php'; |
|
395 | + $this->_template_args['reset_reservations_button'] = $this->get_action_link_or_button( |
|
396 | + 'reset_reservations', |
|
397 | + 'reset_reservations', |
|
398 | + array(), |
|
399 | + 'button button-primary ee-confirm', |
|
400 | + '', |
|
401 | + false |
|
402 | + ); |
|
403 | + $this->_template_args['reset_capabilities_button'] = $this->get_action_link_or_button( |
|
404 | + 'reset_capabilities', |
|
405 | + 'reset_capabilities', |
|
406 | + array(), |
|
407 | + 'button button-primary ee-confirm', |
|
408 | + '', |
|
409 | + false |
|
410 | + ); |
|
411 | + $this->_template_args['delete_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
412 | + array('action' => 'delete_db'), |
|
413 | + EE_MAINTENANCE_ADMIN_URL |
|
414 | + ); |
|
415 | + $this->_template_args['reset_db_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
416 | + array('action' => 'reset_db'), |
|
417 | + EE_MAINTENANCE_ADMIN_URL |
|
418 | + ); |
|
419 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
420 | + $this->_template_path, |
|
421 | + $this->_template_args, |
|
422 | + true |
|
423 | + ); |
|
424 | + $this->display_admin_page_with_sidebar(); |
|
425 | + } |
|
426 | + |
|
427 | + |
|
428 | + |
|
429 | + protected function _reset_reservations() |
|
430 | + { |
|
431 | + if(\EED_Ticket_Sales_Monitor::reset_reservation_counts()) { |
|
432 | + EE_Error::add_success( |
|
433 | + __( |
|
434 | + 'Ticket and datetime reserved counts have been successfully reset.', |
|
435 | + 'event_espresso' |
|
436 | + ) |
|
437 | + ); |
|
438 | + } else { |
|
439 | + EE_Error::add_success( |
|
440 | + __( |
|
441 | + 'Ticket and datetime reserved counts were correct and did not need resetting.', |
|
442 | + 'event_espresso' |
|
443 | + ) |
|
444 | + ); |
|
445 | + } |
|
446 | + $this->_redirect_after_action(true, '', '', array('action' => 'data_reset'), true); |
|
447 | + } |
|
448 | + |
|
449 | + |
|
450 | + |
|
451 | + protected function _reset_capabilities() |
|
452 | + { |
|
453 | + EE_Registry::instance()->CAP->init_caps(true); |
|
454 | + EE_Error::add_success(__('Default Event Espresso capabilities have been restored for all current roles.', |
|
455 | + 'event_espresso')); |
|
456 | + $this->_redirect_after_action(false, '', '', array('action' => 'data_reset'), true); |
|
457 | + } |
|
458 | + |
|
459 | + |
|
460 | + |
|
461 | + /** |
|
462 | + * resets the DMSs so we can attempt to continue migrating after a fatal error |
|
463 | + * (only a good idea when someone has somehow tried ot fix whatever caused |
|
464 | + * the fatal error in teh first place) |
|
465 | + */ |
|
466 | + protected function _reattempt_migration() |
|
467 | + { |
|
468 | + EE_Data_Migration_Manager::instance()->reattempt(); |
|
469 | + $this->_redirect_after_action(false, '', '', array('action' => 'default'), true); |
|
470 | + } |
|
471 | + |
|
472 | + |
|
473 | + |
|
474 | + /** |
|
475 | + * shows the big ol' System Information page |
|
476 | + */ |
|
477 | + public function _system_status() |
|
478 | + { |
|
479 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_system_stati_page.template.php'; |
|
480 | + $this->_template_args['system_stati'] = EEM_System_Status::instance()->get_system_stati(); |
|
481 | + $this->_template_args['download_system_status_url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
482 | + array( |
|
483 | + 'action' => 'download_system_status', |
|
484 | + ), |
|
485 | + EE_MAINTENANCE_ADMIN_URL |
|
486 | + ); |
|
487 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
488 | + $this->_template_args, true); |
|
489 | + $this->display_admin_page_with_sidebar(); |
|
490 | + } |
|
491 | + |
|
492 | + /** |
|
493 | + * Downloads an HTML file of the system status that can be easily stored or emailed |
|
494 | + */ |
|
495 | + public function _download_system_status() |
|
496 | + { |
|
497 | + $status_info = EEM_System_Status::instance()->get_system_stati(); |
|
498 | + header( 'Content-Disposition: attachment' ); |
|
499 | + header( "Content-Disposition: attachment; filename=system_status_" . sanitize_key( site_url() ) . ".html" ); |
|
500 | + echo "<style>table{border:1px solid darkgrey;}td{vertical-align:top}</style>"; |
|
501 | + echo "<h1>System Information for " . site_url() . "</h1>"; |
|
502 | + echo EEH_Template::layout_array_as_table( $status_info ); |
|
503 | + die; |
|
504 | + } |
|
505 | + |
|
506 | + |
|
507 | + |
|
508 | + public function _send_migration_crash_report() |
|
509 | + { |
|
510 | + $from = $this->_req_data['from']; |
|
511 | + $from_name = $this->_req_data['from_name']; |
|
512 | + $body = $this->_req_data['body']; |
|
513 | + try { |
|
514 | + $success = wp_mail(EE_SUPPORT_EMAIL, |
|
515 | + 'Migration Crash Report', |
|
516 | + $body . "/r/n<br>" . print_r(EEM_System_Status::instance()->get_system_stati(), true), |
|
517 | + array( |
|
518 | + "from:$from_name<$from>", |
|
519 | + // 'content-type:text/html charset=UTF-8' |
|
520 | + )); |
|
521 | + } catch (Exception $e) { |
|
522 | + $success = false; |
|
523 | + } |
|
524 | + $this->_redirect_after_action($success, esc_html__("Migration Crash Report", "event_espresso"), |
|
525 | + esc_html__("sent", "event_espresso"), |
|
526 | + array('success' => $success, 'action' => 'confirm_migration_crash_report_sent')); |
|
527 | + } |
|
528 | + |
|
529 | + |
|
530 | + |
|
531 | + public function _confirm_migration_crash_report_sent() |
|
532 | + { |
|
533 | + try { |
|
534 | + $most_recent_migration = EE_Data_Migration_Manager::instance()->get_last_ran_script(true); |
|
535 | + } catch (EE_Error $e) { |
|
536 | + EE_Data_Migration_Manager::instance()->add_error_to_migrations_ran($e->getMessage()); |
|
537 | + //now, just so we can display the page correctly, make a error migration script stage object |
|
538 | + //and also put the error on it. It only persists for the duration of this request |
|
539 | + $most_recent_migration = new EE_DMS_Unknown_1_0_0(); |
|
540 | + $most_recent_migration->add_error($e->getMessage()); |
|
541 | + } |
|
542 | + $success = $this->_req_data['success'] == '1' ? true : false; |
|
543 | + $this->_template_args['success'] = $success; |
|
544 | + $this->_template_args['most_recent_migration'] = $most_recent_migration; |
|
545 | + $this->_template_args['reset_db_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reset_db'), |
|
546 | + EE_MAINTENANCE_ADMIN_URL); |
|
547 | + $this->_template_args['reset_db_page_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'data_reset'), |
|
548 | + EE_MAINTENANCE_ADMIN_URL); |
|
549 | + $this->_template_args['reattempt_action_url'] = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'reattempt_migration'), |
|
550 | + EE_MAINTENANCE_ADMIN_URL); |
|
551 | + $this->_template_path = EE_MAINTENANCE_TEMPLATE_PATH . 'ee_confirm_migration_crash_report_sent.template.php'; |
|
552 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_template_path, |
|
553 | + $this->_template_args, true); |
|
554 | + $this->display_admin_page_with_sidebar(); |
|
555 | + } |
|
556 | + |
|
557 | + |
|
558 | + |
|
559 | + /** |
|
560 | + * Resets the entire EE4 database. |
|
561 | + * Currently basically only sets up ee4 database for a fresh install- doesn't |
|
562 | + * actually clean out the old wp options, or cpts (although does erase old ee table data) |
|
563 | + * |
|
564 | + * @param boolean $nuke_old_ee4_data controls whether or not we |
|
565 | + * destroy the old ee4 data, or just try initializing ee4 default data |
|
566 | + */ |
|
567 | + public function _reset_db($nuke_old_ee4_data = true) |
|
568 | + { |
|
569 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
570 | + if ($nuke_old_ee4_data) { |
|
571 | + EEH_Activation::delete_all_espresso_cpt_data(); |
|
572 | + EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
573 | + EEH_Activation::remove_cron_tasks(); |
|
574 | + } |
|
575 | + //make sure when we reset the registry's config that it |
|
576 | + //switches to using the new singleton |
|
577 | + EE_Registry::instance()->CFG = EE_Registry::instance()->CFG->reset(true); |
|
578 | + EE_System::instance()->initialize_db_if_no_migrations_required(true); |
|
579 | + EE_System::instance()->redirect_to_about_ee(); |
|
580 | + } |
|
581 | + |
|
582 | + |
|
583 | + |
|
584 | + /** |
|
585 | + * Deletes ALL EE tables, Records, and Options from the database. |
|
586 | + */ |
|
587 | + public function _delete_db() |
|
588 | + { |
|
589 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
590 | + EEH_Activation::delete_all_espresso_cpt_data(); |
|
591 | + EEH_Activation::delete_all_espresso_tables_and_data(); |
|
592 | + EEH_Activation::remove_cron_tasks(); |
|
593 | + EEH_Activation::deactivate_event_espresso(); |
|
594 | + wp_safe_redirect(admin_url('plugins.php')); |
|
595 | + exit; |
|
596 | + } |
|
597 | + |
|
598 | + |
|
599 | + |
|
600 | + /** |
|
601 | + * sets up EE4 to rerun the migrations from ee3 to ee4 |
|
602 | + */ |
|
603 | + public function _rerun_migration_from_ee3() |
|
604 | + { |
|
605 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); |
|
606 | + EEH_Activation::delete_all_espresso_cpt_data(); |
|
607 | + EEH_Activation::delete_all_espresso_tables_and_data(false); |
|
608 | + //set the db state to something that will require migrations |
|
609 | + update_option(EE_Data_Migration_Manager::current_database_state, '3.1.36.0'); |
|
610 | + EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_2_complete_maintenance); |
|
611 | + $this->_redirect_after_action(true, esc_html__("Database", 'event_espresso'), esc_html__("reset", 'event_espresso')); |
|
612 | + } |
|
613 | + |
|
614 | + |
|
615 | + |
|
616 | + //none of the below group are currently used for Gateway Settings |
|
617 | + protected function _add_screen_options() |
|
618 | + { |
|
619 | + } |
|
620 | + |
|
621 | + |
|
622 | + |
|
623 | + protected function _add_feature_pointers() |
|
624 | + { |
|
625 | + } |
|
626 | + |
|
627 | 627 | |
628 | 628 | |
629 | - public function admin_init() |
|
630 | - { |
|
631 | - } |
|
632 | - |
|
633 | - |
|
634 | - |
|
635 | - public function admin_notices() |
|
636 | - { |
|
637 | - } |
|
638 | - |
|
629 | + public function admin_init() |
|
630 | + { |
|
631 | + } |
|
632 | + |
|
633 | + |
|
634 | + |
|
635 | + public function admin_notices() |
|
636 | + { |
|
637 | + } |
|
638 | + |
|
639 | 639 | |
640 | 640 | |
641 | - public function admin_footer_scripts() |
|
642 | - { |
|
643 | - } |
|
641 | + public function admin_footer_scripts() |
|
642 | + { |
|
643 | + } |
|
644 | 644 | |
645 | 645 | |
646 | 646 | |
647 | - public function load_scripts_styles() |
|
648 | - { |
|
649 | - wp_enqueue_script('ee_admin_js'); |
|
647 | + public function load_scripts_styles() |
|
648 | + { |
|
649 | + wp_enqueue_script('ee_admin_js'); |
|
650 | 650 | // wp_enqueue_media(); |
651 | 651 | // wp_enqueue_script('media-upload'); |
652 | - wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'), |
|
653 | - EVENT_ESPRESSO_VERSION, true); |
|
654 | - wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(), |
|
655 | - EVENT_ESPRESSO_VERSION); |
|
656 | - wp_enqueue_style('espresso_maintenance'); |
|
657 | - //localize script stuff |
|
658 | - wp_localize_script('ee-maintenance', 'ee_maintenance', array( |
|
659 | - 'migrating' => esc_html__("Updating Database...", "event_espresso"), |
|
660 | - 'next' => esc_html__("Next", "event_espresso"), |
|
661 | - 'fatal_error' => esc_html__("A Fatal Error Has Occurred", "event_espresso"), |
|
662 | - 'click_next_when_ready' => esc_html__( |
|
663 | - "The current Database Update has ended. Click 'next' when ready to proceed", |
|
664 | - "event_espresso" |
|
665 | - ), |
|
666 | - 'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts, |
|
667 | - 'status_fatal_error' => EE_Data_Migration_Manager::status_fatal_error, |
|
668 | - 'status_completed' => EE_Data_Migration_Manager::status_completed, |
|
669 | - 'confirm' => esc_html__( |
|
670 | - 'Are you sure you want to do this? It CANNOT be undone!', |
|
671 | - 'event_espresso' |
|
672 | - ), |
|
673 | - 'confirm_skip_migration' => esc_html__( |
|
674 | - 'You have chosen to NOT migrate your existing data. Are you sure you want to continue?', |
|
675 | - 'event_espresso' |
|
676 | - ) |
|
677 | - )); |
|
678 | - } |
|
679 | - |
|
680 | - |
|
681 | - |
|
682 | - public function load_scripts_styles_default() |
|
683 | - { |
|
684 | - //styles |
|
652 | + wp_enqueue_script('ee-maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.js', array('jquery'), |
|
653 | + EVENT_ESPRESSO_VERSION, true); |
|
654 | + wp_register_style('espresso_maintenance', EE_MAINTENANCE_ASSETS_URL . 'ee-maintenance.css', array(), |
|
655 | + EVENT_ESPRESSO_VERSION); |
|
656 | + wp_enqueue_style('espresso_maintenance'); |
|
657 | + //localize script stuff |
|
658 | + wp_localize_script('ee-maintenance', 'ee_maintenance', array( |
|
659 | + 'migrating' => esc_html__("Updating Database...", "event_espresso"), |
|
660 | + 'next' => esc_html__("Next", "event_espresso"), |
|
661 | + 'fatal_error' => esc_html__("A Fatal Error Has Occurred", "event_espresso"), |
|
662 | + 'click_next_when_ready' => esc_html__( |
|
663 | + "The current Database Update has ended. Click 'next' when ready to proceed", |
|
664 | + "event_espresso" |
|
665 | + ), |
|
666 | + 'status_no_more_migration_scripts' => EE_Data_Migration_Manager::status_no_more_migration_scripts, |
|
667 | + 'status_fatal_error' => EE_Data_Migration_Manager::status_fatal_error, |
|
668 | + 'status_completed' => EE_Data_Migration_Manager::status_completed, |
|
669 | + 'confirm' => esc_html__( |
|
670 | + 'Are you sure you want to do this? It CANNOT be undone!', |
|
671 | + 'event_espresso' |
|
672 | + ), |
|
673 | + 'confirm_skip_migration' => esc_html__( |
|
674 | + 'You have chosen to NOT migrate your existing data. Are you sure you want to continue?', |
|
675 | + 'event_espresso' |
|
676 | + ) |
|
677 | + )); |
|
678 | + } |
|
679 | + |
|
680 | + |
|
681 | + |
|
682 | + public function load_scripts_styles_default() |
|
683 | + { |
|
684 | + //styles |
|
685 | 685 | // wp_enqueue_style('ee-text-links'); |
686 | 686 | // //scripts |
687 | 687 | // wp_enqueue_script('ee-text-links'); |
688 | - } |
|
689 | - |
|
690 | - |
|
691 | - /** |
|
692 | - * Enqueue scripts and styles for the datetime tools page. |
|
693 | - */ |
|
694 | - public function load_scripts_styles_datetime_tools() |
|
695 | - { |
|
696 | - EE_Datepicker_Input::enqueue_styles_and_scripts(); |
|
697 | - } |
|
698 | - |
|
699 | - |
|
700 | - protected function _datetime_tools() |
|
701 | - { |
|
702 | - $form_action = EE_Admin_Page::add_query_args_and_nonce( |
|
703 | - array( |
|
704 | - 'action' => 'run_datetime_offset_fix', |
|
705 | - 'return_action' => $this->_req_action |
|
706 | - ), |
|
707 | - EE_MAINTENANCE_ADMIN_URL |
|
708 | - ); |
|
709 | - $form = $this->_get_datetime_offset_fix_form(); |
|
710 | - $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso'); |
|
711 | - $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post') |
|
712 | - . $form->get_html_and_js() |
|
713 | - . $form->form_close(); |
|
714 | - $this->display_admin_page_with_no_sidebar(); |
|
715 | - } |
|
716 | - |
|
717 | - |
|
718 | - |
|
719 | - protected function _get_datetime_offset_fix_form() |
|
720 | - { |
|
721 | - if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) { |
|
722 | - $this->datetime_fix_offset_form = new EE_Form_Section_Proper( |
|
723 | - array( |
|
724 | - 'name' => 'datetime_offset_fix_option', |
|
725 | - 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
726 | - 'subsections' => array( |
|
727 | - 'title' => new EE_Form_Section_HTML( |
|
728 | - EEH_HTML::h2( |
|
729 | - esc_html__('Datetime Offset Tool', 'event_espresso') |
|
730 | - ) |
|
731 | - ), |
|
732 | - 'explanation' => new EE_Form_Section_HTML( |
|
733 | - EEH_HTML::p( |
|
734 | - esc_html__( |
|
735 | - 'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.', |
|
736 | - 'event_espresso' |
|
737 | - ) |
|
738 | - ) |
|
739 | - . EEH_HTML::p( |
|
740 | - esc_html__( |
|
741 | - 'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied. Decimals represent the fraction of hours, not minutes.', |
|
742 | - 'event_espresso' |
|
743 | - ) |
|
744 | - ) |
|
745 | - ), |
|
746 | - 'offset_input' => new EE_Float_Input( |
|
747 | - array( |
|
748 | - 'html_name' => 'offset_for_datetimes', |
|
749 | - 'html_label_text' => esc_html__( |
|
750 | - 'Offset to apply (in hours):', |
|
751 | - 'event_espresso' |
|
752 | - ), |
|
753 | - 'min_value' => '-12', |
|
754 | - 'max_value' => '14', |
|
755 | - 'step_value' => '.25', |
|
756 | - 'default' => DatetimeOffsetFix::getOffset() |
|
757 | - ) |
|
758 | - ), |
|
759 | - 'date_range_explanation' => new EE_Form_Section_HTML( |
|
760 | - EEH_HTML::p( |
|
761 | - esc_html__( |
|
762 | - 'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.', |
|
763 | - 'event_espresso' |
|
764 | - ) |
|
765 | - ) |
|
766 | - . EEH_HTML::p( |
|
767 | - EEH_HTML::strong( |
|
768 | - sprintf( |
|
769 | - esc_html__( |
|
770 | - 'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).', |
|
771 | - 'event_espresso' |
|
772 | - ), |
|
773 | - '<a href="https://www.timeanddate.com/worldclock/converter.html">', |
|
774 | - '</a>' |
|
775 | - ) |
|
776 | - ) |
|
777 | - ) |
|
778 | - ), |
|
779 | - 'date_range_start_date' => new EE_Datepicker_Input( |
|
780 | - array( |
|
781 | - 'html_name' => 'offset_date_start_range', |
|
782 | - 'html_label_text' => esc_html__( |
|
783 | - 'Start Date for dates the offset applied to:', |
|
784 | - 'event_espresso' |
|
785 | - ) |
|
786 | - ) |
|
787 | - ), |
|
788 | - 'date_range_end_date' => new EE_Datepicker_Input( |
|
789 | - array( |
|
790 | - 'html_name' => 'offset_date_end_range', |
|
791 | - 'html_label_text' => esc_html( |
|
792 | - 'End Date for dates the offset is applied to:', |
|
793 | - 'event_espresso' |
|
794 | - ) |
|
795 | - ) |
|
796 | - ), |
|
797 | - 'submit' => new EE_Submit_Input( |
|
798 | - array( |
|
799 | - 'html_label_text' => '', |
|
800 | - 'default' => esc_html__('Apply Offset', 'event_espresso') |
|
801 | - ) |
|
802 | - ), |
|
803 | - ) |
|
804 | - ) |
|
805 | - ); |
|
806 | - } |
|
807 | - return $this->datetime_fix_offset_form; |
|
808 | - } |
|
809 | - |
|
810 | - |
|
811 | - /** |
|
812 | - * Callback for the run_datetime_offset_fix route. |
|
813 | - * @throws EE_Error |
|
814 | - */ |
|
815 | - protected function _apply_datetime_offset() |
|
816 | - { |
|
817 | - if ($_SERVER['REQUEST_METHOD'] === 'POST') { |
|
818 | - $form = $this->_get_datetime_offset_fix_form(); |
|
819 | - $form->receive_form_submission($this->_req_data); |
|
820 | - if ($form->is_valid()) { |
|
821 | - //save offset data so batch processor can get it. |
|
822 | - DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input')); |
|
823 | - $utc_timezone = new DateTimeZone('UTC'); |
|
824 | - $date_range_start_date = DateTime::createFromFormat( |
|
825 | - 'm/d/Y H:i:s', |
|
826 | - $form->get_input_value('date_range_start_date') . ' 00:00:00', |
|
827 | - $utc_timezone |
|
828 | - ); |
|
829 | - $date_range_end_date = DateTime::createFromFormat( |
|
830 | - 'm/d/Y H:i:s', |
|
831 | - $form->get_input_value('date_range_end_date') . ' 23:59:59', |
|
832 | - $utc_timezone |
|
833 | - ); |
|
834 | - if ($date_range_start_date instanceof DateTime) { |
|
835 | - DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date)); |
|
836 | - } |
|
837 | - if ($date_range_end_date instanceof DateTime) { |
|
838 | - DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date)); |
|
839 | - } |
|
840 | - //redirect to batch tool |
|
841 | - wp_redirect( |
|
842 | - EE_Admin_Page::add_query_args_and_nonce( |
|
843 | - array( |
|
844 | - 'page' => 'espresso_batch', |
|
845 | - 'batch' => 'job', |
|
846 | - 'label' => esc_html__('Applying Offset', 'event_espresso'), |
|
847 | - 'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'), |
|
848 | - 'return_url' => urlencode( |
|
849 | - add_query_arg( |
|
850 | - array( |
|
851 | - 'action' => 'datetime_tools', |
|
852 | - ), |
|
853 | - EEH_URL::current_url_without_query_paramaters( |
|
854 | - array( |
|
855 | - 'return_action', |
|
856 | - 'run_datetime_offset_fix_nonce', |
|
857 | - 'return', |
|
858 | - 'datetime_tools_nonce' |
|
859 | - ) |
|
860 | - ) |
|
861 | - ) |
|
862 | - ) |
|
863 | - ), |
|
864 | - admin_url() |
|
865 | - ) |
|
866 | - ); |
|
867 | - exit; |
|
868 | - } |
|
869 | - } |
|
870 | - } |
|
688 | + } |
|
689 | + |
|
690 | + |
|
691 | + /** |
|
692 | + * Enqueue scripts and styles for the datetime tools page. |
|
693 | + */ |
|
694 | + public function load_scripts_styles_datetime_tools() |
|
695 | + { |
|
696 | + EE_Datepicker_Input::enqueue_styles_and_scripts(); |
|
697 | + } |
|
698 | + |
|
699 | + |
|
700 | + protected function _datetime_tools() |
|
701 | + { |
|
702 | + $form_action = EE_Admin_Page::add_query_args_and_nonce( |
|
703 | + array( |
|
704 | + 'action' => 'run_datetime_offset_fix', |
|
705 | + 'return_action' => $this->_req_action |
|
706 | + ), |
|
707 | + EE_MAINTENANCE_ADMIN_URL |
|
708 | + ); |
|
709 | + $form = $this->_get_datetime_offset_fix_form(); |
|
710 | + $this->_admin_page_title = esc_html__('Datetime Utilities', 'event_espresso'); |
|
711 | + $this->_template_args['admin_page_content'] = $form->form_open($form_action, 'post') |
|
712 | + . $form->get_html_and_js() |
|
713 | + . $form->form_close(); |
|
714 | + $this->display_admin_page_with_no_sidebar(); |
|
715 | + } |
|
716 | + |
|
717 | + |
|
718 | + |
|
719 | + protected function _get_datetime_offset_fix_form() |
|
720 | + { |
|
721 | + if (! $this->datetime_fix_offset_form instanceof EE_Form_Section_Proper) { |
|
722 | + $this->datetime_fix_offset_form = new EE_Form_Section_Proper( |
|
723 | + array( |
|
724 | + 'name' => 'datetime_offset_fix_option', |
|
725 | + 'layout_strategy' => new EE_Admin_Two_Column_Layout(), |
|
726 | + 'subsections' => array( |
|
727 | + 'title' => new EE_Form_Section_HTML( |
|
728 | + EEH_HTML::h2( |
|
729 | + esc_html__('Datetime Offset Tool', 'event_espresso') |
|
730 | + ) |
|
731 | + ), |
|
732 | + 'explanation' => new EE_Form_Section_HTML( |
|
733 | + EEH_HTML::p( |
|
734 | + esc_html__( |
|
735 | + 'Use this tool to automatically apply the provided offset to all Event Espresso records in your database that involve dates and times.', |
|
736 | + 'event_espresso' |
|
737 | + ) |
|
738 | + ) |
|
739 | + . EEH_HTML::p( |
|
740 | + esc_html__( |
|
741 | + 'Note: If you enter 1.25, that will result in the offset of 1 hour 15 minutes being applied. Decimals represent the fraction of hours, not minutes.', |
|
742 | + 'event_espresso' |
|
743 | + ) |
|
744 | + ) |
|
745 | + ), |
|
746 | + 'offset_input' => new EE_Float_Input( |
|
747 | + array( |
|
748 | + 'html_name' => 'offset_for_datetimes', |
|
749 | + 'html_label_text' => esc_html__( |
|
750 | + 'Offset to apply (in hours):', |
|
751 | + 'event_espresso' |
|
752 | + ), |
|
753 | + 'min_value' => '-12', |
|
754 | + 'max_value' => '14', |
|
755 | + 'step_value' => '.25', |
|
756 | + 'default' => DatetimeOffsetFix::getOffset() |
|
757 | + ) |
|
758 | + ), |
|
759 | + 'date_range_explanation' => new EE_Form_Section_HTML( |
|
760 | + EEH_HTML::p( |
|
761 | + esc_html__( |
|
762 | + 'Leave the following fields blank if you want the offset to be applied to all dates. If however, you want to just apply the offset to a specific range of dates you can restrict the offset application using these fields.', |
|
763 | + 'event_espresso' |
|
764 | + ) |
|
765 | + ) |
|
766 | + . EEH_HTML::p( |
|
767 | + EEH_HTML::strong( |
|
768 | + sprintf( |
|
769 | + esc_html__( |
|
770 | + 'Note: please enter the dates in UTC (You can use %1$sthis online tool%2$s to assist with conversions).', |
|
771 | + 'event_espresso' |
|
772 | + ), |
|
773 | + '<a href="https://www.timeanddate.com/worldclock/converter.html">', |
|
774 | + '</a>' |
|
775 | + ) |
|
776 | + ) |
|
777 | + ) |
|
778 | + ), |
|
779 | + 'date_range_start_date' => new EE_Datepicker_Input( |
|
780 | + array( |
|
781 | + 'html_name' => 'offset_date_start_range', |
|
782 | + 'html_label_text' => esc_html__( |
|
783 | + 'Start Date for dates the offset applied to:', |
|
784 | + 'event_espresso' |
|
785 | + ) |
|
786 | + ) |
|
787 | + ), |
|
788 | + 'date_range_end_date' => new EE_Datepicker_Input( |
|
789 | + array( |
|
790 | + 'html_name' => 'offset_date_end_range', |
|
791 | + 'html_label_text' => esc_html( |
|
792 | + 'End Date for dates the offset is applied to:', |
|
793 | + 'event_espresso' |
|
794 | + ) |
|
795 | + ) |
|
796 | + ), |
|
797 | + 'submit' => new EE_Submit_Input( |
|
798 | + array( |
|
799 | + 'html_label_text' => '', |
|
800 | + 'default' => esc_html__('Apply Offset', 'event_espresso') |
|
801 | + ) |
|
802 | + ), |
|
803 | + ) |
|
804 | + ) |
|
805 | + ); |
|
806 | + } |
|
807 | + return $this->datetime_fix_offset_form; |
|
808 | + } |
|
809 | + |
|
810 | + |
|
811 | + /** |
|
812 | + * Callback for the run_datetime_offset_fix route. |
|
813 | + * @throws EE_Error |
|
814 | + */ |
|
815 | + protected function _apply_datetime_offset() |
|
816 | + { |
|
817 | + if ($_SERVER['REQUEST_METHOD'] === 'POST') { |
|
818 | + $form = $this->_get_datetime_offset_fix_form(); |
|
819 | + $form->receive_form_submission($this->_req_data); |
|
820 | + if ($form->is_valid()) { |
|
821 | + //save offset data so batch processor can get it. |
|
822 | + DatetimeOffsetFix::updateOffset($form->get_input_value('offset_input')); |
|
823 | + $utc_timezone = new DateTimeZone('UTC'); |
|
824 | + $date_range_start_date = DateTime::createFromFormat( |
|
825 | + 'm/d/Y H:i:s', |
|
826 | + $form->get_input_value('date_range_start_date') . ' 00:00:00', |
|
827 | + $utc_timezone |
|
828 | + ); |
|
829 | + $date_range_end_date = DateTime::createFromFormat( |
|
830 | + 'm/d/Y H:i:s', |
|
831 | + $form->get_input_value('date_range_end_date') . ' 23:59:59', |
|
832 | + $utc_timezone |
|
833 | + ); |
|
834 | + if ($date_range_start_date instanceof DateTime) { |
|
835 | + DatetimeOffsetFix::updateStartDateRange(DbSafeDateTime::createFromDateTime($date_range_start_date)); |
|
836 | + } |
|
837 | + if ($date_range_end_date instanceof DateTime) { |
|
838 | + DatetimeOffsetFix::updateEndDateRange(DbSafeDateTime::createFromDateTime($date_range_end_date)); |
|
839 | + } |
|
840 | + //redirect to batch tool |
|
841 | + wp_redirect( |
|
842 | + EE_Admin_Page::add_query_args_and_nonce( |
|
843 | + array( |
|
844 | + 'page' => 'espresso_batch', |
|
845 | + 'batch' => 'job', |
|
846 | + 'label' => esc_html__('Applying Offset', 'event_espresso'), |
|
847 | + 'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\DatetimeOffsetFix'), |
|
848 | + 'return_url' => urlencode( |
|
849 | + add_query_arg( |
|
850 | + array( |
|
851 | + 'action' => 'datetime_tools', |
|
852 | + ), |
|
853 | + EEH_URL::current_url_without_query_paramaters( |
|
854 | + array( |
|
855 | + 'return_action', |
|
856 | + 'run_datetime_offset_fix_nonce', |
|
857 | + 'return', |
|
858 | + 'datetime_tools_nonce' |
|
859 | + ) |
|
860 | + ) |
|
861 | + ) |
|
862 | + ) |
|
863 | + ), |
|
864 | + admin_url() |
|
865 | + ) |
|
866 | + ); |
|
867 | + exit; |
|
868 | + } |
|
869 | + } |
|
870 | + } |
|
871 | 871 | } //end Maintenance_Admin_Page class |
@@ -22,454 +22,454 @@ discard block |
||
22 | 22 | final class EE_Admin implements InterminableInterface |
23 | 23 | { |
24 | 24 | |
25 | - /** |
|
26 | - * @var EE_Admin $_instance |
|
27 | - */ |
|
28 | - private static $_instance; |
|
29 | - |
|
30 | - /** |
|
31 | - * @var PersistentAdminNoticeManager $persistent_admin_notice_manager |
|
32 | - */ |
|
33 | - private $persistent_admin_notice_manager; |
|
34 | - |
|
35 | - /** |
|
36 | - * @singleton method used to instantiate class object |
|
37 | - * @return EE_Admin |
|
38 | - * @throws EE_Error |
|
39 | - */ |
|
40 | - public static function instance() |
|
41 | - { |
|
42 | - // check if class object is instantiated |
|
43 | - if (! self::$_instance instanceof EE_Admin) { |
|
44 | - self::$_instance = new self(); |
|
45 | - } |
|
46 | - return self::$_instance; |
|
47 | - } |
|
48 | - |
|
49 | - |
|
50 | - /** |
|
51 | - * @return EE_Admin |
|
52 | - * @throws EE_Error |
|
53 | - */ |
|
54 | - public static function reset() |
|
55 | - { |
|
56 | - self::$_instance = null; |
|
57 | - return self::instance(); |
|
58 | - } |
|
59 | - |
|
60 | - |
|
61 | - /** |
|
62 | - * class constructor |
|
63 | - * |
|
64 | - * @throws EE_Error |
|
65 | - * @throws InvalidDataTypeException |
|
66 | - * @throws InvalidInterfaceException |
|
67 | - * @throws InvalidArgumentException |
|
68 | - */ |
|
69 | - protected function __construct() |
|
70 | - { |
|
71 | - // define global EE_Admin constants |
|
72 | - $this->_define_all_constants(); |
|
73 | - // set autoloaders for our admin page classes based on included path information |
|
74 | - EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN); |
|
75 | - // admin hooks |
|
76 | - add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2); |
|
77 | - // load EE_Request_Handler early |
|
78 | - add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request')); |
|
79 | - add_action('AHEE__EE_System__initialize_last', array($this, 'init')); |
|
80 | - add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2); |
|
81 | - add_action('wp_loaded', array($this, 'wp_loaded'), 100); |
|
82 | - add_action('admin_init', array($this, 'admin_init'), 100); |
|
83 | - add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20); |
|
84 | - add_action('admin_notices', array($this, 'display_admin_notices'), 10); |
|
85 | - add_action('network_admin_notices', array($this, 'display_admin_notices'), 10); |
|
86 | - add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2); |
|
87 | - add_filter('admin_footer_text', array($this, 'espresso_admin_footer')); |
|
88 | - //reset Environment config (we only do this on admin page loads); |
|
89 | - EE_Registry::instance()->CFG->environment->recheck_values(); |
|
90 | - do_action('AHEE__EE_Admin__loaded'); |
|
91 | - } |
|
92 | - |
|
93 | - |
|
94 | - |
|
95 | - /** |
|
96 | - * _define_all_constants |
|
97 | - * define constants that are set globally for all admin pages |
|
98 | - * |
|
99 | - * @return void |
|
100 | - */ |
|
101 | - private function _define_all_constants() |
|
102 | - { |
|
103 | - if (! defined('EE_ADMIN_URL')) { |
|
104 | - define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/'); |
|
105 | - define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/'); |
|
106 | - define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS); |
|
107 | - define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/'); |
|
108 | - define('WP_AJAX_URL', admin_url('admin-ajax.php')); |
|
109 | - } |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * filter_plugin_actions - adds links to the Plugins page listing |
|
115 | - * |
|
116 | - * @param array $links |
|
117 | - * @param string $plugin |
|
118 | - * @return array |
|
119 | - */ |
|
120 | - public function filter_plugin_actions($links, $plugin) |
|
121 | - { |
|
122 | - // set $main_file in stone |
|
123 | - static $main_file; |
|
124 | - // if $main_file is not set yet |
|
125 | - if (! $main_file) { |
|
126 | - $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE); |
|
127 | - } |
|
128 | - if ($plugin === $main_file) { |
|
129 | - // compare current plugin to this one |
|
130 | - if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) { |
|
131 | - $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"' |
|
132 | - . ' title="Event Espresso is in maintenance mode. Click this link to learn why.">' |
|
133 | - . esc_html__('Maintenance Mode Active', 'event_espresso') |
|
134 | - . '</a>'; |
|
135 | - array_unshift($links, $maintenance_link); |
|
136 | - } else { |
|
137 | - $org_settings_link = '<a href="admin.php?page=espresso_general_settings">' |
|
138 | - . esc_html__('Settings', 'event_espresso') |
|
139 | - . '</a>'; |
|
140 | - $events_link = '<a href="admin.php?page=espresso_events">' |
|
141 | - . esc_html__('Events', 'event_espresso') |
|
142 | - . '</a>'; |
|
143 | - // add before other links |
|
144 | - array_unshift($links, $org_settings_link, $events_link); |
|
145 | - } |
|
146 | - } |
|
147 | - return $links; |
|
148 | - } |
|
149 | - |
|
150 | - |
|
151 | - /** |
|
152 | - * _get_request |
|
153 | - * |
|
154 | - * @return void |
|
155 | - * @throws EE_Error |
|
156 | - * @throws InvalidArgumentException |
|
157 | - * @throws InvalidDataTypeException |
|
158 | - * @throws InvalidInterfaceException |
|
159 | - * @throws ReflectionException |
|
160 | - */ |
|
161 | - public function get_request() |
|
162 | - { |
|
163 | - EE_Registry::instance()->load_core('Request_Handler'); |
|
164 | - EE_Registry::instance()->load_core('CPT_Strategy'); |
|
165 | - } |
|
166 | - |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * hide_admin_pages_except_maintenance_mode |
|
171 | - * |
|
172 | - * @param array $admin_page_folder_names |
|
173 | - * @return array |
|
174 | - */ |
|
175 | - public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array()) |
|
176 | - { |
|
177 | - return array( |
|
178 | - 'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS, |
|
179 | - 'about' => EE_ADMIN_PAGES . 'about' . DS, |
|
180 | - 'support' => EE_ADMIN_PAGES . 'support' . DS, |
|
181 | - ); |
|
182 | - } |
|
183 | - |
|
184 | - |
|
185 | - |
|
186 | - /** |
|
187 | - * init- should fire after shortcode, module, addon, other plugin (default priority), and even |
|
188 | - * EE_Front_Controller's init phases have run |
|
189 | - * |
|
190 | - * @return void |
|
191 | - * @throws EE_Error |
|
192 | - * @throws InvalidArgumentException |
|
193 | - * @throws InvalidDataTypeException |
|
194 | - * @throws InvalidInterfaceException |
|
195 | - * @throws ReflectionException |
|
196 | - * @throws ServiceNotFoundException |
|
197 | - */ |
|
198 | - public function init() |
|
199 | - { |
|
200 | - //only enable most of the EE_Admin IF we're not in full maintenance mode |
|
201 | - if (EE_Maintenance_Mode::instance()->models_can_query()) { |
|
202 | - //ok so we want to enable the entire admin |
|
203 | - $this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared( |
|
204 | - 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager', |
|
205 | - array( |
|
206 | - EE_Admin_Page::add_query_args_and_nonce( |
|
207 | - array( |
|
208 | - 'page' => EE_Registry::instance()->REQ->get('page', ''), |
|
209 | - 'action' => EE_Registry::instance()->REQ->get('action', ''), |
|
210 | - ), |
|
211 | - EE_ADMIN_URL |
|
212 | - ), |
|
213 | - ) |
|
214 | - ); |
|
215 | - $this->maybeSetDatetimeWarningNotice(); |
|
216 | - //at a glance dashboard widget |
|
217 | - add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10); |
|
218 | - //filter for get_edit_post_link used on comments for custom post types |
|
219 | - add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2); |
|
220 | - } |
|
221 | - // run the admin page factory but ONLY if we are doing an ee admin ajax request |
|
222 | - if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) { |
|
223 | - try { |
|
224 | - //this loads the controller for the admin pages which will setup routing etc |
|
225 | - EE_Registry::instance()->load_core('Admin_Page_Loader'); |
|
226 | - } catch (EE_Error $e) { |
|
227 | - $e->get_error(); |
|
228 | - } |
|
229 | - } |
|
230 | - add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1); |
|
231 | - //make sure our CPTs and custom taxonomy metaboxes get shown for first time users |
|
232 | - add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10); |
|
233 | - add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10); |
|
234 | - //exclude EE critical pages from all nav menus and wp_list_pages |
|
235 | - add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10); |
|
236 | - } |
|
237 | - |
|
238 | - |
|
239 | - /** |
|
240 | - * get_persistent_admin_notices |
|
241 | - * |
|
242 | - * @access public |
|
243 | - * @return void |
|
244 | - * @throws EE_Error |
|
245 | - * @throws InvalidArgumentException |
|
246 | - * @throws InvalidDataTypeException |
|
247 | - * @throws InvalidInterfaceException |
|
248 | - */ |
|
249 | - public function maybeSetDatetimeWarningNotice() |
|
250 | - { |
|
251 | - //add dismissable notice for datetime changes. Only valid if site does not have a timezone_string set. |
|
252 | - //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version |
|
253 | - //with this. But after enough time (indeterminate at this point) we can just remove this notice. |
|
254 | - //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626 |
|
255 | - if (! get_option('timezone_string') && EEM_Event::instance()->count() > 0) { |
|
256 | - new PersistentAdminNotice( |
|
257 | - 'datetime_fix_notice', |
|
258 | - sprintf( |
|
259 | - esc_html__( |
|
260 | - '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times. Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.', |
|
261 | - 'event_espresso' |
|
262 | - ), |
|
263 | - '<strong>', |
|
264 | - '</strong>', |
|
265 | - '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">', |
|
266 | - '</a>', |
|
267 | - '<a href="' . EE_Admin_Page::add_query_args_and_nonce( |
|
268 | - array( |
|
269 | - 'page' => 'espresso_maintenance_settings', |
|
270 | - 'action' => 'datetime_tools' |
|
271 | - ), |
|
272 | - admin_url('admin.php') |
|
273 | - ) . '">' |
|
274 | - ), |
|
275 | - false, |
|
276 | - 'manage_options', |
|
277 | - 'datetime_fix_persistent_notice' |
|
278 | - ); |
|
279 | - } |
|
280 | - } |
|
281 | - |
|
282 | - |
|
283 | - |
|
284 | - /** |
|
285 | - * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from |
|
286 | - * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in |
|
287 | - * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that |
|
288 | - * to override any queries found in the existing query for the given post type. Note that _default_query is not a |
|
289 | - * normal property on the post_type object. It's found ONLY in this particular context. |
|
290 | - * |
|
291 | - * @param WP_Post $post_type WP post type object |
|
292 | - * @return WP_Post |
|
293 | - * @throws InvalidArgumentException |
|
294 | - * @throws InvalidDataTypeException |
|
295 | - * @throws InvalidInterfaceException |
|
296 | - */ |
|
297 | - public function remove_pages_from_nav_menu($post_type) |
|
298 | - { |
|
299 | - //if this isn't the "pages" post type let's get out |
|
300 | - if ($post_type->name !== 'page') { |
|
301 | - return $post_type; |
|
302 | - } |
|
303 | - $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array(); |
|
304 | - $post_type->_default_query = array( |
|
305 | - 'post__not_in' => $critical_pages, |
|
306 | - ); |
|
307 | - return $post_type; |
|
308 | - } |
|
309 | - |
|
310 | - |
|
311 | - |
|
312 | - /** |
|
313 | - * WP by default only shows three metaboxes in "nav-menus.php" for first times users. We want to make sure our |
|
314 | - * metaboxes get shown as well |
|
315 | - * |
|
316 | - * @return void |
|
317 | - */ |
|
318 | - public function enable_hidden_ee_nav_menu_metaboxes() |
|
319 | - { |
|
320 | - global $wp_meta_boxes, $pagenow; |
|
321 | - if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') { |
|
322 | - return; |
|
323 | - } |
|
324 | - $user = wp_get_current_user(); |
|
325 | - //has this been done yet? |
|
326 | - if (get_user_option('ee_nav_menu_initialized', $user->ID)) { |
|
327 | - return; |
|
328 | - } |
|
329 | - |
|
330 | - $hidden_meta_boxes = get_user_option('metaboxhidden_nav-menus', $user->ID); |
|
331 | - $initial_meta_boxes = apply_filters( |
|
332 | - 'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes', |
|
333 | - array( |
|
334 | - 'nav-menu-theme-locations', |
|
335 | - 'add-page', |
|
336 | - 'add-custom-links', |
|
337 | - 'add-category', |
|
338 | - 'add-espresso_events', |
|
339 | - 'add-espresso_venues', |
|
340 | - 'add-espresso_event_categories', |
|
341 | - 'add-espresso_venue_categories', |
|
342 | - 'add-post-type-post', |
|
343 | - 'add-post-type-page', |
|
344 | - ) |
|
345 | - ); |
|
346 | - |
|
347 | - if (is_array($hidden_meta_boxes)) { |
|
348 | - foreach ($hidden_meta_boxes as $key => $meta_box_id) { |
|
349 | - if (in_array($meta_box_id, $initial_meta_boxes, true)) { |
|
350 | - unset($hidden_meta_boxes[$key]); |
|
351 | - } |
|
352 | - } |
|
353 | - } |
|
354 | - update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true); |
|
355 | - update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true); |
|
356 | - } |
|
357 | - |
|
358 | - |
|
359 | - |
|
360 | - /** |
|
361 | - * This method simply registers custom nav menu boxes for "nav_menus.php route" |
|
362 | - * Currently EE is using this to make sure there are menu options for our CPT archive page routes. |
|
363 | - * |
|
364 | - * @todo modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by |
|
365 | - * addons etc. |
|
366 | - * @return void |
|
367 | - */ |
|
368 | - public function register_custom_nav_menu_boxes() |
|
369 | - { |
|
370 | - add_meta_box( |
|
371 | - 'add-extra-nav-menu-pages', |
|
372 | - esc_html__('Event Espresso Pages', 'event_espresso'), |
|
373 | - array($this, 'ee_cpt_archive_pages'), |
|
374 | - 'nav-menus', |
|
375 | - 'side', |
|
376 | - 'core' |
|
377 | - ); |
|
378 | - } |
|
379 | - |
|
380 | - |
|
381 | - |
|
382 | - /** |
|
383 | - * Use this to edit the post link for our cpts so that the edit link points to the correct page. |
|
384 | - * |
|
385 | - * @since 4.3.0 |
|
386 | - * @param string $link the original link generated by wp |
|
387 | - * @param int $id post id |
|
388 | - * @return string the (maybe) modified link |
|
389 | - */ |
|
390 | - public function modify_edit_post_link($link, $id) |
|
391 | - { |
|
392 | - if (! $post = get_post($id)) { |
|
393 | - return $link; |
|
394 | - } |
|
395 | - if ($post->post_type === 'espresso_attendees') { |
|
396 | - $query_args = array( |
|
397 | - 'action' => 'edit_attendee', |
|
398 | - 'post' => $id, |
|
399 | - ); |
|
400 | - return EEH_URL::add_query_args_and_nonce( |
|
401 | - $query_args, |
|
402 | - admin_url('admin.php?page=espresso_registrations') |
|
403 | - ); |
|
404 | - } |
|
405 | - return $link; |
|
406 | - } |
|
407 | - |
|
408 | - |
|
409 | - |
|
410 | - public function ee_cpt_archive_pages() |
|
411 | - { |
|
412 | - global $nav_menu_selected_id; |
|
413 | - $db_fields = false; |
|
414 | - $walker = new Walker_Nav_Menu_Checklist($db_fields); |
|
415 | - $current_tab = 'event-archives'; |
|
416 | - $removed_args = array( |
|
417 | - 'action', |
|
418 | - 'customlink-tab', |
|
419 | - 'edit-menu-item', |
|
420 | - 'menu-item', |
|
421 | - 'page-tab', |
|
422 | - '_wpnonce', |
|
423 | - ); |
|
424 | - ?> |
|
25 | + /** |
|
26 | + * @var EE_Admin $_instance |
|
27 | + */ |
|
28 | + private static $_instance; |
|
29 | + |
|
30 | + /** |
|
31 | + * @var PersistentAdminNoticeManager $persistent_admin_notice_manager |
|
32 | + */ |
|
33 | + private $persistent_admin_notice_manager; |
|
34 | + |
|
35 | + /** |
|
36 | + * @singleton method used to instantiate class object |
|
37 | + * @return EE_Admin |
|
38 | + * @throws EE_Error |
|
39 | + */ |
|
40 | + public static function instance() |
|
41 | + { |
|
42 | + // check if class object is instantiated |
|
43 | + if (! self::$_instance instanceof EE_Admin) { |
|
44 | + self::$_instance = new self(); |
|
45 | + } |
|
46 | + return self::$_instance; |
|
47 | + } |
|
48 | + |
|
49 | + |
|
50 | + /** |
|
51 | + * @return EE_Admin |
|
52 | + * @throws EE_Error |
|
53 | + */ |
|
54 | + public static function reset() |
|
55 | + { |
|
56 | + self::$_instance = null; |
|
57 | + return self::instance(); |
|
58 | + } |
|
59 | + |
|
60 | + |
|
61 | + /** |
|
62 | + * class constructor |
|
63 | + * |
|
64 | + * @throws EE_Error |
|
65 | + * @throws InvalidDataTypeException |
|
66 | + * @throws InvalidInterfaceException |
|
67 | + * @throws InvalidArgumentException |
|
68 | + */ |
|
69 | + protected function __construct() |
|
70 | + { |
|
71 | + // define global EE_Admin constants |
|
72 | + $this->_define_all_constants(); |
|
73 | + // set autoloaders for our admin page classes based on included path information |
|
74 | + EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN); |
|
75 | + // admin hooks |
|
76 | + add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2); |
|
77 | + // load EE_Request_Handler early |
|
78 | + add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request')); |
|
79 | + add_action('AHEE__EE_System__initialize_last', array($this, 'init')); |
|
80 | + add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2); |
|
81 | + add_action('wp_loaded', array($this, 'wp_loaded'), 100); |
|
82 | + add_action('admin_init', array($this, 'admin_init'), 100); |
|
83 | + add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20); |
|
84 | + add_action('admin_notices', array($this, 'display_admin_notices'), 10); |
|
85 | + add_action('network_admin_notices', array($this, 'display_admin_notices'), 10); |
|
86 | + add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2); |
|
87 | + add_filter('admin_footer_text', array($this, 'espresso_admin_footer')); |
|
88 | + //reset Environment config (we only do this on admin page loads); |
|
89 | + EE_Registry::instance()->CFG->environment->recheck_values(); |
|
90 | + do_action('AHEE__EE_Admin__loaded'); |
|
91 | + } |
|
92 | + |
|
93 | + |
|
94 | + |
|
95 | + /** |
|
96 | + * _define_all_constants |
|
97 | + * define constants that are set globally for all admin pages |
|
98 | + * |
|
99 | + * @return void |
|
100 | + */ |
|
101 | + private function _define_all_constants() |
|
102 | + { |
|
103 | + if (! defined('EE_ADMIN_URL')) { |
|
104 | + define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/'); |
|
105 | + define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/'); |
|
106 | + define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS); |
|
107 | + define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/'); |
|
108 | + define('WP_AJAX_URL', admin_url('admin-ajax.php')); |
|
109 | + } |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * filter_plugin_actions - adds links to the Plugins page listing |
|
115 | + * |
|
116 | + * @param array $links |
|
117 | + * @param string $plugin |
|
118 | + * @return array |
|
119 | + */ |
|
120 | + public function filter_plugin_actions($links, $plugin) |
|
121 | + { |
|
122 | + // set $main_file in stone |
|
123 | + static $main_file; |
|
124 | + // if $main_file is not set yet |
|
125 | + if (! $main_file) { |
|
126 | + $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE); |
|
127 | + } |
|
128 | + if ($plugin === $main_file) { |
|
129 | + // compare current plugin to this one |
|
130 | + if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) { |
|
131 | + $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"' |
|
132 | + . ' title="Event Espresso is in maintenance mode. Click this link to learn why.">' |
|
133 | + . esc_html__('Maintenance Mode Active', 'event_espresso') |
|
134 | + . '</a>'; |
|
135 | + array_unshift($links, $maintenance_link); |
|
136 | + } else { |
|
137 | + $org_settings_link = '<a href="admin.php?page=espresso_general_settings">' |
|
138 | + . esc_html__('Settings', 'event_espresso') |
|
139 | + . '</a>'; |
|
140 | + $events_link = '<a href="admin.php?page=espresso_events">' |
|
141 | + . esc_html__('Events', 'event_espresso') |
|
142 | + . '</a>'; |
|
143 | + // add before other links |
|
144 | + array_unshift($links, $org_settings_link, $events_link); |
|
145 | + } |
|
146 | + } |
|
147 | + return $links; |
|
148 | + } |
|
149 | + |
|
150 | + |
|
151 | + /** |
|
152 | + * _get_request |
|
153 | + * |
|
154 | + * @return void |
|
155 | + * @throws EE_Error |
|
156 | + * @throws InvalidArgumentException |
|
157 | + * @throws InvalidDataTypeException |
|
158 | + * @throws InvalidInterfaceException |
|
159 | + * @throws ReflectionException |
|
160 | + */ |
|
161 | + public function get_request() |
|
162 | + { |
|
163 | + EE_Registry::instance()->load_core('Request_Handler'); |
|
164 | + EE_Registry::instance()->load_core('CPT_Strategy'); |
|
165 | + } |
|
166 | + |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * hide_admin_pages_except_maintenance_mode |
|
171 | + * |
|
172 | + * @param array $admin_page_folder_names |
|
173 | + * @return array |
|
174 | + */ |
|
175 | + public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array()) |
|
176 | + { |
|
177 | + return array( |
|
178 | + 'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS, |
|
179 | + 'about' => EE_ADMIN_PAGES . 'about' . DS, |
|
180 | + 'support' => EE_ADMIN_PAGES . 'support' . DS, |
|
181 | + ); |
|
182 | + } |
|
183 | + |
|
184 | + |
|
185 | + |
|
186 | + /** |
|
187 | + * init- should fire after shortcode, module, addon, other plugin (default priority), and even |
|
188 | + * EE_Front_Controller's init phases have run |
|
189 | + * |
|
190 | + * @return void |
|
191 | + * @throws EE_Error |
|
192 | + * @throws InvalidArgumentException |
|
193 | + * @throws InvalidDataTypeException |
|
194 | + * @throws InvalidInterfaceException |
|
195 | + * @throws ReflectionException |
|
196 | + * @throws ServiceNotFoundException |
|
197 | + */ |
|
198 | + public function init() |
|
199 | + { |
|
200 | + //only enable most of the EE_Admin IF we're not in full maintenance mode |
|
201 | + if (EE_Maintenance_Mode::instance()->models_can_query()) { |
|
202 | + //ok so we want to enable the entire admin |
|
203 | + $this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared( |
|
204 | + 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager', |
|
205 | + array( |
|
206 | + EE_Admin_Page::add_query_args_and_nonce( |
|
207 | + array( |
|
208 | + 'page' => EE_Registry::instance()->REQ->get('page', ''), |
|
209 | + 'action' => EE_Registry::instance()->REQ->get('action', ''), |
|
210 | + ), |
|
211 | + EE_ADMIN_URL |
|
212 | + ), |
|
213 | + ) |
|
214 | + ); |
|
215 | + $this->maybeSetDatetimeWarningNotice(); |
|
216 | + //at a glance dashboard widget |
|
217 | + add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10); |
|
218 | + //filter for get_edit_post_link used on comments for custom post types |
|
219 | + add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2); |
|
220 | + } |
|
221 | + // run the admin page factory but ONLY if we are doing an ee admin ajax request |
|
222 | + if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) { |
|
223 | + try { |
|
224 | + //this loads the controller for the admin pages which will setup routing etc |
|
225 | + EE_Registry::instance()->load_core('Admin_Page_Loader'); |
|
226 | + } catch (EE_Error $e) { |
|
227 | + $e->get_error(); |
|
228 | + } |
|
229 | + } |
|
230 | + add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1); |
|
231 | + //make sure our CPTs and custom taxonomy metaboxes get shown for first time users |
|
232 | + add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10); |
|
233 | + add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10); |
|
234 | + //exclude EE critical pages from all nav menus and wp_list_pages |
|
235 | + add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10); |
|
236 | + } |
|
237 | + |
|
238 | + |
|
239 | + /** |
|
240 | + * get_persistent_admin_notices |
|
241 | + * |
|
242 | + * @access public |
|
243 | + * @return void |
|
244 | + * @throws EE_Error |
|
245 | + * @throws InvalidArgumentException |
|
246 | + * @throws InvalidDataTypeException |
|
247 | + * @throws InvalidInterfaceException |
|
248 | + */ |
|
249 | + public function maybeSetDatetimeWarningNotice() |
|
250 | + { |
|
251 | + //add dismissable notice for datetime changes. Only valid if site does not have a timezone_string set. |
|
252 | + //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version |
|
253 | + //with this. But after enough time (indeterminate at this point) we can just remove this notice. |
|
254 | + //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626 |
|
255 | + if (! get_option('timezone_string') && EEM_Event::instance()->count() > 0) { |
|
256 | + new PersistentAdminNotice( |
|
257 | + 'datetime_fix_notice', |
|
258 | + sprintf( |
|
259 | + esc_html__( |
|
260 | + '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times. Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.', |
|
261 | + 'event_espresso' |
|
262 | + ), |
|
263 | + '<strong>', |
|
264 | + '</strong>', |
|
265 | + '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">', |
|
266 | + '</a>', |
|
267 | + '<a href="' . EE_Admin_Page::add_query_args_and_nonce( |
|
268 | + array( |
|
269 | + 'page' => 'espresso_maintenance_settings', |
|
270 | + 'action' => 'datetime_tools' |
|
271 | + ), |
|
272 | + admin_url('admin.php') |
|
273 | + ) . '">' |
|
274 | + ), |
|
275 | + false, |
|
276 | + 'manage_options', |
|
277 | + 'datetime_fix_persistent_notice' |
|
278 | + ); |
|
279 | + } |
|
280 | + } |
|
281 | + |
|
282 | + |
|
283 | + |
|
284 | + /** |
|
285 | + * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from |
|
286 | + * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in |
|
287 | + * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that |
|
288 | + * to override any queries found in the existing query for the given post type. Note that _default_query is not a |
|
289 | + * normal property on the post_type object. It's found ONLY in this particular context. |
|
290 | + * |
|
291 | + * @param WP_Post $post_type WP post type object |
|
292 | + * @return WP_Post |
|
293 | + * @throws InvalidArgumentException |
|
294 | + * @throws InvalidDataTypeException |
|
295 | + * @throws InvalidInterfaceException |
|
296 | + */ |
|
297 | + public function remove_pages_from_nav_menu($post_type) |
|
298 | + { |
|
299 | + //if this isn't the "pages" post type let's get out |
|
300 | + if ($post_type->name !== 'page') { |
|
301 | + return $post_type; |
|
302 | + } |
|
303 | + $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array(); |
|
304 | + $post_type->_default_query = array( |
|
305 | + 'post__not_in' => $critical_pages, |
|
306 | + ); |
|
307 | + return $post_type; |
|
308 | + } |
|
309 | + |
|
310 | + |
|
311 | + |
|
312 | + /** |
|
313 | + * WP by default only shows three metaboxes in "nav-menus.php" for first times users. We want to make sure our |
|
314 | + * metaboxes get shown as well |
|
315 | + * |
|
316 | + * @return void |
|
317 | + */ |
|
318 | + public function enable_hidden_ee_nav_menu_metaboxes() |
|
319 | + { |
|
320 | + global $wp_meta_boxes, $pagenow; |
|
321 | + if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') { |
|
322 | + return; |
|
323 | + } |
|
324 | + $user = wp_get_current_user(); |
|
325 | + //has this been done yet? |
|
326 | + if (get_user_option('ee_nav_menu_initialized', $user->ID)) { |
|
327 | + return; |
|
328 | + } |
|
329 | + |
|
330 | + $hidden_meta_boxes = get_user_option('metaboxhidden_nav-menus', $user->ID); |
|
331 | + $initial_meta_boxes = apply_filters( |
|
332 | + 'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes', |
|
333 | + array( |
|
334 | + 'nav-menu-theme-locations', |
|
335 | + 'add-page', |
|
336 | + 'add-custom-links', |
|
337 | + 'add-category', |
|
338 | + 'add-espresso_events', |
|
339 | + 'add-espresso_venues', |
|
340 | + 'add-espresso_event_categories', |
|
341 | + 'add-espresso_venue_categories', |
|
342 | + 'add-post-type-post', |
|
343 | + 'add-post-type-page', |
|
344 | + ) |
|
345 | + ); |
|
346 | + |
|
347 | + if (is_array($hidden_meta_boxes)) { |
|
348 | + foreach ($hidden_meta_boxes as $key => $meta_box_id) { |
|
349 | + if (in_array($meta_box_id, $initial_meta_boxes, true)) { |
|
350 | + unset($hidden_meta_boxes[$key]); |
|
351 | + } |
|
352 | + } |
|
353 | + } |
|
354 | + update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true); |
|
355 | + update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true); |
|
356 | + } |
|
357 | + |
|
358 | + |
|
359 | + |
|
360 | + /** |
|
361 | + * This method simply registers custom nav menu boxes for "nav_menus.php route" |
|
362 | + * Currently EE is using this to make sure there are menu options for our CPT archive page routes. |
|
363 | + * |
|
364 | + * @todo modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by |
|
365 | + * addons etc. |
|
366 | + * @return void |
|
367 | + */ |
|
368 | + public function register_custom_nav_menu_boxes() |
|
369 | + { |
|
370 | + add_meta_box( |
|
371 | + 'add-extra-nav-menu-pages', |
|
372 | + esc_html__('Event Espresso Pages', 'event_espresso'), |
|
373 | + array($this, 'ee_cpt_archive_pages'), |
|
374 | + 'nav-menus', |
|
375 | + 'side', |
|
376 | + 'core' |
|
377 | + ); |
|
378 | + } |
|
379 | + |
|
380 | + |
|
381 | + |
|
382 | + /** |
|
383 | + * Use this to edit the post link for our cpts so that the edit link points to the correct page. |
|
384 | + * |
|
385 | + * @since 4.3.0 |
|
386 | + * @param string $link the original link generated by wp |
|
387 | + * @param int $id post id |
|
388 | + * @return string the (maybe) modified link |
|
389 | + */ |
|
390 | + public function modify_edit_post_link($link, $id) |
|
391 | + { |
|
392 | + if (! $post = get_post($id)) { |
|
393 | + return $link; |
|
394 | + } |
|
395 | + if ($post->post_type === 'espresso_attendees') { |
|
396 | + $query_args = array( |
|
397 | + 'action' => 'edit_attendee', |
|
398 | + 'post' => $id, |
|
399 | + ); |
|
400 | + return EEH_URL::add_query_args_and_nonce( |
|
401 | + $query_args, |
|
402 | + admin_url('admin.php?page=espresso_registrations') |
|
403 | + ); |
|
404 | + } |
|
405 | + return $link; |
|
406 | + } |
|
407 | + |
|
408 | + |
|
409 | + |
|
410 | + public function ee_cpt_archive_pages() |
|
411 | + { |
|
412 | + global $nav_menu_selected_id; |
|
413 | + $db_fields = false; |
|
414 | + $walker = new Walker_Nav_Menu_Checklist($db_fields); |
|
415 | + $current_tab = 'event-archives'; |
|
416 | + $removed_args = array( |
|
417 | + 'action', |
|
418 | + 'customlink-tab', |
|
419 | + 'edit-menu-item', |
|
420 | + 'menu-item', |
|
421 | + 'page-tab', |
|
422 | + '_wpnonce', |
|
423 | + ); |
|
424 | + ?> |
|
425 | 425 | <div id="posttype-extra-nav-menu-pages" class="posttypediv"> |
426 | 426 | <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs"> |
427 | 427 | <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>> |
428 | 428 | <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives" |
429 | 429 | href="<?php if ($nav_menu_selected_id) { |
430 | - echo esc_url( |
|
431 | - add_query_arg( |
|
432 | - 'extra-nav-menu-pages-tab', |
|
433 | - 'event-archives', |
|
434 | - remove_query_arg($removed_args) |
|
435 | - ) |
|
436 | - ); |
|
437 | - } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives"> |
|
430 | + echo esc_url( |
|
431 | + add_query_arg( |
|
432 | + 'extra-nav-menu-pages-tab', |
|
433 | + 'event-archives', |
|
434 | + remove_query_arg($removed_args) |
|
435 | + ) |
|
436 | + ); |
|
437 | + } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives"> |
|
438 | 438 | <?php _e('Event Archive Pages', 'event_espresso'); ?> |
439 | 439 | </a> |
440 | 440 | </li> |
441 | 441 | </ul><!-- .posttype-tabs --> |
442 | 442 | |
443 | 443 | <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php |
444 | - echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive'); |
|
445 | - ?>"> |
|
444 | + echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive'); |
|
445 | + ?>"> |
|
446 | 446 | <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear"> |
447 | 447 | <?php |
448 | - $pages = $this->_get_extra_nav_menu_pages_items(); |
|
449 | - $args['walker'] = $walker; |
|
450 | - echo walk_nav_menu_tree( |
|
451 | - array_map( |
|
452 | - array($this, '_setup_extra_nav_menu_pages_items'), |
|
453 | - $pages |
|
454 | - ), |
|
455 | - 0, |
|
456 | - (object) $args |
|
457 | - ); |
|
458 | - ?> |
|
448 | + $pages = $this->_get_extra_nav_menu_pages_items(); |
|
449 | + $args['walker'] = $walker; |
|
450 | + echo walk_nav_menu_tree( |
|
451 | + array_map( |
|
452 | + array($this, '_setup_extra_nav_menu_pages_items'), |
|
453 | + $pages |
|
454 | + ), |
|
455 | + 0, |
|
456 | + (object) $args |
|
457 | + ); |
|
458 | + ?> |
|
459 | 459 | </ul> |
460 | 460 | </div><!-- /.tabs-panel --> |
461 | 461 | |
462 | 462 | <p class="button-controls"> |
463 | 463 | <span class="list-controls"> |
464 | 464 | <a href="<?php |
465 | - echo esc_url(add_query_arg( |
|
466 | - array( |
|
467 | - 'extra-nav-menu-pages-tab' => 'event-archives', |
|
468 | - 'selectall' => 1, |
|
469 | - ), |
|
470 | - remove_query_arg($removed_args) |
|
471 | - )); |
|
472 | - ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a> |
|
465 | + echo esc_url(add_query_arg( |
|
466 | + array( |
|
467 | + 'extra-nav-menu-pages-tab' => 'event-archives', |
|
468 | + 'selectall' => 1, |
|
469 | + ), |
|
470 | + remove_query_arg($removed_args) |
|
471 | + )); |
|
472 | + ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a> |
|
473 | 473 | </span> |
474 | 474 | <span class="add-to-menu"> |
475 | 475 | <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?> |
@@ -482,471 +482,471 @@ discard block |
||
482 | 482 | |
483 | 483 | </div><!-- /.posttypediv --> |
484 | 484 | <?php |
485 | - } |
|
486 | - |
|
487 | - |
|
488 | - /** |
|
489 | - * Returns an array of event archive nav items. |
|
490 | - * |
|
491 | - * @todo for now this method is just in place so when it gets abstracted further we can substitute in whatever |
|
492 | - * method we use for getting the extra nav menu items |
|
493 | - * @return array |
|
494 | - */ |
|
495 | - private function _get_extra_nav_menu_pages_items() |
|
496 | - { |
|
497 | - $menuitems[] = array( |
|
498 | - 'title' => esc_html__('Event List', 'event_espresso'), |
|
499 | - 'url' => get_post_type_archive_link('espresso_events'), |
|
500 | - 'description' => esc_html__('Archive page for all events.', 'event_espresso'), |
|
501 | - ); |
|
502 | - return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems); |
|
503 | - } |
|
504 | - |
|
505 | - |
|
506 | - /** |
|
507 | - * Setup nav menu walker item for usage in the event archive nav menu metabox. It receives a menu_item array with |
|
508 | - * the properties and converts it to the menu item object. |
|
509 | - * |
|
510 | - * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php |
|
511 | - * @param $menu_item_values |
|
512 | - * @return stdClass |
|
513 | - */ |
|
514 | - private function _setup_extra_nav_menu_pages_items($menu_item_values) |
|
515 | - { |
|
516 | - $menu_item = new stdClass(); |
|
517 | - $keys = array( |
|
518 | - 'ID' => 0, |
|
519 | - 'db_id' => 0, |
|
520 | - 'menu_item_parent' => 0, |
|
521 | - 'object_id' => -1, |
|
522 | - 'post_parent' => 0, |
|
523 | - 'type' => 'custom', |
|
524 | - 'object' => '', |
|
525 | - 'type_label' => esc_html__('Extra Nav Menu Item', 'event_espresso'), |
|
526 | - 'title' => '', |
|
527 | - 'url' => '', |
|
528 | - 'target' => '', |
|
529 | - 'attr_title' => '', |
|
530 | - 'description' => '', |
|
531 | - 'classes' => array(), |
|
532 | - 'xfn' => '', |
|
533 | - ); |
|
534 | - |
|
535 | - foreach ($keys as $key => $value) { |
|
536 | - $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value; |
|
537 | - } |
|
538 | - return $menu_item; |
|
539 | - } |
|
540 | - |
|
541 | - |
|
542 | - /** |
|
543 | - * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an |
|
544 | - * EE_Admin_Page route is called. |
|
545 | - * |
|
546 | - * @return void |
|
547 | - */ |
|
548 | - public function route_admin_request() |
|
549 | - { |
|
550 | - } |
|
551 | - |
|
552 | - |
|
553 | - /** |
|
554 | - * wp_loaded should fire on the WordPress wp_loaded hook. This fires on a VERY late priority. |
|
555 | - * |
|
556 | - * @return void |
|
557 | - */ |
|
558 | - public function wp_loaded() |
|
559 | - { |
|
560 | - } |
|
561 | - |
|
562 | - |
|
563 | - /** |
|
564 | - * admin_init |
|
565 | - * |
|
566 | - * @return void |
|
567 | - * @throws EE_Error |
|
568 | - * @throws InvalidArgumentException |
|
569 | - * @throws InvalidDataTypeException |
|
570 | - * @throws InvalidInterfaceException |
|
571 | - * @throws ReflectionException |
|
572 | - */ |
|
573 | - public function admin_init() |
|
574 | - { |
|
575 | - |
|
576 | - /** |
|
577 | - * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php), |
|
578 | - * so any hooking into core WP routes is taken care of. So in this next few lines of code: |
|
579 | - * - check if doing post processing. |
|
580 | - * - check if doing post processing of one of EE CPTs |
|
581 | - * - instantiate the corresponding EE CPT model for the post_type being processed. |
|
582 | - */ |
|
583 | - if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') { |
|
584 | - EE_Registry::instance()->load_core('Register_CPTs'); |
|
585 | - EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']); |
|
586 | - } |
|
587 | - |
|
588 | - |
|
589 | - /** |
|
590 | - * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting |
|
591 | - * critical pages. The only place critical pages need included in a generated dropdown is on the "Critical |
|
592 | - * Pages" tab in the EE General Settings Admin page. |
|
593 | - * This is for user-proofing. |
|
594 | - */ |
|
595 | - add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages')); |
|
596 | - } |
|
597 | - |
|
598 | - |
|
599 | - /** |
|
600 | - * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection. |
|
601 | - * |
|
602 | - * @param string $output Current output. |
|
603 | - * @return string |
|
604 | - * @throws InvalidArgumentException |
|
605 | - * @throws InvalidDataTypeException |
|
606 | - * @throws InvalidInterfaceException |
|
607 | - */ |
|
608 | - public function modify_dropdown_pages($output) |
|
609 | - { |
|
610 | - //get critical pages |
|
611 | - $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array(); |
|
612 | - |
|
613 | - //split current output by line break for easier parsing. |
|
614 | - $split_output = explode("\n", $output); |
|
615 | - |
|
616 | - //loop through to remove any critical pages from the array. |
|
617 | - foreach ($critical_pages as $page_id) { |
|
618 | - $needle = 'value="' . $page_id . '"'; |
|
619 | - foreach ($split_output as $key => $haystack) { |
|
620 | - if (strpos($haystack, $needle) !== false) { |
|
621 | - unset($split_output[$key]); |
|
622 | - } |
|
623 | - } |
|
624 | - } |
|
625 | - //replace output with the new contents |
|
626 | - return implode("\n", $split_output); |
|
627 | - } |
|
628 | - |
|
629 | - |
|
630 | - /** |
|
631 | - * enqueue all admin scripts that need loaded for admin pages |
|
632 | - * |
|
633 | - * @return void |
|
634 | - */ |
|
635 | - public function enqueue_admin_scripts() |
|
636 | - { |
|
637 | - // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js. |
|
638 | - // Note: the intention of this script is to only do TARGETED injections. I.E, only injecting on certain script |
|
639 | - // calls. |
|
640 | - wp_enqueue_script( |
|
641 | - 'ee-inject-wp', |
|
642 | - EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js', |
|
643 | - array('jquery'), |
|
644 | - EVENT_ESPRESSO_VERSION, |
|
645 | - true |
|
646 | - ); |
|
647 | - // register cookie script for future dependencies |
|
648 | - wp_register_script( |
|
649 | - 'jquery-cookie', |
|
650 | - EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js', |
|
651 | - array('jquery'), |
|
652 | - '2.1', |
|
653 | - true |
|
654 | - ); |
|
655 | - //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again |
|
656 | - // via: add_filter('FHEE_load_joyride', '__return_true' ); |
|
657 | - if (apply_filters('FHEE_load_joyride', false)) { |
|
658 | - //joyride style |
|
659 | - wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1'); |
|
660 | - wp_register_style( |
|
661 | - 'ee-joyride-css', |
|
662 | - EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css', |
|
663 | - array('joyride-css'), |
|
664 | - EVENT_ESPRESSO_VERSION |
|
665 | - ); |
|
666 | - wp_register_script( |
|
667 | - 'joyride-modernizr', |
|
668 | - EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js', |
|
669 | - array(), |
|
670 | - '2.1', |
|
671 | - true |
|
672 | - ); |
|
673 | - //joyride JS |
|
674 | - wp_register_script( |
|
675 | - 'jquery-joyride', |
|
676 | - EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js', |
|
677 | - array('jquery-cookie', 'joyride-modernizr'), |
|
678 | - '2.1', |
|
679 | - true |
|
680 | - ); |
|
681 | - // wanna go for a joyride? |
|
682 | - wp_enqueue_style('ee-joyride-css'); |
|
683 | - wp_enqueue_script('jquery-joyride'); |
|
684 | - } |
|
685 | - } |
|
686 | - |
|
687 | - |
|
688 | - /** |
|
689 | - * display_admin_notices |
|
690 | - * |
|
691 | - * @return void |
|
692 | - */ |
|
693 | - public function display_admin_notices() |
|
694 | - { |
|
695 | - echo EE_Error::get_notices(); |
|
696 | - } |
|
697 | - |
|
698 | - |
|
699 | - |
|
700 | - /** |
|
701 | - * @param array $elements |
|
702 | - * @return array |
|
703 | - * @throws EE_Error |
|
704 | - * @throws InvalidArgumentException |
|
705 | - * @throws InvalidDataTypeException |
|
706 | - * @throws InvalidInterfaceException |
|
707 | - */ |
|
708 | - public function dashboard_glance_items($elements) |
|
709 | - { |
|
710 | - $elements = is_array($elements) ? $elements : array($elements); |
|
711 | - $events = EEM_Event::instance()->count(); |
|
712 | - $items['events']['url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
713 | - array('page' => 'espresso_events'), |
|
714 | - admin_url('admin.php') |
|
715 | - ); |
|
716 | - $items['events']['text'] = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events)); |
|
717 | - $items['events']['title'] = esc_html__('Click to view all Events', 'event_espresso'); |
|
718 | - $registrations = EEM_Registration::instance()->count( |
|
719 | - array( |
|
720 | - array( |
|
721 | - 'STS_ID' => array('!=', EEM_Registration::status_id_incomplete), |
|
722 | - ), |
|
723 | - ) |
|
724 | - ); |
|
725 | - $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
726 | - array('page' => 'espresso_registrations'), |
|
727 | - admin_url('admin.php') |
|
728 | - ); |
|
729 | - $items['registrations']['text'] = sprintf( |
|
730 | - _n('%s Registration', '%s Registrations', $registrations), |
|
731 | - number_format_i18n($registrations) |
|
732 | - ); |
|
733 | - $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso'); |
|
734 | - |
|
735 | - $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items); |
|
736 | - |
|
737 | - foreach ($items as $type => $item_properties) { |
|
738 | - $elements[] = sprintf( |
|
739 | - '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>', |
|
740 | - $item_properties['url'], |
|
741 | - $item_properties['title'], |
|
742 | - $item_properties['text'] |
|
743 | - ); |
|
744 | - } |
|
745 | - return $elements; |
|
746 | - } |
|
747 | - |
|
748 | - |
|
749 | - /** |
|
750 | - * check_for_invalid_datetime_formats |
|
751 | - * if an admin changes their date or time format settings on the WP General Settings admin page, verify that |
|
752 | - * their selected format can be parsed by PHP |
|
753 | - * |
|
754 | - * @param $value |
|
755 | - * @param $option |
|
756 | - * @throws EE_Error |
|
757 | - * @return string |
|
758 | - */ |
|
759 | - public function check_for_invalid_datetime_formats($value, $option) |
|
760 | - { |
|
761 | - // check for date_format or time_format |
|
762 | - switch ($option) { |
|
763 | - case 'date_format': |
|
764 | - $date_time_format = $value . ' ' . get_option('time_format'); |
|
765 | - break; |
|
766 | - case 'time_format': |
|
767 | - $date_time_format = get_option('date_format') . ' ' . $value; |
|
768 | - break; |
|
769 | - default: |
|
770 | - $date_time_format = false; |
|
771 | - } |
|
772 | - // do we have a date_time format to check ? |
|
773 | - if ($date_time_format) { |
|
774 | - $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format); |
|
775 | - |
|
776 | - if (is_array($error_msg)) { |
|
777 | - $msg = '<p>' |
|
778 | - . sprintf( |
|
779 | - esc_html__( |
|
780 | - 'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:', |
|
781 | - 'event_espresso' |
|
782 | - ), |
|
783 | - date($date_time_format), |
|
784 | - $date_time_format |
|
785 | - ) |
|
786 | - . '</p><p><ul>'; |
|
787 | - |
|
788 | - |
|
789 | - foreach ($error_msg as $error) { |
|
790 | - $msg .= '<li>' . $error . '</li>'; |
|
791 | - } |
|
792 | - |
|
793 | - $msg .= '</ul></p><p>' |
|
794 | - . sprintf( |
|
795 | - esc_html__( |
|
796 | - '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s', |
|
797 | - 'event_espresso' |
|
798 | - ), |
|
799 | - '<span style="color:#D54E21;">', |
|
800 | - '</span>' |
|
801 | - ) |
|
802 | - . '</p>'; |
|
803 | - |
|
804 | - // trigger WP settings error |
|
805 | - add_settings_error( |
|
806 | - 'date_format', |
|
807 | - 'date_format', |
|
808 | - $msg |
|
809 | - ); |
|
810 | - |
|
811 | - // set format to something valid |
|
812 | - switch ($option) { |
|
813 | - case 'date_format': |
|
814 | - $value = 'F j, Y'; |
|
815 | - break; |
|
816 | - case 'time_format': |
|
817 | - $value = 'g:i a'; |
|
818 | - break; |
|
819 | - } |
|
820 | - } |
|
821 | - } |
|
822 | - return $value; |
|
823 | - } |
|
824 | - |
|
825 | - |
|
826 | - /** |
|
827 | - * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso" |
|
828 | - * |
|
829 | - * @param $content |
|
830 | - * @return string |
|
831 | - */ |
|
832 | - public function its_eSpresso($content) |
|
833 | - { |
|
834 | - return str_replace('[EXPRESSO_', '[ESPRESSO_', $content); |
|
835 | - } |
|
836 | - |
|
837 | - |
|
838 | - /** |
|
839 | - * espresso_admin_footer |
|
840 | - * |
|
841 | - * @return string |
|
842 | - */ |
|
843 | - public function espresso_admin_footer() |
|
844 | - { |
|
845 | - return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer')); |
|
846 | - } |
|
847 | - |
|
848 | - |
|
849 | - /** |
|
850 | - * static method for registering ee admin page. |
|
851 | - * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register. |
|
852 | - * |
|
853 | - * @since 4.3.0 |
|
854 | - * @deprecated 4.3.0 Use EE_Register_Admin_Page::register() instead |
|
855 | - * @see EE_Register_Admin_Page::register() |
|
856 | - * @param $page_basename |
|
857 | - * @param $page_path |
|
858 | - * @param array $config |
|
859 | - * @return void |
|
860 | - * @throws EE_Error |
|
861 | - */ |
|
862 | - public static function register_ee_admin_page($page_basename, $page_path, $config = array()) |
|
863 | - { |
|
864 | - EE_Error::doing_it_wrong( |
|
865 | - __METHOD__, |
|
866 | - sprintf( |
|
867 | - esc_html__( |
|
868 | - 'Usage is deprecated. Use EE_Register_Admin_Page::register() for registering the %s admin page.', |
|
869 | - 'event_espresso' |
|
870 | - ), |
|
871 | - $page_basename |
|
872 | - ), |
|
873 | - '4.3' |
|
874 | - ); |
|
875 | - if (class_exists('EE_Register_Admin_Page')) { |
|
876 | - $config['page_path'] = $page_path; |
|
877 | - } |
|
878 | - EE_Register_Admin_Page::register($page_basename, $config); |
|
879 | - } |
|
880 | - |
|
881 | - |
|
882 | - /** |
|
883 | - * @deprecated 4.8.41 |
|
884 | - * @param int $post_ID |
|
885 | - * @param \WP_Post $post |
|
886 | - * @return void |
|
887 | - */ |
|
888 | - public static function parse_post_content_on_save($post_ID, $post) |
|
889 | - { |
|
890 | - EE_Error::doing_it_wrong( |
|
891 | - __METHOD__, |
|
892 | - esc_html__('Usage is deprecated', 'event_espresso'), |
|
893 | - '4.8.41' |
|
894 | - ); |
|
895 | - } |
|
896 | - |
|
897 | - |
|
898 | - /** |
|
899 | - * @deprecated 4.8.41 |
|
900 | - * @param $option |
|
901 | - * @param $old_value |
|
902 | - * @param $value |
|
903 | - * @return void |
|
904 | - */ |
|
905 | - public function reset_page_for_posts_on_change($option, $old_value, $value) |
|
906 | - { |
|
907 | - EE_Error::doing_it_wrong( |
|
908 | - __METHOD__, |
|
909 | - esc_html__('Usage is deprecated', 'event_espresso'), |
|
910 | - '4.8.41' |
|
911 | - ); |
|
912 | - } |
|
913 | - |
|
914 | - |
|
915 | - |
|
916 | - /** |
|
917 | - * @deprecated 4.9.27 |
|
918 | - * @return void |
|
919 | - */ |
|
920 | - public function get_persistent_admin_notices() |
|
921 | - { |
|
922 | - EE_Error::doing_it_wrong( |
|
923 | - __METHOD__, |
|
924 | - sprintf( |
|
925 | - __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'), |
|
926 | - '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
927 | - ), |
|
928 | - '4.9.27' |
|
929 | - ); |
|
930 | - } |
|
931 | - |
|
932 | - |
|
933 | - |
|
934 | - /** |
|
935 | - * @deprecated 4.9.27 |
|
936 | - * @throws InvalidInterfaceException |
|
937 | - * @throws InvalidDataTypeException |
|
938 | - * @throws DomainException |
|
939 | - */ |
|
940 | - public function dismiss_ee_nag_notice_callback() |
|
941 | - { |
|
942 | - EE_Error::doing_it_wrong( |
|
943 | - __METHOD__, |
|
944 | - sprintf( |
|
945 | - __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'), |
|
946 | - '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
947 | - ), |
|
948 | - '4.9.27' |
|
949 | - ); |
|
950 | - $this->persistent_admin_notice_manager->dismissNotice(); |
|
951 | - } |
|
485 | + } |
|
486 | + |
|
487 | + |
|
488 | + /** |
|
489 | + * Returns an array of event archive nav items. |
|
490 | + * |
|
491 | + * @todo for now this method is just in place so when it gets abstracted further we can substitute in whatever |
|
492 | + * method we use for getting the extra nav menu items |
|
493 | + * @return array |
|
494 | + */ |
|
495 | + private function _get_extra_nav_menu_pages_items() |
|
496 | + { |
|
497 | + $menuitems[] = array( |
|
498 | + 'title' => esc_html__('Event List', 'event_espresso'), |
|
499 | + 'url' => get_post_type_archive_link('espresso_events'), |
|
500 | + 'description' => esc_html__('Archive page for all events.', 'event_espresso'), |
|
501 | + ); |
|
502 | + return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems); |
|
503 | + } |
|
504 | + |
|
505 | + |
|
506 | + /** |
|
507 | + * Setup nav menu walker item for usage in the event archive nav menu metabox. It receives a menu_item array with |
|
508 | + * the properties and converts it to the menu item object. |
|
509 | + * |
|
510 | + * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php |
|
511 | + * @param $menu_item_values |
|
512 | + * @return stdClass |
|
513 | + */ |
|
514 | + private function _setup_extra_nav_menu_pages_items($menu_item_values) |
|
515 | + { |
|
516 | + $menu_item = new stdClass(); |
|
517 | + $keys = array( |
|
518 | + 'ID' => 0, |
|
519 | + 'db_id' => 0, |
|
520 | + 'menu_item_parent' => 0, |
|
521 | + 'object_id' => -1, |
|
522 | + 'post_parent' => 0, |
|
523 | + 'type' => 'custom', |
|
524 | + 'object' => '', |
|
525 | + 'type_label' => esc_html__('Extra Nav Menu Item', 'event_espresso'), |
|
526 | + 'title' => '', |
|
527 | + 'url' => '', |
|
528 | + 'target' => '', |
|
529 | + 'attr_title' => '', |
|
530 | + 'description' => '', |
|
531 | + 'classes' => array(), |
|
532 | + 'xfn' => '', |
|
533 | + ); |
|
534 | + |
|
535 | + foreach ($keys as $key => $value) { |
|
536 | + $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value; |
|
537 | + } |
|
538 | + return $menu_item; |
|
539 | + } |
|
540 | + |
|
541 | + |
|
542 | + /** |
|
543 | + * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an |
|
544 | + * EE_Admin_Page route is called. |
|
545 | + * |
|
546 | + * @return void |
|
547 | + */ |
|
548 | + public function route_admin_request() |
|
549 | + { |
|
550 | + } |
|
551 | + |
|
552 | + |
|
553 | + /** |
|
554 | + * wp_loaded should fire on the WordPress wp_loaded hook. This fires on a VERY late priority. |
|
555 | + * |
|
556 | + * @return void |
|
557 | + */ |
|
558 | + public function wp_loaded() |
|
559 | + { |
|
560 | + } |
|
561 | + |
|
562 | + |
|
563 | + /** |
|
564 | + * admin_init |
|
565 | + * |
|
566 | + * @return void |
|
567 | + * @throws EE_Error |
|
568 | + * @throws InvalidArgumentException |
|
569 | + * @throws InvalidDataTypeException |
|
570 | + * @throws InvalidInterfaceException |
|
571 | + * @throws ReflectionException |
|
572 | + */ |
|
573 | + public function admin_init() |
|
574 | + { |
|
575 | + |
|
576 | + /** |
|
577 | + * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php), |
|
578 | + * so any hooking into core WP routes is taken care of. So in this next few lines of code: |
|
579 | + * - check if doing post processing. |
|
580 | + * - check if doing post processing of one of EE CPTs |
|
581 | + * - instantiate the corresponding EE CPT model for the post_type being processed. |
|
582 | + */ |
|
583 | + if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') { |
|
584 | + EE_Registry::instance()->load_core('Register_CPTs'); |
|
585 | + EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']); |
|
586 | + } |
|
587 | + |
|
588 | + |
|
589 | + /** |
|
590 | + * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting |
|
591 | + * critical pages. The only place critical pages need included in a generated dropdown is on the "Critical |
|
592 | + * Pages" tab in the EE General Settings Admin page. |
|
593 | + * This is for user-proofing. |
|
594 | + */ |
|
595 | + add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages')); |
|
596 | + } |
|
597 | + |
|
598 | + |
|
599 | + /** |
|
600 | + * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection. |
|
601 | + * |
|
602 | + * @param string $output Current output. |
|
603 | + * @return string |
|
604 | + * @throws InvalidArgumentException |
|
605 | + * @throws InvalidDataTypeException |
|
606 | + * @throws InvalidInterfaceException |
|
607 | + */ |
|
608 | + public function modify_dropdown_pages($output) |
|
609 | + { |
|
610 | + //get critical pages |
|
611 | + $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array(); |
|
612 | + |
|
613 | + //split current output by line break for easier parsing. |
|
614 | + $split_output = explode("\n", $output); |
|
615 | + |
|
616 | + //loop through to remove any critical pages from the array. |
|
617 | + foreach ($critical_pages as $page_id) { |
|
618 | + $needle = 'value="' . $page_id . '"'; |
|
619 | + foreach ($split_output as $key => $haystack) { |
|
620 | + if (strpos($haystack, $needle) !== false) { |
|
621 | + unset($split_output[$key]); |
|
622 | + } |
|
623 | + } |
|
624 | + } |
|
625 | + //replace output with the new contents |
|
626 | + return implode("\n", $split_output); |
|
627 | + } |
|
628 | + |
|
629 | + |
|
630 | + /** |
|
631 | + * enqueue all admin scripts that need loaded for admin pages |
|
632 | + * |
|
633 | + * @return void |
|
634 | + */ |
|
635 | + public function enqueue_admin_scripts() |
|
636 | + { |
|
637 | + // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js. |
|
638 | + // Note: the intention of this script is to only do TARGETED injections. I.E, only injecting on certain script |
|
639 | + // calls. |
|
640 | + wp_enqueue_script( |
|
641 | + 'ee-inject-wp', |
|
642 | + EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js', |
|
643 | + array('jquery'), |
|
644 | + EVENT_ESPRESSO_VERSION, |
|
645 | + true |
|
646 | + ); |
|
647 | + // register cookie script for future dependencies |
|
648 | + wp_register_script( |
|
649 | + 'jquery-cookie', |
|
650 | + EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js', |
|
651 | + array('jquery'), |
|
652 | + '2.1', |
|
653 | + true |
|
654 | + ); |
|
655 | + //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again |
|
656 | + // via: add_filter('FHEE_load_joyride', '__return_true' ); |
|
657 | + if (apply_filters('FHEE_load_joyride', false)) { |
|
658 | + //joyride style |
|
659 | + wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1'); |
|
660 | + wp_register_style( |
|
661 | + 'ee-joyride-css', |
|
662 | + EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css', |
|
663 | + array('joyride-css'), |
|
664 | + EVENT_ESPRESSO_VERSION |
|
665 | + ); |
|
666 | + wp_register_script( |
|
667 | + 'joyride-modernizr', |
|
668 | + EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js', |
|
669 | + array(), |
|
670 | + '2.1', |
|
671 | + true |
|
672 | + ); |
|
673 | + //joyride JS |
|
674 | + wp_register_script( |
|
675 | + 'jquery-joyride', |
|
676 | + EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js', |
|
677 | + array('jquery-cookie', 'joyride-modernizr'), |
|
678 | + '2.1', |
|
679 | + true |
|
680 | + ); |
|
681 | + // wanna go for a joyride? |
|
682 | + wp_enqueue_style('ee-joyride-css'); |
|
683 | + wp_enqueue_script('jquery-joyride'); |
|
684 | + } |
|
685 | + } |
|
686 | + |
|
687 | + |
|
688 | + /** |
|
689 | + * display_admin_notices |
|
690 | + * |
|
691 | + * @return void |
|
692 | + */ |
|
693 | + public function display_admin_notices() |
|
694 | + { |
|
695 | + echo EE_Error::get_notices(); |
|
696 | + } |
|
697 | + |
|
698 | + |
|
699 | + |
|
700 | + /** |
|
701 | + * @param array $elements |
|
702 | + * @return array |
|
703 | + * @throws EE_Error |
|
704 | + * @throws InvalidArgumentException |
|
705 | + * @throws InvalidDataTypeException |
|
706 | + * @throws InvalidInterfaceException |
|
707 | + */ |
|
708 | + public function dashboard_glance_items($elements) |
|
709 | + { |
|
710 | + $elements = is_array($elements) ? $elements : array($elements); |
|
711 | + $events = EEM_Event::instance()->count(); |
|
712 | + $items['events']['url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
713 | + array('page' => 'espresso_events'), |
|
714 | + admin_url('admin.php') |
|
715 | + ); |
|
716 | + $items['events']['text'] = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events)); |
|
717 | + $items['events']['title'] = esc_html__('Click to view all Events', 'event_espresso'); |
|
718 | + $registrations = EEM_Registration::instance()->count( |
|
719 | + array( |
|
720 | + array( |
|
721 | + 'STS_ID' => array('!=', EEM_Registration::status_id_incomplete), |
|
722 | + ), |
|
723 | + ) |
|
724 | + ); |
|
725 | + $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
726 | + array('page' => 'espresso_registrations'), |
|
727 | + admin_url('admin.php') |
|
728 | + ); |
|
729 | + $items['registrations']['text'] = sprintf( |
|
730 | + _n('%s Registration', '%s Registrations', $registrations), |
|
731 | + number_format_i18n($registrations) |
|
732 | + ); |
|
733 | + $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso'); |
|
734 | + |
|
735 | + $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items); |
|
736 | + |
|
737 | + foreach ($items as $type => $item_properties) { |
|
738 | + $elements[] = sprintf( |
|
739 | + '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>', |
|
740 | + $item_properties['url'], |
|
741 | + $item_properties['title'], |
|
742 | + $item_properties['text'] |
|
743 | + ); |
|
744 | + } |
|
745 | + return $elements; |
|
746 | + } |
|
747 | + |
|
748 | + |
|
749 | + /** |
|
750 | + * check_for_invalid_datetime_formats |
|
751 | + * if an admin changes their date or time format settings on the WP General Settings admin page, verify that |
|
752 | + * their selected format can be parsed by PHP |
|
753 | + * |
|
754 | + * @param $value |
|
755 | + * @param $option |
|
756 | + * @throws EE_Error |
|
757 | + * @return string |
|
758 | + */ |
|
759 | + public function check_for_invalid_datetime_formats($value, $option) |
|
760 | + { |
|
761 | + // check for date_format or time_format |
|
762 | + switch ($option) { |
|
763 | + case 'date_format': |
|
764 | + $date_time_format = $value . ' ' . get_option('time_format'); |
|
765 | + break; |
|
766 | + case 'time_format': |
|
767 | + $date_time_format = get_option('date_format') . ' ' . $value; |
|
768 | + break; |
|
769 | + default: |
|
770 | + $date_time_format = false; |
|
771 | + } |
|
772 | + // do we have a date_time format to check ? |
|
773 | + if ($date_time_format) { |
|
774 | + $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format); |
|
775 | + |
|
776 | + if (is_array($error_msg)) { |
|
777 | + $msg = '<p>' |
|
778 | + . sprintf( |
|
779 | + esc_html__( |
|
780 | + 'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:', |
|
781 | + 'event_espresso' |
|
782 | + ), |
|
783 | + date($date_time_format), |
|
784 | + $date_time_format |
|
785 | + ) |
|
786 | + . '</p><p><ul>'; |
|
787 | + |
|
788 | + |
|
789 | + foreach ($error_msg as $error) { |
|
790 | + $msg .= '<li>' . $error . '</li>'; |
|
791 | + } |
|
792 | + |
|
793 | + $msg .= '</ul></p><p>' |
|
794 | + . sprintf( |
|
795 | + esc_html__( |
|
796 | + '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s', |
|
797 | + 'event_espresso' |
|
798 | + ), |
|
799 | + '<span style="color:#D54E21;">', |
|
800 | + '</span>' |
|
801 | + ) |
|
802 | + . '</p>'; |
|
803 | + |
|
804 | + // trigger WP settings error |
|
805 | + add_settings_error( |
|
806 | + 'date_format', |
|
807 | + 'date_format', |
|
808 | + $msg |
|
809 | + ); |
|
810 | + |
|
811 | + // set format to something valid |
|
812 | + switch ($option) { |
|
813 | + case 'date_format': |
|
814 | + $value = 'F j, Y'; |
|
815 | + break; |
|
816 | + case 'time_format': |
|
817 | + $value = 'g:i a'; |
|
818 | + break; |
|
819 | + } |
|
820 | + } |
|
821 | + } |
|
822 | + return $value; |
|
823 | + } |
|
824 | + |
|
825 | + |
|
826 | + /** |
|
827 | + * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso" |
|
828 | + * |
|
829 | + * @param $content |
|
830 | + * @return string |
|
831 | + */ |
|
832 | + public function its_eSpresso($content) |
|
833 | + { |
|
834 | + return str_replace('[EXPRESSO_', '[ESPRESSO_', $content); |
|
835 | + } |
|
836 | + |
|
837 | + |
|
838 | + /** |
|
839 | + * espresso_admin_footer |
|
840 | + * |
|
841 | + * @return string |
|
842 | + */ |
|
843 | + public function espresso_admin_footer() |
|
844 | + { |
|
845 | + return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer')); |
|
846 | + } |
|
847 | + |
|
848 | + |
|
849 | + /** |
|
850 | + * static method for registering ee admin page. |
|
851 | + * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register. |
|
852 | + * |
|
853 | + * @since 4.3.0 |
|
854 | + * @deprecated 4.3.0 Use EE_Register_Admin_Page::register() instead |
|
855 | + * @see EE_Register_Admin_Page::register() |
|
856 | + * @param $page_basename |
|
857 | + * @param $page_path |
|
858 | + * @param array $config |
|
859 | + * @return void |
|
860 | + * @throws EE_Error |
|
861 | + */ |
|
862 | + public static function register_ee_admin_page($page_basename, $page_path, $config = array()) |
|
863 | + { |
|
864 | + EE_Error::doing_it_wrong( |
|
865 | + __METHOD__, |
|
866 | + sprintf( |
|
867 | + esc_html__( |
|
868 | + 'Usage is deprecated. Use EE_Register_Admin_Page::register() for registering the %s admin page.', |
|
869 | + 'event_espresso' |
|
870 | + ), |
|
871 | + $page_basename |
|
872 | + ), |
|
873 | + '4.3' |
|
874 | + ); |
|
875 | + if (class_exists('EE_Register_Admin_Page')) { |
|
876 | + $config['page_path'] = $page_path; |
|
877 | + } |
|
878 | + EE_Register_Admin_Page::register($page_basename, $config); |
|
879 | + } |
|
880 | + |
|
881 | + |
|
882 | + /** |
|
883 | + * @deprecated 4.8.41 |
|
884 | + * @param int $post_ID |
|
885 | + * @param \WP_Post $post |
|
886 | + * @return void |
|
887 | + */ |
|
888 | + public static function parse_post_content_on_save($post_ID, $post) |
|
889 | + { |
|
890 | + EE_Error::doing_it_wrong( |
|
891 | + __METHOD__, |
|
892 | + esc_html__('Usage is deprecated', 'event_espresso'), |
|
893 | + '4.8.41' |
|
894 | + ); |
|
895 | + } |
|
896 | + |
|
897 | + |
|
898 | + /** |
|
899 | + * @deprecated 4.8.41 |
|
900 | + * @param $option |
|
901 | + * @param $old_value |
|
902 | + * @param $value |
|
903 | + * @return void |
|
904 | + */ |
|
905 | + public function reset_page_for_posts_on_change($option, $old_value, $value) |
|
906 | + { |
|
907 | + EE_Error::doing_it_wrong( |
|
908 | + __METHOD__, |
|
909 | + esc_html__('Usage is deprecated', 'event_espresso'), |
|
910 | + '4.8.41' |
|
911 | + ); |
|
912 | + } |
|
913 | + |
|
914 | + |
|
915 | + |
|
916 | + /** |
|
917 | + * @deprecated 4.9.27 |
|
918 | + * @return void |
|
919 | + */ |
|
920 | + public function get_persistent_admin_notices() |
|
921 | + { |
|
922 | + EE_Error::doing_it_wrong( |
|
923 | + __METHOD__, |
|
924 | + sprintf( |
|
925 | + __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'), |
|
926 | + '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
927 | + ), |
|
928 | + '4.9.27' |
|
929 | + ); |
|
930 | + } |
|
931 | + |
|
932 | + |
|
933 | + |
|
934 | + /** |
|
935 | + * @deprecated 4.9.27 |
|
936 | + * @throws InvalidInterfaceException |
|
937 | + * @throws InvalidDataTypeException |
|
938 | + * @throws DomainException |
|
939 | + */ |
|
940 | + public function dismiss_ee_nag_notice_callback() |
|
941 | + { |
|
942 | + EE_Error::doing_it_wrong( |
|
943 | + __METHOD__, |
|
944 | + sprintf( |
|
945 | + __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'), |
|
946 | + '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager' |
|
947 | + ), |
|
948 | + '4.9.27' |
|
949 | + ); |
|
950 | + $this->persistent_admin_notice_manager->dismissNotice(); |
|
951 | + } |
|
952 | 952 | } |
@@ -40,7 +40,7 @@ discard block |
||
40 | 40 | public static function instance() |
41 | 41 | { |
42 | 42 | // check if class object is instantiated |
43 | - if (! self::$_instance instanceof EE_Admin) { |
|
43 | + if ( ! self::$_instance instanceof EE_Admin) { |
|
44 | 44 | self::$_instance = new self(); |
45 | 45 | } |
46 | 46 | return self::$_instance; |
@@ -100,11 +100,11 @@ discard block |
||
100 | 100 | */ |
101 | 101 | private function _define_all_constants() |
102 | 102 | { |
103 | - if (! defined('EE_ADMIN_URL')) { |
|
104 | - define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/'); |
|
105 | - define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/'); |
|
106 | - define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS); |
|
107 | - define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/'); |
|
103 | + if ( ! defined('EE_ADMIN_URL')) { |
|
104 | + define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL.'core/admin/'); |
|
105 | + define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL.'admin_pages/'); |
|
106 | + define('EE_ADMIN_TEMPLATE', EE_ADMIN.'templates'.DS); |
|
107 | + define('WP_ADMIN_PATH', ABSPATH.'wp-admin/'); |
|
108 | 108 | define('WP_AJAX_URL', admin_url('admin-ajax.php')); |
109 | 109 | } |
110 | 110 | } |
@@ -122,7 +122,7 @@ discard block |
||
122 | 122 | // set $main_file in stone |
123 | 123 | static $main_file; |
124 | 124 | // if $main_file is not set yet |
125 | - if (! $main_file) { |
|
125 | + if ( ! $main_file) { |
|
126 | 126 | $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE); |
127 | 127 | } |
128 | 128 | if ($plugin === $main_file) { |
@@ -175,9 +175,9 @@ discard block |
||
175 | 175 | public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array()) |
176 | 176 | { |
177 | 177 | return array( |
178 | - 'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS, |
|
179 | - 'about' => EE_ADMIN_PAGES . 'about' . DS, |
|
180 | - 'support' => EE_ADMIN_PAGES . 'support' . DS, |
|
178 | + 'maintenance' => EE_ADMIN_PAGES.'maintenance'.DS, |
|
179 | + 'about' => EE_ADMIN_PAGES.'about'.DS, |
|
180 | + 'support' => EE_ADMIN_PAGES.'support'.DS, |
|
181 | 181 | ); |
182 | 182 | } |
183 | 183 | |
@@ -219,7 +219,7 @@ discard block |
||
219 | 219 | add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2); |
220 | 220 | } |
221 | 221 | // run the admin page factory but ONLY if we are doing an ee admin ajax request |
222 | - if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) { |
|
222 | + if ( ! defined('DOING_AJAX') || EE_ADMIN_AJAX) { |
|
223 | 223 | try { |
224 | 224 | //this loads the controller for the admin pages which will setup routing etc |
225 | 225 | EE_Registry::instance()->load_core('Admin_Page_Loader'); |
@@ -252,7 +252,7 @@ discard block |
||
252 | 252 | //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version |
253 | 253 | //with this. But after enough time (indeterminate at this point) we can just remove this notice. |
254 | 254 | //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626 |
255 | - if (! get_option('timezone_string') && EEM_Event::instance()->count() > 0) { |
|
255 | + if ( ! get_option('timezone_string') && EEM_Event::instance()->count() > 0) { |
|
256 | 256 | new PersistentAdminNotice( |
257 | 257 | 'datetime_fix_notice', |
258 | 258 | sprintf( |
@@ -264,13 +264,13 @@ discard block |
||
264 | 264 | '</strong>', |
265 | 265 | '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">', |
266 | 266 | '</a>', |
267 | - '<a href="' . EE_Admin_Page::add_query_args_and_nonce( |
|
267 | + '<a href="'.EE_Admin_Page::add_query_args_and_nonce( |
|
268 | 268 | array( |
269 | 269 | 'page' => 'espresso_maintenance_settings', |
270 | 270 | 'action' => 'datetime_tools' |
271 | 271 | ), |
272 | 272 | admin_url('admin.php') |
273 | - ) . '">' |
|
273 | + ).'">' |
|
274 | 274 | ), |
275 | 275 | false, |
276 | 276 | 'manage_options', |
@@ -318,7 +318,7 @@ discard block |
||
318 | 318 | public function enable_hidden_ee_nav_menu_metaboxes() |
319 | 319 | { |
320 | 320 | global $wp_meta_boxes, $pagenow; |
321 | - if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') { |
|
321 | + if ( ! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') { |
|
322 | 322 | return; |
323 | 323 | } |
324 | 324 | $user = wp_get_current_user(); |
@@ -389,7 +389,7 @@ discard block |
||
389 | 389 | */ |
390 | 390 | public function modify_edit_post_link($link, $id) |
391 | 391 | { |
392 | - if (! $post = get_post($id)) { |
|
392 | + if ( ! $post = get_post($id)) { |
|
393 | 393 | return $link; |
394 | 394 | } |
395 | 395 | if ($post->post_type === 'espresso_attendees') { |
@@ -615,7 +615,7 @@ discard block |
||
615 | 615 | |
616 | 616 | //loop through to remove any critical pages from the array. |
617 | 617 | foreach ($critical_pages as $page_id) { |
618 | - $needle = 'value="' . $page_id . '"'; |
|
618 | + $needle = 'value="'.$page_id.'"'; |
|
619 | 619 | foreach ($split_output as $key => $haystack) { |
620 | 620 | if (strpos($haystack, $needle) !== false) { |
621 | 621 | unset($split_output[$key]); |
@@ -639,7 +639,7 @@ discard block |
||
639 | 639 | // calls. |
640 | 640 | wp_enqueue_script( |
641 | 641 | 'ee-inject-wp', |
642 | - EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js', |
|
642 | + EE_ADMIN_URL.'assets/ee-cpt-wp-injects.js', |
|
643 | 643 | array('jquery'), |
644 | 644 | EVENT_ESPRESSO_VERSION, |
645 | 645 | true |
@@ -647,7 +647,7 @@ discard block |
||
647 | 647 | // register cookie script for future dependencies |
648 | 648 | wp_register_script( |
649 | 649 | 'jquery-cookie', |
650 | - EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js', |
|
650 | + EE_THIRD_PARTY_URL.'joyride/jquery.cookie.js', |
|
651 | 651 | array('jquery'), |
652 | 652 | '2.1', |
653 | 653 | true |
@@ -656,16 +656,16 @@ discard block |
||
656 | 656 | // via: add_filter('FHEE_load_joyride', '__return_true' ); |
657 | 657 | if (apply_filters('FHEE_load_joyride', false)) { |
658 | 658 | //joyride style |
659 | - wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1'); |
|
659 | + wp_register_style('joyride-css', EE_THIRD_PARTY_URL.'joyride/joyride-2.1.css', array(), '2.1'); |
|
660 | 660 | wp_register_style( |
661 | 661 | 'ee-joyride-css', |
662 | - EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css', |
|
662 | + EE_GLOBAL_ASSETS_URL.'css/ee-joyride-styles.css', |
|
663 | 663 | array('joyride-css'), |
664 | 664 | EVENT_ESPRESSO_VERSION |
665 | 665 | ); |
666 | 666 | wp_register_script( |
667 | 667 | 'joyride-modernizr', |
668 | - EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js', |
|
668 | + EE_THIRD_PARTY_URL.'joyride/modernizr.mq.js', |
|
669 | 669 | array(), |
670 | 670 | '2.1', |
671 | 671 | true |
@@ -673,7 +673,7 @@ discard block |
||
673 | 673 | //joyride JS |
674 | 674 | wp_register_script( |
675 | 675 | 'jquery-joyride', |
676 | - EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js', |
|
676 | + EE_THIRD_PARTY_URL.'joyride/jquery.joyride-2.1.js', |
|
677 | 677 | array('jquery-cookie', 'joyride-modernizr'), |
678 | 678 | '2.1', |
679 | 679 | true |
@@ -722,21 +722,21 @@ discard block |
||
722 | 722 | ), |
723 | 723 | ) |
724 | 724 | ); |
725 | - $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
725 | + $items['registrations']['url'] = EE_Admin_Page::add_query_args_and_nonce( |
|
726 | 726 | array('page' => 'espresso_registrations'), |
727 | 727 | admin_url('admin.php') |
728 | 728 | ); |
729 | - $items['registrations']['text'] = sprintf( |
|
729 | + $items['registrations']['text'] = sprintf( |
|
730 | 730 | _n('%s Registration', '%s Registrations', $registrations), |
731 | 731 | number_format_i18n($registrations) |
732 | 732 | ); |
733 | 733 | $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso'); |
734 | 734 | |
735 | - $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items); |
|
735 | + $items = (array) apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items); |
|
736 | 736 | |
737 | 737 | foreach ($items as $type => $item_properties) { |
738 | 738 | $elements[] = sprintf( |
739 | - '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>', |
|
739 | + '<a class="ee-dashboard-link-'.$type.'" href="%s" title="%s">%s</a>', |
|
740 | 740 | $item_properties['url'], |
741 | 741 | $item_properties['title'], |
742 | 742 | $item_properties['text'] |
@@ -761,10 +761,10 @@ discard block |
||
761 | 761 | // check for date_format or time_format |
762 | 762 | switch ($option) { |
763 | 763 | case 'date_format': |
764 | - $date_time_format = $value . ' ' . get_option('time_format'); |
|
764 | + $date_time_format = $value.' '.get_option('time_format'); |
|
765 | 765 | break; |
766 | 766 | case 'time_format': |
767 | - $date_time_format = get_option('date_format') . ' ' . $value; |
|
767 | + $date_time_format = get_option('date_format').' '.$value; |
|
768 | 768 | break; |
769 | 769 | default: |
770 | 770 | $date_time_format = false; |
@@ -787,7 +787,7 @@ discard block |
||
787 | 787 | |
788 | 788 | |
789 | 789 | foreach ($error_msg as $error) { |
790 | - $msg .= '<li>' . $error . '</li>'; |
|
790 | + $msg .= '<li>'.$error.'</li>'; |
|
791 | 791 | } |
792 | 792 | |
793 | 793 | $msg .= '</ul></p><p>' |
@@ -1,6 +1,6 @@ discard block |
||
1 | 1 | <?php |
2 | 2 | if (! defined('EVENT_ESPRESSO_VERSION')) { |
3 | - exit('NO direct script access allowed'); |
|
3 | + exit('NO direct script access allowed'); |
|
4 | 4 | } |
5 | 5 | |
6 | 6 | /** |
@@ -28,596 +28,596 @@ discard block |
||
28 | 28 | class Registration_Form_Admin_Page extends EE_Admin_Page |
29 | 29 | { |
30 | 30 | |
31 | - /** |
|
32 | - * _question |
|
33 | - * holds the specific question object for the question details screen |
|
34 | - * |
|
35 | - * @var EE_Question $_question |
|
36 | - */ |
|
37 | - protected $_question; |
|
38 | - |
|
39 | - /** |
|
40 | - * _question_group |
|
41 | - * holds the specific question group object for the question group details screen |
|
42 | - * |
|
43 | - * @var EE_Question_Group $_question_group |
|
44 | - */ |
|
45 | - protected $_question_group; |
|
46 | - |
|
47 | - /** |
|
48 | - *_question_model EEM_Question model instance (for queries) |
|
49 | - * |
|
50 | - * @var EEM_Question $_question_model ; |
|
51 | - */ |
|
52 | - protected $_question_model; |
|
53 | - |
|
54 | - /** |
|
55 | - * _question_group_model EEM_Question_group instance (for queries) |
|
56 | - * |
|
57 | - * @var EEM_Question_Group $_question_group_model |
|
58 | - */ |
|
59 | - protected $_question_group_model; |
|
60 | - |
|
61 | - |
|
62 | - /** |
|
63 | - * @Constructor |
|
64 | - * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object. |
|
65 | - * @access public |
|
66 | - */ |
|
67 | - public function __construct($routing = true) |
|
68 | - { |
|
69 | - require_once(EE_MODELS . 'EEM_Question.model.php'); |
|
70 | - require_once(EE_MODELS . 'EEM_Question_Group.model.php'); |
|
71 | - $this->_question_model = EEM_Question::instance(); |
|
72 | - $this->_question_group_model = EEM_Question_Group::instance(); |
|
73 | - parent::__construct($routing); |
|
74 | - } |
|
75 | - |
|
76 | - |
|
77 | - protected function _init_page_props() |
|
78 | - { |
|
79 | - $this->page_slug = REGISTRATION_FORM_PG_SLUG; |
|
80 | - $this->page_label = esc_html__('Registration Form', 'event_espresso'); |
|
81 | - $this->_admin_base_url = REGISTRATION_FORM_ADMIN_URL; |
|
82 | - $this->_admin_base_path = REGISTRATION_FORM_ADMIN; |
|
83 | - } |
|
84 | - |
|
85 | - |
|
86 | - protected function _ajax_hooks() |
|
87 | - { |
|
88 | - } |
|
89 | - |
|
90 | - |
|
91 | - protected function _define_page_props() |
|
92 | - { |
|
93 | - $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso'); |
|
94 | - $this->_labels = array( |
|
95 | - 'buttons' => array( |
|
96 | - 'edit_question' => esc_html__('Edit Question', 'event_espresso'), |
|
97 | - ), |
|
98 | - ); |
|
99 | - } |
|
100 | - |
|
101 | - |
|
102 | - /** |
|
103 | - *_set_page_routes |
|
104 | - */ |
|
105 | - protected function _set_page_routes() |
|
106 | - { |
|
107 | - $qst_id = ! empty($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0; |
|
108 | - $this->_page_routes = array( |
|
109 | - 'default' => array( |
|
110 | - 'func' => '_questions_overview_list_table', |
|
111 | - 'capability' => 'ee_read_questions', |
|
112 | - ), |
|
113 | - |
|
114 | - 'edit_question' => array( |
|
115 | - 'func' => '_edit_question', |
|
116 | - 'capability' => 'ee_edit_question', |
|
117 | - 'obj_id' => $qst_id, |
|
118 | - 'args' => array('edit'), |
|
119 | - ), |
|
120 | - |
|
121 | - 'question_groups' => array( |
|
122 | - 'func' => '_questions_groups_preview', |
|
123 | - 'capability' => 'ee_read_question_groups', |
|
124 | - ), |
|
125 | - |
|
126 | - 'update_question' => array( |
|
127 | - 'func' => '_insert_or_update_question', |
|
128 | - 'args' => array('new_question' => false), |
|
129 | - 'capability' => 'ee_edit_question', |
|
130 | - 'obj_id' => $qst_id, |
|
131 | - 'noheader' => true, |
|
132 | - ), |
|
133 | - ); |
|
134 | - } |
|
135 | - |
|
136 | - |
|
137 | - protected function _set_page_config() |
|
138 | - { |
|
139 | - $this->_page_config = array( |
|
140 | - 'default' => array( |
|
141 | - 'nav' => array( |
|
142 | - 'label' => esc_html__('Questions', 'event_espresso'), |
|
143 | - 'order' => 10, |
|
144 | - ), |
|
145 | - 'list_table' => 'Registration_Form_Questions_Admin_List_Table', |
|
146 | - 'metaboxes' => $this->_default_espresso_metaboxes, |
|
147 | - 'help_tabs' => array( |
|
148 | - 'registration_form_questions_overview_help_tab' => array( |
|
149 | - 'title' => esc_html__('Questions Overview', 'event_espresso'), |
|
150 | - 'filename' => 'registration_form_questions_overview', |
|
151 | - ), |
|
152 | - 'registration_form_questions_overview_table_column_headings_help_tab' => array( |
|
153 | - 'title' => esc_html__('Questions Overview Table Column Headings', 'event_espresso'), |
|
154 | - 'filename' => 'registration_form_questions_overview_table_column_headings', |
|
155 | - ), |
|
156 | - 'registration_form_questions_overview_views_bulk_actions_search_help_tab' => array( |
|
157 | - 'title' => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'), |
|
158 | - 'filename' => 'registration_form_questions_overview_views_bulk_actions_search', |
|
159 | - ), |
|
160 | - ), |
|
161 | - 'help_tour' => array('Registration_Form_Questions_Overview_Help_Tour'), |
|
162 | - 'require_nonce' => false, |
|
163 | - 'qtips' => array( |
|
164 | - 'EE_Registration_Form_Tips', |
|
165 | - )/**/ |
|
166 | - ), |
|
167 | - |
|
168 | - 'question_groups' => array( |
|
169 | - 'nav' => array( |
|
170 | - 'label' => esc_html__('Question Groups', 'event_espresso'), |
|
171 | - 'order' => 20, |
|
172 | - ), |
|
173 | - 'metaboxes' => $this->_default_espresso_metaboxes, |
|
174 | - 'help_tabs' => array( |
|
175 | - 'registration_form_question_groups_help_tab' => array( |
|
176 | - 'title' => esc_html__('Question Groups', 'event_espresso'), |
|
177 | - 'filename' => 'registration_form_question_groups', |
|
178 | - ), |
|
179 | - ), |
|
180 | - 'help_tour' => array('Registration_Form_Question_Groups_Help_Tour'), |
|
181 | - 'require_nonce' => false, |
|
182 | - ), |
|
183 | - |
|
184 | - 'edit_question' => array( |
|
185 | - 'nav' => array( |
|
186 | - 'label' => esc_html__('Edit Question', 'event_espresso'), |
|
187 | - 'order' => 15, |
|
188 | - 'persistent' => false, |
|
189 | - 'url' => isset($this->_req_data['question_id']) ? add_query_arg(array('question_id' => $this->_req_data['question_id']), |
|
190 | - $this->_current_page_view_url) : $this->_admin_base_url, |
|
191 | - ), |
|
192 | - 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
193 | - 'help_tabs' => array( |
|
194 | - 'registration_form_edit_question_group_help_tab' => array( |
|
195 | - 'title' => esc_html__('Edit Question', 'event_espresso'), |
|
196 | - 'filename' => 'registration_form_edit_question', |
|
197 | - ), |
|
198 | - ), |
|
199 | - 'help_tour' => array('Registration_Form_Edit_Question_Help_Tour'), |
|
200 | - 'require_nonce' => false, |
|
201 | - ), |
|
202 | - ); |
|
203 | - } |
|
204 | - |
|
205 | - |
|
206 | - protected function _add_screen_options() |
|
207 | - { |
|
208 | - //todo |
|
209 | - } |
|
210 | - |
|
211 | - protected function _add_screen_options_default() |
|
212 | - { |
|
213 | - $page_title = $this->_admin_page_title; |
|
214 | - $this->_admin_page_title = esc_html__('Questions', 'event_espresso'); |
|
215 | - $this->_per_page_screen_option(); |
|
216 | - $this->_admin_page_title = $page_title; |
|
217 | - } |
|
218 | - |
|
219 | - protected function _add_screen_options_question_groups() |
|
220 | - { |
|
221 | - $page_title = $this->_admin_page_title; |
|
222 | - $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso'); |
|
223 | - $this->_per_page_screen_option(); |
|
224 | - $this->_admin_page_title = $page_title; |
|
225 | - } |
|
226 | - |
|
227 | - //none of the below group are currently used for Event Categories |
|
228 | - protected function _add_feature_pointers() |
|
229 | - { |
|
230 | - } |
|
231 | - |
|
232 | - public function load_scripts_styles() |
|
233 | - { |
|
234 | - wp_register_style('espresso_registration', |
|
235 | - REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css', array(), EVENT_ESPRESSO_VERSION); |
|
236 | - wp_enqueue_style('espresso_registration'); |
|
237 | - } |
|
238 | - |
|
239 | - public function admin_init() |
|
240 | - { |
|
241 | - } |
|
242 | - |
|
243 | - public function admin_notices() |
|
244 | - { |
|
245 | - } |
|
246 | - |
|
247 | - public function admin_footer_scripts() |
|
248 | - { |
|
249 | - } |
|
250 | - |
|
251 | - |
|
252 | - public function load_scripts_styles_default() |
|
253 | - { |
|
254 | - } |
|
255 | - |
|
256 | - |
|
257 | - public function load_scripts_styles_add_question() |
|
258 | - { |
|
259 | - $this->load_scripts_styles_forms(); |
|
260 | - wp_register_script('espresso_registration_form_single', |
|
261 | - REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
262 | - EVENT_ESPRESSO_VERSION, true); |
|
263 | - wp_enqueue_script('espresso_registration_form_single'); |
|
264 | - } |
|
265 | - |
|
266 | - public function load_scripts_styles_edit_question() |
|
267 | - { |
|
268 | - $this->load_scripts_styles_forms(); |
|
269 | - wp_register_script('espresso_registration_form_single', |
|
270 | - REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
271 | - EVENT_ESPRESSO_VERSION, true); |
|
272 | - wp_enqueue_script('espresso_registration_form_single'); |
|
273 | - } |
|
274 | - |
|
275 | - |
|
276 | - public function recaptcha_info_help_tab() |
|
277 | - { |
|
278 | - $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php'; |
|
279 | - EEH_Template::display_template($template, array()); |
|
280 | - } |
|
281 | - |
|
282 | - |
|
283 | - public function load_scripts_styles_forms() |
|
284 | - { |
|
285 | - //styles |
|
286 | - wp_enqueue_style('espresso-ui-theme'); |
|
287 | - //scripts |
|
288 | - wp_enqueue_script('ee_admin_js'); |
|
289 | - } |
|
290 | - |
|
291 | - |
|
292 | - protected function _set_list_table_views_default() |
|
293 | - { |
|
294 | - $this->_views = array( |
|
295 | - 'all' => array( |
|
296 | - 'slug' => 'all', |
|
297 | - 'label' => esc_html__('View All Questions', 'event_espresso'), |
|
298 | - 'count' => 0, |
|
31 | + /** |
|
32 | + * _question |
|
33 | + * holds the specific question object for the question details screen |
|
34 | + * |
|
35 | + * @var EE_Question $_question |
|
36 | + */ |
|
37 | + protected $_question; |
|
38 | + |
|
39 | + /** |
|
40 | + * _question_group |
|
41 | + * holds the specific question group object for the question group details screen |
|
42 | + * |
|
43 | + * @var EE_Question_Group $_question_group |
|
44 | + */ |
|
45 | + protected $_question_group; |
|
46 | + |
|
47 | + /** |
|
48 | + *_question_model EEM_Question model instance (for queries) |
|
49 | + * |
|
50 | + * @var EEM_Question $_question_model ; |
|
51 | + */ |
|
52 | + protected $_question_model; |
|
53 | + |
|
54 | + /** |
|
55 | + * _question_group_model EEM_Question_group instance (for queries) |
|
56 | + * |
|
57 | + * @var EEM_Question_Group $_question_group_model |
|
58 | + */ |
|
59 | + protected $_question_group_model; |
|
60 | + |
|
61 | + |
|
62 | + /** |
|
63 | + * @Constructor |
|
64 | + * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object. |
|
65 | + * @access public |
|
66 | + */ |
|
67 | + public function __construct($routing = true) |
|
68 | + { |
|
69 | + require_once(EE_MODELS . 'EEM_Question.model.php'); |
|
70 | + require_once(EE_MODELS . 'EEM_Question_Group.model.php'); |
|
71 | + $this->_question_model = EEM_Question::instance(); |
|
72 | + $this->_question_group_model = EEM_Question_Group::instance(); |
|
73 | + parent::__construct($routing); |
|
74 | + } |
|
75 | + |
|
76 | + |
|
77 | + protected function _init_page_props() |
|
78 | + { |
|
79 | + $this->page_slug = REGISTRATION_FORM_PG_SLUG; |
|
80 | + $this->page_label = esc_html__('Registration Form', 'event_espresso'); |
|
81 | + $this->_admin_base_url = REGISTRATION_FORM_ADMIN_URL; |
|
82 | + $this->_admin_base_path = REGISTRATION_FORM_ADMIN; |
|
83 | + } |
|
84 | + |
|
85 | + |
|
86 | + protected function _ajax_hooks() |
|
87 | + { |
|
88 | + } |
|
89 | + |
|
90 | + |
|
91 | + protected function _define_page_props() |
|
92 | + { |
|
93 | + $this->_admin_page_title = esc_html__('Registration Form', 'event_espresso'); |
|
94 | + $this->_labels = array( |
|
95 | + 'buttons' => array( |
|
96 | + 'edit_question' => esc_html__('Edit Question', 'event_espresso'), |
|
97 | + ), |
|
98 | + ); |
|
99 | + } |
|
100 | + |
|
101 | + |
|
102 | + /** |
|
103 | + *_set_page_routes |
|
104 | + */ |
|
105 | + protected function _set_page_routes() |
|
106 | + { |
|
107 | + $qst_id = ! empty($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0; |
|
108 | + $this->_page_routes = array( |
|
109 | + 'default' => array( |
|
110 | + 'func' => '_questions_overview_list_table', |
|
111 | + 'capability' => 'ee_read_questions', |
|
112 | + ), |
|
113 | + |
|
114 | + 'edit_question' => array( |
|
115 | + 'func' => '_edit_question', |
|
116 | + 'capability' => 'ee_edit_question', |
|
117 | + 'obj_id' => $qst_id, |
|
118 | + 'args' => array('edit'), |
|
119 | + ), |
|
120 | + |
|
121 | + 'question_groups' => array( |
|
122 | + 'func' => '_questions_groups_preview', |
|
123 | + 'capability' => 'ee_read_question_groups', |
|
124 | + ), |
|
125 | + |
|
126 | + 'update_question' => array( |
|
127 | + 'func' => '_insert_or_update_question', |
|
128 | + 'args' => array('new_question' => false), |
|
129 | + 'capability' => 'ee_edit_question', |
|
130 | + 'obj_id' => $qst_id, |
|
131 | + 'noheader' => true, |
|
132 | + ), |
|
133 | + ); |
|
134 | + } |
|
135 | + |
|
136 | + |
|
137 | + protected function _set_page_config() |
|
138 | + { |
|
139 | + $this->_page_config = array( |
|
140 | + 'default' => array( |
|
141 | + 'nav' => array( |
|
142 | + 'label' => esc_html__('Questions', 'event_espresso'), |
|
143 | + 'order' => 10, |
|
144 | + ), |
|
145 | + 'list_table' => 'Registration_Form_Questions_Admin_List_Table', |
|
146 | + 'metaboxes' => $this->_default_espresso_metaboxes, |
|
147 | + 'help_tabs' => array( |
|
148 | + 'registration_form_questions_overview_help_tab' => array( |
|
149 | + 'title' => esc_html__('Questions Overview', 'event_espresso'), |
|
150 | + 'filename' => 'registration_form_questions_overview', |
|
151 | + ), |
|
152 | + 'registration_form_questions_overview_table_column_headings_help_tab' => array( |
|
153 | + 'title' => esc_html__('Questions Overview Table Column Headings', 'event_espresso'), |
|
154 | + 'filename' => 'registration_form_questions_overview_table_column_headings', |
|
155 | + ), |
|
156 | + 'registration_form_questions_overview_views_bulk_actions_search_help_tab' => array( |
|
157 | + 'title' => esc_html__('Question Overview Views & Bulk Actions & Search', 'event_espresso'), |
|
158 | + 'filename' => 'registration_form_questions_overview_views_bulk_actions_search', |
|
159 | + ), |
|
160 | + ), |
|
161 | + 'help_tour' => array('Registration_Form_Questions_Overview_Help_Tour'), |
|
162 | + 'require_nonce' => false, |
|
163 | + 'qtips' => array( |
|
164 | + 'EE_Registration_Form_Tips', |
|
165 | + )/**/ |
|
166 | + ), |
|
167 | + |
|
168 | + 'question_groups' => array( |
|
169 | + 'nav' => array( |
|
170 | + 'label' => esc_html__('Question Groups', 'event_espresso'), |
|
171 | + 'order' => 20, |
|
172 | + ), |
|
173 | + 'metaboxes' => $this->_default_espresso_metaboxes, |
|
174 | + 'help_tabs' => array( |
|
175 | + 'registration_form_question_groups_help_tab' => array( |
|
176 | + 'title' => esc_html__('Question Groups', 'event_espresso'), |
|
177 | + 'filename' => 'registration_form_question_groups', |
|
178 | + ), |
|
179 | + ), |
|
180 | + 'help_tour' => array('Registration_Form_Question_Groups_Help_Tour'), |
|
181 | + 'require_nonce' => false, |
|
182 | + ), |
|
183 | + |
|
184 | + 'edit_question' => array( |
|
185 | + 'nav' => array( |
|
186 | + 'label' => esc_html__('Edit Question', 'event_espresso'), |
|
187 | + 'order' => 15, |
|
188 | + 'persistent' => false, |
|
189 | + 'url' => isset($this->_req_data['question_id']) ? add_query_arg(array('question_id' => $this->_req_data['question_id']), |
|
190 | + $this->_current_page_view_url) : $this->_admin_base_url, |
|
191 | + ), |
|
192 | + 'metaboxes' => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')), |
|
193 | + 'help_tabs' => array( |
|
194 | + 'registration_form_edit_question_group_help_tab' => array( |
|
195 | + 'title' => esc_html__('Edit Question', 'event_espresso'), |
|
196 | + 'filename' => 'registration_form_edit_question', |
|
197 | + ), |
|
198 | + ), |
|
199 | + 'help_tour' => array('Registration_Form_Edit_Question_Help_Tour'), |
|
200 | + 'require_nonce' => false, |
|
201 | + ), |
|
202 | + ); |
|
203 | + } |
|
204 | + |
|
205 | + |
|
206 | + protected function _add_screen_options() |
|
207 | + { |
|
208 | + //todo |
|
209 | + } |
|
210 | + |
|
211 | + protected function _add_screen_options_default() |
|
212 | + { |
|
213 | + $page_title = $this->_admin_page_title; |
|
214 | + $this->_admin_page_title = esc_html__('Questions', 'event_espresso'); |
|
215 | + $this->_per_page_screen_option(); |
|
216 | + $this->_admin_page_title = $page_title; |
|
217 | + } |
|
218 | + |
|
219 | + protected function _add_screen_options_question_groups() |
|
220 | + { |
|
221 | + $page_title = $this->_admin_page_title; |
|
222 | + $this->_admin_page_title = esc_html__('Question Groups', 'event_espresso'); |
|
223 | + $this->_per_page_screen_option(); |
|
224 | + $this->_admin_page_title = $page_title; |
|
225 | + } |
|
226 | + |
|
227 | + //none of the below group are currently used for Event Categories |
|
228 | + protected function _add_feature_pointers() |
|
229 | + { |
|
230 | + } |
|
231 | + |
|
232 | + public function load_scripts_styles() |
|
233 | + { |
|
234 | + wp_register_style('espresso_registration', |
|
235 | + REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css', array(), EVENT_ESPRESSO_VERSION); |
|
236 | + wp_enqueue_style('espresso_registration'); |
|
237 | + } |
|
238 | + |
|
239 | + public function admin_init() |
|
240 | + { |
|
241 | + } |
|
242 | + |
|
243 | + public function admin_notices() |
|
244 | + { |
|
245 | + } |
|
246 | + |
|
247 | + public function admin_footer_scripts() |
|
248 | + { |
|
249 | + } |
|
250 | + |
|
251 | + |
|
252 | + public function load_scripts_styles_default() |
|
253 | + { |
|
254 | + } |
|
255 | + |
|
256 | + |
|
257 | + public function load_scripts_styles_add_question() |
|
258 | + { |
|
259 | + $this->load_scripts_styles_forms(); |
|
260 | + wp_register_script('espresso_registration_form_single', |
|
261 | + REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
262 | + EVENT_ESPRESSO_VERSION, true); |
|
263 | + wp_enqueue_script('espresso_registration_form_single'); |
|
264 | + } |
|
265 | + |
|
266 | + public function load_scripts_styles_edit_question() |
|
267 | + { |
|
268 | + $this->load_scripts_styles_forms(); |
|
269 | + wp_register_script('espresso_registration_form_single', |
|
270 | + REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
271 | + EVENT_ESPRESSO_VERSION, true); |
|
272 | + wp_enqueue_script('espresso_registration_form_single'); |
|
273 | + } |
|
274 | + |
|
275 | + |
|
276 | + public function recaptcha_info_help_tab() |
|
277 | + { |
|
278 | + $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php'; |
|
279 | + EEH_Template::display_template($template, array()); |
|
280 | + } |
|
281 | + |
|
282 | + |
|
283 | + public function load_scripts_styles_forms() |
|
284 | + { |
|
285 | + //styles |
|
286 | + wp_enqueue_style('espresso-ui-theme'); |
|
287 | + //scripts |
|
288 | + wp_enqueue_script('ee_admin_js'); |
|
289 | + } |
|
290 | + |
|
291 | + |
|
292 | + protected function _set_list_table_views_default() |
|
293 | + { |
|
294 | + $this->_views = array( |
|
295 | + 'all' => array( |
|
296 | + 'slug' => 'all', |
|
297 | + 'label' => esc_html__('View All Questions', 'event_espresso'), |
|
298 | + 'count' => 0, |
|
299 | 299 | // 'bulk_action' => array( |
300 | 300 | // 'trash_questions' => esc_html__('Trash', 'event_espresso'), |
301 | 301 | // ) |
302 | - ), |
|
303 | - ); |
|
304 | - |
|
305 | - if (EE_Registry::instance()->CAP->current_user_can('ee_delete_questions', |
|
306 | - 'espresso_registration_form_trash_questions') |
|
307 | - ) { |
|
308 | - $this->_views['trash'] = array( |
|
309 | - 'slug' => 'trash', |
|
310 | - 'label' => esc_html__('Trash', 'event_espresso'), |
|
311 | - 'count' => 0, |
|
302 | + ), |
|
303 | + ); |
|
304 | + |
|
305 | + if (EE_Registry::instance()->CAP->current_user_can('ee_delete_questions', |
|
306 | + 'espresso_registration_form_trash_questions') |
|
307 | + ) { |
|
308 | + $this->_views['trash'] = array( |
|
309 | + 'slug' => 'trash', |
|
310 | + 'label' => esc_html__('Trash', 'event_espresso'), |
|
311 | + 'count' => 0, |
|
312 | 312 | // 'bulk_action' => array( |
313 | 313 | // 'delete_questions' => esc_html__('Delete Permanently', 'event_espresso'), |
314 | 314 | // 'restore_questions' => esc_html__('Restore', 'event_espresso'), |
315 | - ); |
|
316 | - } |
|
317 | - } |
|
318 | - |
|
319 | - /** |
|
320 | - * This just previews the question groups tab that comes in caffeinated. |
|
321 | - * |
|
322 | - * @return string html |
|
323 | - */ |
|
324 | - protected function _questions_groups_preview() |
|
325 | - { |
|
326 | - $this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso'); |
|
327 | - $this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="' . esc_attr__('Preview Question Groups Overview List Table screenshot', |
|
328 | - 'event_espresso') . '" />'; |
|
329 | - $this->_template_args['preview_text'] = '<strong>' . esc_html__('Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.', |
|
330 | - 'event_espresso') . '</strong>'; |
|
331 | - $this->display_admin_caf_preview_page('question_groups_tab'); |
|
332 | - } |
|
333 | - |
|
334 | - |
|
335 | - /** |
|
336 | - * Extracts the question field's values from the POST request to update or insert them |
|
337 | - * |
|
338 | - * @param \EEM_Base $model |
|
339 | - * @return array where each key is the name of a model's field/db column, and each value is its value. |
|
340 | - */ |
|
341 | - protected function _set_column_values_for(EEM_Base $model) |
|
342 | - { |
|
343 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
344 | - $set_column_values = array(); |
|
345 | - |
|
346 | - //some initial checks for proper values. |
|
347 | - //if QST_admin_only, then no matter what QST_required is we disable. |
|
348 | - if (! empty($this->_req_data['QST_admin_only'])) { |
|
349 | - $this->_req_data['QST_required'] = 0; |
|
350 | - } |
|
351 | - foreach ($model->field_settings() as $fieldName => $settings) { |
|
352 | - // basically if QSG_identifier is empty or not set |
|
353 | - if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) { |
|
354 | - $QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : ''; |
|
355 | - $set_column_values[$fieldName] = sanitize_title($QSG_name) . '-' . uniqid('', true); |
|
315 | + ); |
|
316 | + } |
|
317 | + } |
|
318 | + |
|
319 | + /** |
|
320 | + * This just previews the question groups tab that comes in caffeinated. |
|
321 | + * |
|
322 | + * @return string html |
|
323 | + */ |
|
324 | + protected function _questions_groups_preview() |
|
325 | + { |
|
326 | + $this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso'); |
|
327 | + $this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="' . esc_attr__('Preview Question Groups Overview List Table screenshot', |
|
328 | + 'event_espresso') . '" />'; |
|
329 | + $this->_template_args['preview_text'] = '<strong>' . esc_html__('Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.', |
|
330 | + 'event_espresso') . '</strong>'; |
|
331 | + $this->display_admin_caf_preview_page('question_groups_tab'); |
|
332 | + } |
|
333 | + |
|
334 | + |
|
335 | + /** |
|
336 | + * Extracts the question field's values from the POST request to update or insert them |
|
337 | + * |
|
338 | + * @param \EEM_Base $model |
|
339 | + * @return array where each key is the name of a model's field/db column, and each value is its value. |
|
340 | + */ |
|
341 | + protected function _set_column_values_for(EEM_Base $model) |
|
342 | + { |
|
343 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
344 | + $set_column_values = array(); |
|
345 | + |
|
346 | + //some initial checks for proper values. |
|
347 | + //if QST_admin_only, then no matter what QST_required is we disable. |
|
348 | + if (! empty($this->_req_data['QST_admin_only'])) { |
|
349 | + $this->_req_data['QST_required'] = 0; |
|
350 | + } |
|
351 | + foreach ($model->field_settings() as $fieldName => $settings) { |
|
352 | + // basically if QSG_identifier is empty or not set |
|
353 | + if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) { |
|
354 | + $QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : ''; |
|
355 | + $set_column_values[$fieldName] = sanitize_title($QSG_name) . '-' . uniqid('', true); |
|
356 | 356 | // dd($set_column_values); |
357 | - } //if the admin label is blank, use a slug version of the question text |
|
358 | - else if ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) { |
|
359 | - $QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : ''; |
|
360 | - $set_column_values[$fieldName] = sanitize_title(wp_trim_words($QST_text, 10)); |
|
361 | - } else if ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) { |
|
362 | - $set_column_values[$fieldName] = 0; |
|
363 | - } else if ($fieldName === 'QST_max') { |
|
364 | - $qst_system = EEM_Question::instance()->get_var( |
|
365 | - array( |
|
366 | - array( |
|
367 | - 'QST_ID' => isset($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0, |
|
368 | - ), |
|
369 | - ), |
|
370 | - 'QST_system'); |
|
371 | - $max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system); |
|
372 | - if (empty($this->_req_data['QST_max']) || |
|
373 | - $this->_req_data['QST_max'] > $max_max |
|
374 | - ) { |
|
375 | - $set_column_values[$fieldName] = $max_max; |
|
376 | - } |
|
377 | - } |
|
378 | - |
|
379 | - |
|
380 | - //only add a property to the array if it's not null (otherwise the model should just use the default value) |
|
381 | - if ( |
|
382 | - ! isset($set_column_values[$fieldName]) && |
|
383 | - isset($this->_req_data[$fieldName]) |
|
384 | - ) { |
|
385 | - $set_column_values[$fieldName] = $this->_req_data[$fieldName]; |
|
386 | - } |
|
387 | - |
|
388 | - } |
|
389 | - return $set_column_values;//validation fo this data to be performed by the model before insertion. |
|
390 | - } |
|
391 | - |
|
392 | - |
|
393 | - /** |
|
394 | - *_questions_overview_list_table |
|
395 | - */ |
|
396 | - protected function _questions_overview_list_table() |
|
397 | - { |
|
398 | - $this->_search_btn_label = esc_html__('Questions', 'event_espresso'); |
|
399 | - $this->display_admin_list_table_page_with_sidebar(); |
|
400 | - } |
|
401 | - |
|
402 | - |
|
403 | - /** |
|
404 | - * _edit_question |
|
405 | - */ |
|
406 | - protected function _edit_question() |
|
407 | - { |
|
408 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
409 | - $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID']) ? absint($this->_req_data['QST_ID']) : false; |
|
410 | - |
|
411 | - switch ($this->_req_action) { |
|
412 | - case 'add_question' : |
|
413 | - $this->_admin_page_title = esc_html__('Add Question', 'event_espresso'); |
|
414 | - break; |
|
415 | - case 'edit_question' : |
|
416 | - $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso'); |
|
417 | - break; |
|
418 | - default : |
|
419 | - $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action)); |
|
420 | - } |
|
421 | - |
|
422 | - // add PRC_ID to title if editing |
|
423 | - $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title; |
|
424 | - if ($ID) { |
|
425 | - $question = $this->_question_model->get_one_by_ID($ID); |
|
426 | - $additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID)); |
|
427 | - $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields); |
|
428 | - } else { |
|
429 | - $question = EE_Question::new_instance(); |
|
430 | - $question->set_order_to_latest(); |
|
431 | - $this->_set_add_edit_form_tags('insert_question'); |
|
432 | - } |
|
433 | - if( $question->system_ID() === EEM_Attendee::system_question_phone ){ |
|
434 | - $question_types = array_intersect_key( |
|
435 | - EEM_Question::instance()->allowed_question_types(), |
|
436 | - array_flip( |
|
437 | - array( |
|
438 | - EEM_Question::QST_type_text, |
|
439 | - EEM_Question::QST_type_us_phone |
|
440 | - ) |
|
441 | - ) |
|
442 | - ); |
|
443 | - } else { |
|
444 | - $question_types = $question->has_answers() ? $this->_question_model->question_types_in_same_category($question->type()) : $this->_question_model->allowed_question_types(); |
|
445 | - } |
|
446 | - $this->_template_args['QST_ID'] = $ID; |
|
447 | - $this->_template_args['question'] = $question; |
|
448 | - $this->_template_args['question_types'] = $question_types; |
|
449 | - $this->_template_args['max_max'] = EEM_Question::instance()->absolute_max_for_system_question( |
|
450 | - $question->system_ID() |
|
451 | - ); |
|
452 | - $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions(); |
|
453 | - $this->_set_publish_post_box_vars('id', $ID); |
|
454 | - $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
455 | - REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php', |
|
456 | - $this->_template_args, true |
|
457 | - ); |
|
458 | - |
|
459 | - // the details template wrapper |
|
460 | - $this->display_admin_page_with_sidebar(); |
|
461 | - } |
|
462 | - |
|
463 | - |
|
464 | - /** |
|
465 | - * @return string |
|
466 | - */ |
|
467 | - protected function _get_question_type_descriptions() |
|
468 | - { |
|
469 | - EE_Registry::instance()->load_helper('HTML'); |
|
470 | - $descriptions = ''; |
|
471 | - $question_type_descriptions = EEM_Question::instance()->question_descriptions(); |
|
472 | - foreach ($question_type_descriptions as $type => $question_type_description) { |
|
473 | - if ($type == 'HTML_TEXTAREA') { |
|
474 | - $html = new EE_Simple_HTML_Validation_Strategy(); |
|
475 | - $question_type_description .= sprintf( |
|
476 | - esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'), |
|
477 | - '<br/>', |
|
478 | - $html->get_list_of_allowed_tags() |
|
479 | - ); |
|
480 | - } |
|
481 | - $descriptions .= EEH_HTML::p( |
|
482 | - $question_type_description, |
|
483 | - 'question_type_description-' . $type, |
|
484 | - 'question_type_description description', |
|
485 | - 'display:none;' |
|
486 | - ); |
|
487 | - } |
|
488 | - return $descriptions; |
|
489 | - } |
|
490 | - |
|
491 | - |
|
492 | - /** |
|
493 | - * @param bool|true $new_question |
|
494 | - * @throws \EE_Error |
|
495 | - */ |
|
496 | - protected function _insert_or_update_question($new_question = true) |
|
497 | - { |
|
498 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
499 | - $set_column_values = $this->_set_column_values_for($this->_question_model); |
|
500 | - if ($new_question) { |
|
501 | - $question = EE_Question::new_instance($set_column_values); |
|
502 | - $action_desc = 'added'; |
|
503 | - } else { |
|
504 | - $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID'])); |
|
505 | - foreach($set_column_values as $field => $new_value) { |
|
506 | - $question->set($field, $new_value); |
|
507 | - } |
|
508 | - $action_desc = 'updated'; |
|
509 | - } |
|
510 | - $success = $question->save(); |
|
511 | - $ID = $question->ID(); |
|
512 | - if ($ID && $question->should_have_question_options()) { |
|
513 | - //save the related options |
|
514 | - //trash removed options, save old ones |
|
515 | - //get list of all options |
|
516 | - $options = $question->options(); |
|
517 | - if (! empty($options)) { |
|
518 | - foreach ($options as $option_ID => $option) { |
|
519 | - $option_req_index = $this->_get_option_req_data_index($option_ID); |
|
520 | - if ($option_req_index !== false) { |
|
521 | - $option->save($this->_req_data['question_options'][$option_req_index]); |
|
522 | - } else { |
|
523 | - //not found, remove it |
|
524 | - $option->delete(); |
|
525 | - } |
|
526 | - } |
|
527 | - } |
|
528 | - //save new related options |
|
529 | - foreach ($this->_req_data['question_options'] as $index => $option_req_data) { |
|
530 | - //skip $index that is from our sample |
|
531 | - if ( $index === 'xxcountxx' ) { |
|
532 | - continue; |
|
533 | - } |
|
534 | - //note we allow saving blank options. |
|
535 | - if (empty($option_req_data['QSO_ID']) |
|
536 | - ) {//no ID! save it! |
|
537 | - $new_option = EE_Question_Option::new_instance(array( |
|
538 | - 'QSO_value' => $option_req_data['QSO_value'], |
|
539 | - 'QSO_desc' => $option_req_data['QSO_desc'], |
|
540 | - 'QSO_order' => $option_req_data['QSO_order'], |
|
541 | - 'QST_ID' => $question->ID(), |
|
542 | - )); |
|
543 | - $new_option->save(); |
|
544 | - } |
|
545 | - } |
|
546 | - } |
|
547 | - $query_args = array('action' => 'edit_question', 'QST_ID' => $ID); |
|
548 | - if ($success !== false) { |
|
549 | - $msg = $new_question ? sprintf(esc_html__('The %s has been created', 'event_espresso'), |
|
550 | - $this->_question_model->item_name()) : sprintf(esc_html__('The %s has been updated', 'event_espresso'), |
|
551 | - $this->_question_model->item_name()); |
|
552 | - EE_Error::add_success($msg); |
|
553 | - } |
|
554 | - |
|
555 | - $this->_redirect_after_action(false, '', $action_desc, $query_args, true); |
|
556 | - } |
|
557 | - |
|
558 | - |
|
559 | - /** |
|
560 | - * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not |
|
561 | - * by ID |
|
562 | - * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously). |
|
563 | - * So, this function gets the index in that request data array called question_options. Returns FALSE if not found. |
|
564 | - * |
|
565 | - * @param int $ID of the question option to find |
|
566 | - * @return int index in question_options array if successful, FALSE if unsuccessful |
|
567 | - */ |
|
568 | - protected function _get_option_req_data_index($ID) |
|
569 | - { |
|
570 | - $req_data_for_question_options = $this->_req_data['question_options']; |
|
571 | - foreach ($req_data_for_question_options as $num => $option_data) { |
|
572 | - if (array_key_exists('QSO_ID', $option_data) && (int)$option_data['QSO_ID'] === $ID) { |
|
573 | - return $num; |
|
574 | - } |
|
575 | - } |
|
576 | - return false; |
|
577 | - } |
|
578 | - |
|
579 | - |
|
580 | - |
|
581 | - |
|
582 | - /***********/ |
|
583 | - /* QUERIES */ |
|
584 | - /** |
|
585 | - * For internal use in getting all the query parameters |
|
586 | - * (because it's pretty well the same between question, question groups, |
|
587 | - * and for both when searching for trashed and untrashed ones) |
|
588 | - * |
|
589 | - * @param EEM_Base $model either EEM_Question or EEM_Question_Group |
|
590 | - * @param int $per_page |
|
591 | - * @param int $current_page |
|
592 | - * @return array lik EEM_Base::get_all's $query_params parameter |
|
593 | - */ |
|
594 | - protected function get_query_params($model, $per_page = 10, $current_page = 10) |
|
595 | - { |
|
596 | - $query_params = array(); |
|
597 | - $offset = ($current_page - 1) * $per_page; |
|
598 | - $query_params['limit'] = array($offset, $per_page); |
|
599 | - $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order'] : 'ASC'; |
|
600 | - $orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order'; |
|
601 | - $field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby']; |
|
602 | - $query_params['order_by'] = array($field_to_order_by => $order); |
|
603 | - $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null; |
|
604 | - if (! empty($search_string)) { |
|
605 | - if ($model instanceof EEM_Question_Group) { |
|
606 | - $query_params[0] = array( |
|
607 | - 'OR' => array( |
|
608 | - 'QSG_name' => array('LIKE', "%$search_string%"), |
|
609 | - 'QSG_desc' => array('LIKE', "%$search_string%"), |
|
610 | - ), |
|
611 | - ); |
|
612 | - } else { |
|
613 | - $query_params[0] = array( |
|
614 | - 'QST_display_text' => array('LIKE', "%$search_string%"), |
|
615 | - ); |
|
616 | - } |
|
617 | - } |
|
618 | - |
|
619 | - //capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented) |
|
620 | - /*if ( $model instanceof EEM_Question_Group ) { |
|
357 | + } //if the admin label is blank, use a slug version of the question text |
|
358 | + else if ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) { |
|
359 | + $QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : ''; |
|
360 | + $set_column_values[$fieldName] = sanitize_title(wp_trim_words($QST_text, 10)); |
|
361 | + } else if ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) { |
|
362 | + $set_column_values[$fieldName] = 0; |
|
363 | + } else if ($fieldName === 'QST_max') { |
|
364 | + $qst_system = EEM_Question::instance()->get_var( |
|
365 | + array( |
|
366 | + array( |
|
367 | + 'QST_ID' => isset($this->_req_data['QST_ID']) ? $this->_req_data['QST_ID'] : 0, |
|
368 | + ), |
|
369 | + ), |
|
370 | + 'QST_system'); |
|
371 | + $max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system); |
|
372 | + if (empty($this->_req_data['QST_max']) || |
|
373 | + $this->_req_data['QST_max'] > $max_max |
|
374 | + ) { |
|
375 | + $set_column_values[$fieldName] = $max_max; |
|
376 | + } |
|
377 | + } |
|
378 | + |
|
379 | + |
|
380 | + //only add a property to the array if it's not null (otherwise the model should just use the default value) |
|
381 | + if ( |
|
382 | + ! isset($set_column_values[$fieldName]) && |
|
383 | + isset($this->_req_data[$fieldName]) |
|
384 | + ) { |
|
385 | + $set_column_values[$fieldName] = $this->_req_data[$fieldName]; |
|
386 | + } |
|
387 | + |
|
388 | + } |
|
389 | + return $set_column_values;//validation fo this data to be performed by the model before insertion. |
|
390 | + } |
|
391 | + |
|
392 | + |
|
393 | + /** |
|
394 | + *_questions_overview_list_table |
|
395 | + */ |
|
396 | + protected function _questions_overview_list_table() |
|
397 | + { |
|
398 | + $this->_search_btn_label = esc_html__('Questions', 'event_espresso'); |
|
399 | + $this->display_admin_list_table_page_with_sidebar(); |
|
400 | + } |
|
401 | + |
|
402 | + |
|
403 | + /** |
|
404 | + * _edit_question |
|
405 | + */ |
|
406 | + protected function _edit_question() |
|
407 | + { |
|
408 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
409 | + $ID = isset($this->_req_data['QST_ID']) && ! empty($this->_req_data['QST_ID']) ? absint($this->_req_data['QST_ID']) : false; |
|
410 | + |
|
411 | + switch ($this->_req_action) { |
|
412 | + case 'add_question' : |
|
413 | + $this->_admin_page_title = esc_html__('Add Question', 'event_espresso'); |
|
414 | + break; |
|
415 | + case 'edit_question' : |
|
416 | + $this->_admin_page_title = esc_html__('Edit Question', 'event_espresso'); |
|
417 | + break; |
|
418 | + default : |
|
419 | + $this->_admin_page_title = ucwords(str_replace('_', ' ', $this->_req_action)); |
|
420 | + } |
|
421 | + |
|
422 | + // add PRC_ID to title if editing |
|
423 | + $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title; |
|
424 | + if ($ID) { |
|
425 | + $question = $this->_question_model->get_one_by_ID($ID); |
|
426 | + $additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID)); |
|
427 | + $this->_set_add_edit_form_tags('update_question', $additional_hidden_fields); |
|
428 | + } else { |
|
429 | + $question = EE_Question::new_instance(); |
|
430 | + $question->set_order_to_latest(); |
|
431 | + $this->_set_add_edit_form_tags('insert_question'); |
|
432 | + } |
|
433 | + if( $question->system_ID() === EEM_Attendee::system_question_phone ){ |
|
434 | + $question_types = array_intersect_key( |
|
435 | + EEM_Question::instance()->allowed_question_types(), |
|
436 | + array_flip( |
|
437 | + array( |
|
438 | + EEM_Question::QST_type_text, |
|
439 | + EEM_Question::QST_type_us_phone |
|
440 | + ) |
|
441 | + ) |
|
442 | + ); |
|
443 | + } else { |
|
444 | + $question_types = $question->has_answers() ? $this->_question_model->question_types_in_same_category($question->type()) : $this->_question_model->allowed_question_types(); |
|
445 | + } |
|
446 | + $this->_template_args['QST_ID'] = $ID; |
|
447 | + $this->_template_args['question'] = $question; |
|
448 | + $this->_template_args['question_types'] = $question_types; |
|
449 | + $this->_template_args['max_max'] = EEM_Question::instance()->absolute_max_for_system_question( |
|
450 | + $question->system_ID() |
|
451 | + ); |
|
452 | + $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions(); |
|
453 | + $this->_set_publish_post_box_vars('id', $ID); |
|
454 | + $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
|
455 | + REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php', |
|
456 | + $this->_template_args, true |
|
457 | + ); |
|
458 | + |
|
459 | + // the details template wrapper |
|
460 | + $this->display_admin_page_with_sidebar(); |
|
461 | + } |
|
462 | + |
|
463 | + |
|
464 | + /** |
|
465 | + * @return string |
|
466 | + */ |
|
467 | + protected function _get_question_type_descriptions() |
|
468 | + { |
|
469 | + EE_Registry::instance()->load_helper('HTML'); |
|
470 | + $descriptions = ''; |
|
471 | + $question_type_descriptions = EEM_Question::instance()->question_descriptions(); |
|
472 | + foreach ($question_type_descriptions as $type => $question_type_description) { |
|
473 | + if ($type == 'HTML_TEXTAREA') { |
|
474 | + $html = new EE_Simple_HTML_Validation_Strategy(); |
|
475 | + $question_type_description .= sprintf( |
|
476 | + esc_html__('%1$s(allowed tags: %2$s)', 'event_espresso'), |
|
477 | + '<br/>', |
|
478 | + $html->get_list_of_allowed_tags() |
|
479 | + ); |
|
480 | + } |
|
481 | + $descriptions .= EEH_HTML::p( |
|
482 | + $question_type_description, |
|
483 | + 'question_type_description-' . $type, |
|
484 | + 'question_type_description description', |
|
485 | + 'display:none;' |
|
486 | + ); |
|
487 | + } |
|
488 | + return $descriptions; |
|
489 | + } |
|
490 | + |
|
491 | + |
|
492 | + /** |
|
493 | + * @param bool|true $new_question |
|
494 | + * @throws \EE_Error |
|
495 | + */ |
|
496 | + protected function _insert_or_update_question($new_question = true) |
|
497 | + { |
|
498 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
499 | + $set_column_values = $this->_set_column_values_for($this->_question_model); |
|
500 | + if ($new_question) { |
|
501 | + $question = EE_Question::new_instance($set_column_values); |
|
502 | + $action_desc = 'added'; |
|
503 | + } else { |
|
504 | + $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID'])); |
|
505 | + foreach($set_column_values as $field => $new_value) { |
|
506 | + $question->set($field, $new_value); |
|
507 | + } |
|
508 | + $action_desc = 'updated'; |
|
509 | + } |
|
510 | + $success = $question->save(); |
|
511 | + $ID = $question->ID(); |
|
512 | + if ($ID && $question->should_have_question_options()) { |
|
513 | + //save the related options |
|
514 | + //trash removed options, save old ones |
|
515 | + //get list of all options |
|
516 | + $options = $question->options(); |
|
517 | + if (! empty($options)) { |
|
518 | + foreach ($options as $option_ID => $option) { |
|
519 | + $option_req_index = $this->_get_option_req_data_index($option_ID); |
|
520 | + if ($option_req_index !== false) { |
|
521 | + $option->save($this->_req_data['question_options'][$option_req_index]); |
|
522 | + } else { |
|
523 | + //not found, remove it |
|
524 | + $option->delete(); |
|
525 | + } |
|
526 | + } |
|
527 | + } |
|
528 | + //save new related options |
|
529 | + foreach ($this->_req_data['question_options'] as $index => $option_req_data) { |
|
530 | + //skip $index that is from our sample |
|
531 | + if ( $index === 'xxcountxx' ) { |
|
532 | + continue; |
|
533 | + } |
|
534 | + //note we allow saving blank options. |
|
535 | + if (empty($option_req_data['QSO_ID']) |
|
536 | + ) {//no ID! save it! |
|
537 | + $new_option = EE_Question_Option::new_instance(array( |
|
538 | + 'QSO_value' => $option_req_data['QSO_value'], |
|
539 | + 'QSO_desc' => $option_req_data['QSO_desc'], |
|
540 | + 'QSO_order' => $option_req_data['QSO_order'], |
|
541 | + 'QST_ID' => $question->ID(), |
|
542 | + )); |
|
543 | + $new_option->save(); |
|
544 | + } |
|
545 | + } |
|
546 | + } |
|
547 | + $query_args = array('action' => 'edit_question', 'QST_ID' => $ID); |
|
548 | + if ($success !== false) { |
|
549 | + $msg = $new_question ? sprintf(esc_html__('The %s has been created', 'event_espresso'), |
|
550 | + $this->_question_model->item_name()) : sprintf(esc_html__('The %s has been updated', 'event_espresso'), |
|
551 | + $this->_question_model->item_name()); |
|
552 | + EE_Error::add_success($msg); |
|
553 | + } |
|
554 | + |
|
555 | + $this->_redirect_after_action(false, '', $action_desc, $query_args, true); |
|
556 | + } |
|
557 | + |
|
558 | + |
|
559 | + /** |
|
560 | + * Upon saving a question, there should be an array of 'question_options'. This array is index numerically, but not |
|
561 | + * by ID |
|
562 | + * (this is done because new question options don't have an ID, but we may want to add multiple simultaneously). |
|
563 | + * So, this function gets the index in that request data array called question_options. Returns FALSE if not found. |
|
564 | + * |
|
565 | + * @param int $ID of the question option to find |
|
566 | + * @return int index in question_options array if successful, FALSE if unsuccessful |
|
567 | + */ |
|
568 | + protected function _get_option_req_data_index($ID) |
|
569 | + { |
|
570 | + $req_data_for_question_options = $this->_req_data['question_options']; |
|
571 | + foreach ($req_data_for_question_options as $num => $option_data) { |
|
572 | + if (array_key_exists('QSO_ID', $option_data) && (int)$option_data['QSO_ID'] === $ID) { |
|
573 | + return $num; |
|
574 | + } |
|
575 | + } |
|
576 | + return false; |
|
577 | + } |
|
578 | + |
|
579 | + |
|
580 | + |
|
581 | + |
|
582 | + /***********/ |
|
583 | + /* QUERIES */ |
|
584 | + /** |
|
585 | + * For internal use in getting all the query parameters |
|
586 | + * (because it's pretty well the same between question, question groups, |
|
587 | + * and for both when searching for trashed and untrashed ones) |
|
588 | + * |
|
589 | + * @param EEM_Base $model either EEM_Question or EEM_Question_Group |
|
590 | + * @param int $per_page |
|
591 | + * @param int $current_page |
|
592 | + * @return array lik EEM_Base::get_all's $query_params parameter |
|
593 | + */ |
|
594 | + protected function get_query_params($model, $per_page = 10, $current_page = 10) |
|
595 | + { |
|
596 | + $query_params = array(); |
|
597 | + $offset = ($current_page - 1) * $per_page; |
|
598 | + $query_params['limit'] = array($offset, $per_page); |
|
599 | + $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order'] : 'ASC'; |
|
600 | + $orderby_field = $model instanceof EEM_Question ? 'QST_ID' : 'QSG_order'; |
|
601 | + $field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby']; |
|
602 | + $query_params['order_by'] = array($field_to_order_by => $order); |
|
603 | + $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null; |
|
604 | + if (! empty($search_string)) { |
|
605 | + if ($model instanceof EEM_Question_Group) { |
|
606 | + $query_params[0] = array( |
|
607 | + 'OR' => array( |
|
608 | + 'QSG_name' => array('LIKE', "%$search_string%"), |
|
609 | + 'QSG_desc' => array('LIKE', "%$search_string%"), |
|
610 | + ), |
|
611 | + ); |
|
612 | + } else { |
|
613 | + $query_params[0] = array( |
|
614 | + 'QST_display_text' => array('LIKE', "%$search_string%"), |
|
615 | + ); |
|
616 | + } |
|
617 | + } |
|
618 | + |
|
619 | + //capability checks (just leaving this commented out for reference because it illustrates some complicated query params that could be useful when fully implemented) |
|
620 | + /*if ( $model instanceof EEM_Question_Group ) { |
|
621 | 621 | if ( ! EE_Registry::instance()->CAP->current_user_can( 'edit_others_question_groups', 'espresso_registration_form_edit_question_group' ) ) { |
622 | 622 | $query_params[0] = array( |
623 | 623 | 'AND' => array( |
@@ -647,62 +647,62 @@ discard block |
||
647 | 647 | } |
648 | 648 | }/**/ |
649 | 649 | |
650 | - return $query_params; |
|
651 | - |
|
652 | - } |
|
653 | - |
|
654 | - |
|
655 | - /** |
|
656 | - * @param int $per_page |
|
657 | - * @param int $current_page |
|
658 | - * @param bool|false $count |
|
659 | - * @return \EE_Soft_Delete_Base_Class[]|int |
|
660 | - */ |
|
661 | - public function get_questions($per_page = 10, $current_page = 1, $count = false) |
|
662 | - { |
|
663 | - $QST = EEM_Question::instance(); |
|
664 | - $query_params = $this->get_query_params($QST, $per_page, $current_page); |
|
665 | - if ($count) { |
|
666 | - $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
667 | - $results = $QST->count($where); |
|
668 | - } else { |
|
669 | - $results = $QST->get_all($query_params); |
|
670 | - } |
|
671 | - return $results; |
|
672 | - |
|
673 | - } |
|
674 | - |
|
675 | - |
|
676 | - /** |
|
677 | - * @param $per_page |
|
678 | - * @param int $current_page |
|
679 | - * @param bool|false $count |
|
680 | - * @return \EE_Soft_Delete_Base_Class[]|int |
|
681 | - */ |
|
682 | - public function get_trashed_questions($per_page, $current_page = 1, $count = false) |
|
683 | - { |
|
684 | - $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page); |
|
685 | - $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
686 | - $questions = $count ? EEM_Question::instance()->count_deleted($where) : EEM_Question::instance()->get_all_deleted($query_params); |
|
687 | - return $questions; |
|
688 | - } |
|
689 | - |
|
690 | - |
|
691 | - /** |
|
692 | - * @param $per_page |
|
693 | - * @param int $current_page |
|
694 | - * @param bool|false $count |
|
695 | - * @return \EE_Soft_Delete_Base_Class[] |
|
696 | - */ |
|
697 | - public function get_question_groups($per_page, $current_page = 1, $count = false) |
|
698 | - { |
|
699 | - /** @type EEM_Question_Group $questionGroupModel */ |
|
700 | - $questionGroupModel = EEM_Question_Group::instance(); |
|
701 | - //note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items |
|
702 | - return $questionGroupModel->get_all( |
|
703 | - $this->get_query_params($questionGroupModel, $per_page, $current_page) |
|
704 | - ); |
|
705 | - } |
|
650 | + return $query_params; |
|
651 | + |
|
652 | + } |
|
653 | + |
|
654 | + |
|
655 | + /** |
|
656 | + * @param int $per_page |
|
657 | + * @param int $current_page |
|
658 | + * @param bool|false $count |
|
659 | + * @return \EE_Soft_Delete_Base_Class[]|int |
|
660 | + */ |
|
661 | + public function get_questions($per_page = 10, $current_page = 1, $count = false) |
|
662 | + { |
|
663 | + $QST = EEM_Question::instance(); |
|
664 | + $query_params = $this->get_query_params($QST, $per_page, $current_page); |
|
665 | + if ($count) { |
|
666 | + $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
667 | + $results = $QST->count($where); |
|
668 | + } else { |
|
669 | + $results = $QST->get_all($query_params); |
|
670 | + } |
|
671 | + return $results; |
|
672 | + |
|
673 | + } |
|
674 | + |
|
675 | + |
|
676 | + /** |
|
677 | + * @param $per_page |
|
678 | + * @param int $current_page |
|
679 | + * @param bool|false $count |
|
680 | + * @return \EE_Soft_Delete_Base_Class[]|int |
|
681 | + */ |
|
682 | + public function get_trashed_questions($per_page, $current_page = 1, $count = false) |
|
683 | + { |
|
684 | + $query_params = $this->get_query_params(EEM_Question::instance(), $per_page, $current_page); |
|
685 | + $where = isset($query_params[0]) ? array($query_params[0]) : array(); |
|
686 | + $questions = $count ? EEM_Question::instance()->count_deleted($where) : EEM_Question::instance()->get_all_deleted($query_params); |
|
687 | + return $questions; |
|
688 | + } |
|
689 | + |
|
690 | + |
|
691 | + /** |
|
692 | + * @param $per_page |
|
693 | + * @param int $current_page |
|
694 | + * @param bool|false $count |
|
695 | + * @return \EE_Soft_Delete_Base_Class[] |
|
696 | + */ |
|
697 | + public function get_question_groups($per_page, $current_page = 1, $count = false) |
|
698 | + { |
|
699 | + /** @type EEM_Question_Group $questionGroupModel */ |
|
700 | + $questionGroupModel = EEM_Question_Group::instance(); |
|
701 | + //note: this a subclass of EEM_Soft_Delete_Base, so this is actually only getting non-trashed items |
|
702 | + return $questionGroupModel->get_all( |
|
703 | + $this->get_query_params($questionGroupModel, $per_page, $current_page) |
|
704 | + ); |
|
705 | + } |
|
706 | 706 | |
707 | 707 | |
708 | 708 | } //ends Registration_Form_Admin_Page class |
@@ -1,5 +1,5 @@ discard block |
||
1 | 1 | <?php |
2 | -if (! defined('EVENT_ESPRESSO_VERSION')) { |
|
2 | +if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
|
3 | 3 | exit('NO direct script access allowed'); |
4 | 4 | } |
5 | 5 | |
@@ -66,8 +66,8 @@ discard block |
||
66 | 66 | */ |
67 | 67 | public function __construct($routing = true) |
68 | 68 | { |
69 | - require_once(EE_MODELS . 'EEM_Question.model.php'); |
|
70 | - require_once(EE_MODELS . 'EEM_Question_Group.model.php'); |
|
69 | + require_once(EE_MODELS.'EEM_Question.model.php'); |
|
70 | + require_once(EE_MODELS.'EEM_Question_Group.model.php'); |
|
71 | 71 | $this->_question_model = EEM_Question::instance(); |
72 | 72 | $this->_question_group_model = EEM_Question_Group::instance(); |
73 | 73 | parent::__construct($routing); |
@@ -232,7 +232,7 @@ discard block |
||
232 | 232 | public function load_scripts_styles() |
233 | 233 | { |
234 | 234 | wp_register_style('espresso_registration', |
235 | - REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.css', array(), EVENT_ESPRESSO_VERSION); |
|
235 | + REGISTRATION_FORM_ASSETS_URL.'espresso_registration_form_admin.css', array(), EVENT_ESPRESSO_VERSION); |
|
236 | 236 | wp_enqueue_style('espresso_registration'); |
237 | 237 | } |
238 | 238 | |
@@ -258,7 +258,7 @@ discard block |
||
258 | 258 | { |
259 | 259 | $this->load_scripts_styles_forms(); |
260 | 260 | wp_register_script('espresso_registration_form_single', |
261 | - REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
261 | + REGISTRATION_FORM_ASSETS_URL.'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
262 | 262 | EVENT_ESPRESSO_VERSION, true); |
263 | 263 | wp_enqueue_script('espresso_registration_form_single'); |
264 | 264 | } |
@@ -267,7 +267,7 @@ discard block |
||
267 | 267 | { |
268 | 268 | $this->load_scripts_styles_forms(); |
269 | 269 | wp_register_script('espresso_registration_form_single', |
270 | - REGISTRATION_FORM_ASSETS_URL . 'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
270 | + REGISTRATION_FORM_ASSETS_URL.'espresso_registration_form_admin.js', array('jquery-ui-sortable'), |
|
271 | 271 | EVENT_ESPRESSO_VERSION, true); |
272 | 272 | wp_enqueue_script('espresso_registration_form_single'); |
273 | 273 | } |
@@ -275,7 +275,7 @@ discard block |
||
275 | 275 | |
276 | 276 | public function recaptcha_info_help_tab() |
277 | 277 | { |
278 | - $template = REGISTRATION_FORM_TEMPLATE_PATH . 'recaptcha_info_help_tab.template.php'; |
|
278 | + $template = REGISTRATION_FORM_TEMPLATE_PATH.'recaptcha_info_help_tab.template.php'; |
|
279 | 279 | EEH_Template::display_template($template, array()); |
280 | 280 | } |
281 | 281 | |
@@ -324,10 +324,10 @@ discard block |
||
324 | 324 | protected function _questions_groups_preview() |
325 | 325 | { |
326 | 326 | $this->_admin_page_title = esc_html__('Question Groups (Preview)', 'event_espresso'); |
327 | - $this->_template_args['preview_img'] = '<img src="' . REGISTRATION_FORM_ASSETS_URL . 'caf_reg_form_preview.jpg" alt="' . esc_attr__('Preview Question Groups Overview List Table screenshot', |
|
328 | - 'event_espresso') . '" />'; |
|
329 | - $this->_template_args['preview_text'] = '<strong>' . esc_html__('Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.', |
|
330 | - 'event_espresso') . '</strong>'; |
|
327 | + $this->_template_args['preview_img'] = '<img src="'.REGISTRATION_FORM_ASSETS_URL.'caf_reg_form_preview.jpg" alt="'.esc_attr__('Preview Question Groups Overview List Table screenshot', |
|
328 | + 'event_espresso').'" />'; |
|
329 | + $this->_template_args['preview_text'] = '<strong>'.esc_html__('Question Groups is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Question Groups feature you are able to create new question groups, edit existing question groups, and create and edit new questions and add them to question groups.', |
|
330 | + 'event_espresso').'</strong>'; |
|
331 | 331 | $this->display_admin_caf_preview_page('question_groups_tab'); |
332 | 332 | } |
333 | 333 | |
@@ -345,20 +345,20 @@ discard block |
||
345 | 345 | |
346 | 346 | //some initial checks for proper values. |
347 | 347 | //if QST_admin_only, then no matter what QST_required is we disable. |
348 | - if (! empty($this->_req_data['QST_admin_only'])) { |
|
348 | + if ( ! empty($this->_req_data['QST_admin_only'])) { |
|
349 | 349 | $this->_req_data['QST_required'] = 0; |
350 | 350 | } |
351 | 351 | foreach ($model->field_settings() as $fieldName => $settings) { |
352 | 352 | // basically if QSG_identifier is empty or not set |
353 | 353 | if ($fieldName === 'QSG_identifier' && (isset($this->_req_data['QSG_identifier']) && empty($this->_req_data['QSG_identifier']))) { |
354 | 354 | $QSG_name = isset($this->_req_data['QSG_name']) ? $this->_req_data['QSG_name'] : ''; |
355 | - $set_column_values[$fieldName] = sanitize_title($QSG_name) . '-' . uniqid('', true); |
|
355 | + $set_column_values[$fieldName] = sanitize_title($QSG_name).'-'.uniqid('', true); |
|
356 | 356 | // dd($set_column_values); |
357 | 357 | } //if the admin label is blank, use a slug version of the question text |
358 | 358 | else if ($fieldName === 'QST_admin_label' && (isset($this->_req_data['QST_admin_label']) && empty($this->_req_data['QST_admin_label']))) { |
359 | 359 | $QST_text = isset($this->_req_data['QST_display_text']) ? $this->_req_data['QST_display_text'] : ''; |
360 | 360 | $set_column_values[$fieldName] = sanitize_title(wp_trim_words($QST_text, 10)); |
361 | - } else if ($fieldName === 'QST_admin_only' && (! isset($this->_req_data['QST_admin_only']))) { |
|
361 | + } else if ($fieldName === 'QST_admin_only' && ( ! isset($this->_req_data['QST_admin_only']))) { |
|
362 | 362 | $set_column_values[$fieldName] = 0; |
363 | 363 | } else if ($fieldName === 'QST_max') { |
364 | 364 | $qst_system = EEM_Question::instance()->get_var( |
@@ -368,7 +368,7 @@ discard block |
||
368 | 368 | ), |
369 | 369 | ), |
370 | 370 | 'QST_system'); |
371 | - $max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system); |
|
371 | + $max_max = EEM_Question::instance()->absolute_max_for_system_question($qst_system); |
|
372 | 372 | if (empty($this->_req_data['QST_max']) || |
373 | 373 | $this->_req_data['QST_max'] > $max_max |
374 | 374 | ) { |
@@ -386,7 +386,7 @@ discard block |
||
386 | 386 | } |
387 | 387 | |
388 | 388 | } |
389 | - return $set_column_values;//validation fo this data to be performed by the model before insertion. |
|
389 | + return $set_column_values; //validation fo this data to be performed by the model before insertion. |
|
390 | 390 | } |
391 | 391 | |
392 | 392 | |
@@ -420,7 +420,7 @@ discard block |
||
420 | 420 | } |
421 | 421 | |
422 | 422 | // add PRC_ID to title if editing |
423 | - $this->_admin_page_title = $ID ? $this->_admin_page_title . ' # ' . $ID : $this->_admin_page_title; |
|
423 | + $this->_admin_page_title = $ID ? $this->_admin_page_title.' # '.$ID : $this->_admin_page_title; |
|
424 | 424 | if ($ID) { |
425 | 425 | $question = $this->_question_model->get_one_by_ID($ID); |
426 | 426 | $additional_hidden_fields = array('QST_ID' => array('type' => 'hidden', 'value' => $ID)); |
@@ -430,7 +430,7 @@ discard block |
||
430 | 430 | $question->set_order_to_latest(); |
431 | 431 | $this->_set_add_edit_form_tags('insert_question'); |
432 | 432 | } |
433 | - if( $question->system_ID() === EEM_Attendee::system_question_phone ){ |
|
433 | + if ($question->system_ID() === EEM_Attendee::system_question_phone) { |
|
434 | 434 | $question_types = array_intersect_key( |
435 | 435 | EEM_Question::instance()->allowed_question_types(), |
436 | 436 | array_flip( |
@@ -452,7 +452,7 @@ discard block |
||
452 | 452 | $this->_template_args['question_type_descriptions'] = $this->_get_question_type_descriptions(); |
453 | 453 | $this->_set_publish_post_box_vars('id', $ID); |
454 | 454 | $this->_template_args['admin_page_content'] = EEH_Template::display_template( |
455 | - REGISTRATION_FORM_TEMPLATE_PATH . 'questions_main_meta_box.template.php', |
|
455 | + REGISTRATION_FORM_TEMPLATE_PATH.'questions_main_meta_box.template.php', |
|
456 | 456 | $this->_template_args, true |
457 | 457 | ); |
458 | 458 | |
@@ -480,7 +480,7 @@ discard block |
||
480 | 480 | } |
481 | 481 | $descriptions .= EEH_HTML::p( |
482 | 482 | $question_type_description, |
483 | - 'question_type_description-' . $type, |
|
483 | + 'question_type_description-'.$type, |
|
484 | 484 | 'question_type_description description', |
485 | 485 | 'display:none;' |
486 | 486 | ); |
@@ -501,8 +501,8 @@ discard block |
||
501 | 501 | $question = EE_Question::new_instance($set_column_values); |
502 | 502 | $action_desc = 'added'; |
503 | 503 | } else { |
504 | - $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID'])); |
|
505 | - foreach($set_column_values as $field => $new_value) { |
|
504 | + $question = EEM_Question::instance()->get_one_by_ID(absint($this->_req_data['QST_ID'])); |
|
505 | + foreach ($set_column_values as $field => $new_value) { |
|
506 | 506 | $question->set($field, $new_value); |
507 | 507 | } |
508 | 508 | $action_desc = 'updated'; |
@@ -513,8 +513,8 @@ discard block |
||
513 | 513 | //save the related options |
514 | 514 | //trash removed options, save old ones |
515 | 515 | //get list of all options |
516 | - $options = $question->options(); |
|
517 | - if (! empty($options)) { |
|
516 | + $options = $question->options(); |
|
517 | + if ( ! empty($options)) { |
|
518 | 518 | foreach ($options as $option_ID => $option) { |
519 | 519 | $option_req_index = $this->_get_option_req_data_index($option_ID); |
520 | 520 | if ($option_req_index !== false) { |
@@ -528,7 +528,7 @@ discard block |
||
528 | 528 | //save new related options |
529 | 529 | foreach ($this->_req_data['question_options'] as $index => $option_req_data) { |
530 | 530 | //skip $index that is from our sample |
531 | - if ( $index === 'xxcountxx' ) { |
|
531 | + if ($index === 'xxcountxx') { |
|
532 | 532 | continue; |
533 | 533 | } |
534 | 534 | //note we allow saving blank options. |
@@ -569,7 +569,7 @@ discard block |
||
569 | 569 | { |
570 | 570 | $req_data_for_question_options = $this->_req_data['question_options']; |
571 | 571 | foreach ($req_data_for_question_options as $num => $option_data) { |
572 | - if (array_key_exists('QSO_ID', $option_data) && (int)$option_data['QSO_ID'] === $ID) { |
|
572 | + if (array_key_exists('QSO_ID', $option_data) && (int) $option_data['QSO_ID'] === $ID) { |
|
573 | 573 | return $num; |
574 | 574 | } |
575 | 575 | } |
@@ -601,7 +601,7 @@ discard block |
||
601 | 601 | $field_to_order_by = empty($this->_req_data['orderby']) ? $orderby_field : $this->_req_data['orderby']; |
602 | 602 | $query_params['order_by'] = array($field_to_order_by => $order); |
603 | 603 | $search_string = array_key_exists('s', $this->_req_data) ? $this->_req_data['s'] : null; |
604 | - if (! empty($search_string)) { |
|
604 | + if ( ! empty($search_string)) { |
|
605 | 605 | if ($model instanceof EEM_Question_Group) { |
606 | 606 | $query_params[0] = array( |
607 | 607 | 'OR' => array( |
@@ -38,217 +38,217 @@ |
||
38 | 38 | * @since 4.0 |
39 | 39 | */ |
40 | 40 | if (function_exists('espresso_version')) { |
41 | - if (! function_exists('espresso_duplicate_plugin_error')) { |
|
42 | - /** |
|
43 | - * espresso_duplicate_plugin_error |
|
44 | - * displays if more than one version of EE is activated at the same time |
|
45 | - */ |
|
46 | - function espresso_duplicate_plugin_error() |
|
47 | - { |
|
48 | - ?> |
|
41 | + if (! function_exists('espresso_duplicate_plugin_error')) { |
|
42 | + /** |
|
43 | + * espresso_duplicate_plugin_error |
|
44 | + * displays if more than one version of EE is activated at the same time |
|
45 | + */ |
|
46 | + function espresso_duplicate_plugin_error() |
|
47 | + { |
|
48 | + ?> |
|
49 | 49 | <div class="error"> |
50 | 50 | <p> |
51 | 51 | <?php |
52 | - echo esc_html__( |
|
53 | - 'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.', |
|
54 | - 'event_espresso' |
|
55 | - ); ?> |
|
52 | + echo esc_html__( |
|
53 | + 'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.', |
|
54 | + 'event_espresso' |
|
55 | + ); ?> |
|
56 | 56 | </p> |
57 | 57 | </div> |
58 | 58 | <?php |
59 | - espresso_deactivate_plugin(plugin_basename(__FILE__)); |
|
60 | - } |
|
61 | - } |
|
62 | - add_action('admin_notices', 'espresso_duplicate_plugin_error', 1); |
|
59 | + espresso_deactivate_plugin(plugin_basename(__FILE__)); |
|
60 | + } |
|
61 | + } |
|
62 | + add_action('admin_notices', 'espresso_duplicate_plugin_error', 1); |
|
63 | 63 | |
64 | 64 | } else { |
65 | - define('EE_MIN_PHP_VER_REQUIRED', '5.3.9'); |
|
66 | - if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) { |
|
67 | - /** |
|
68 | - * espresso_minimum_php_version_error |
|
69 | - * |
|
70 | - * @return void |
|
71 | - */ |
|
72 | - function espresso_minimum_php_version_error() |
|
73 | - { |
|
74 | - ?> |
|
65 | + define('EE_MIN_PHP_VER_REQUIRED', '5.3.9'); |
|
66 | + if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) { |
|
67 | + /** |
|
68 | + * espresso_minimum_php_version_error |
|
69 | + * |
|
70 | + * @return void |
|
71 | + */ |
|
72 | + function espresso_minimum_php_version_error() |
|
73 | + { |
|
74 | + ?> |
|
75 | 75 | <div class="error"> |
76 | 76 | <p> |
77 | 77 | <?php |
78 | - printf( |
|
79 | - esc_html__( |
|
80 | - 'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.', |
|
81 | - 'event_espresso' |
|
82 | - ), |
|
83 | - EE_MIN_PHP_VER_REQUIRED, |
|
84 | - PHP_VERSION, |
|
85 | - '<br/>', |
|
86 | - '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>' |
|
87 | - ); |
|
88 | - ?> |
|
78 | + printf( |
|
79 | + esc_html__( |
|
80 | + 'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.', |
|
81 | + 'event_espresso' |
|
82 | + ), |
|
83 | + EE_MIN_PHP_VER_REQUIRED, |
|
84 | + PHP_VERSION, |
|
85 | + '<br/>', |
|
86 | + '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>' |
|
87 | + ); |
|
88 | + ?> |
|
89 | 89 | </p> |
90 | 90 | </div> |
91 | 91 | <?php |
92 | - espresso_deactivate_plugin(plugin_basename(__FILE__)); |
|
93 | - } |
|
92 | + espresso_deactivate_plugin(plugin_basename(__FILE__)); |
|
93 | + } |
|
94 | 94 | |
95 | - add_action('admin_notices', 'espresso_minimum_php_version_error', 1); |
|
96 | - } else { |
|
97 | - define('EVENT_ESPRESSO_MAIN_FILE', __FILE__); |
|
98 | - /** |
|
99 | - * espresso_version |
|
100 | - * Returns the plugin version |
|
101 | - * |
|
102 | - * @return string |
|
103 | - */ |
|
104 | - function espresso_version() |
|
105 | - { |
|
106 | - return apply_filters('FHEE__espresso__espresso_version', '4.9.52.rc.005'); |
|
107 | - } |
|
95 | + add_action('admin_notices', 'espresso_minimum_php_version_error', 1); |
|
96 | + } else { |
|
97 | + define('EVENT_ESPRESSO_MAIN_FILE', __FILE__); |
|
98 | + /** |
|
99 | + * espresso_version |
|
100 | + * Returns the plugin version |
|
101 | + * |
|
102 | + * @return string |
|
103 | + */ |
|
104 | + function espresso_version() |
|
105 | + { |
|
106 | + return apply_filters('FHEE__espresso__espresso_version', '4.9.52.rc.005'); |
|
107 | + } |
|
108 | 108 | |
109 | - /** |
|
110 | - * espresso_plugin_activation |
|
111 | - * adds a wp-option to indicate that EE has been activated via the WP admin plugins page |
|
112 | - */ |
|
113 | - function espresso_plugin_activation() |
|
114 | - { |
|
115 | - update_option('ee_espresso_activation', true); |
|
116 | - } |
|
109 | + /** |
|
110 | + * espresso_plugin_activation |
|
111 | + * adds a wp-option to indicate that EE has been activated via the WP admin plugins page |
|
112 | + */ |
|
113 | + function espresso_plugin_activation() |
|
114 | + { |
|
115 | + update_option('ee_espresso_activation', true); |
|
116 | + } |
|
117 | 117 | |
118 | - register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation'); |
|
119 | - /** |
|
120 | - * espresso_load_error_handling |
|
121 | - * this function loads EE's class for handling exceptions and errors |
|
122 | - */ |
|
123 | - function espresso_load_error_handling() |
|
124 | - { |
|
125 | - static $error_handling_loaded = false; |
|
126 | - if ($error_handling_loaded) { |
|
127 | - return; |
|
128 | - } |
|
129 | - // load debugging tools |
|
130 | - if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) { |
|
131 | - require_once EE_HELPERS . 'EEH_Debug_Tools.helper.php'; |
|
132 | - \EEH_Debug_Tools::instance(); |
|
133 | - } |
|
134 | - // load error handling |
|
135 | - if (is_readable(EE_CORE . 'EE_Error.core.php')) { |
|
136 | - require_once EE_CORE . 'EE_Error.core.php'; |
|
137 | - } else { |
|
138 | - wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso')); |
|
139 | - } |
|
140 | - $error_handling_loaded = true; |
|
141 | - } |
|
118 | + register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation'); |
|
119 | + /** |
|
120 | + * espresso_load_error_handling |
|
121 | + * this function loads EE's class for handling exceptions and errors |
|
122 | + */ |
|
123 | + function espresso_load_error_handling() |
|
124 | + { |
|
125 | + static $error_handling_loaded = false; |
|
126 | + if ($error_handling_loaded) { |
|
127 | + return; |
|
128 | + } |
|
129 | + // load debugging tools |
|
130 | + if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) { |
|
131 | + require_once EE_HELPERS . 'EEH_Debug_Tools.helper.php'; |
|
132 | + \EEH_Debug_Tools::instance(); |
|
133 | + } |
|
134 | + // load error handling |
|
135 | + if (is_readable(EE_CORE . 'EE_Error.core.php')) { |
|
136 | + require_once EE_CORE . 'EE_Error.core.php'; |
|
137 | + } else { |
|
138 | + wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso')); |
|
139 | + } |
|
140 | + $error_handling_loaded = true; |
|
141 | + } |
|
142 | 142 | |
143 | - /** |
|
144 | - * espresso_load_required |
|
145 | - * given a class name and path, this function will load that file or throw an exception |
|
146 | - * |
|
147 | - * @param string $classname |
|
148 | - * @param string $full_path_to_file |
|
149 | - * @throws EE_Error |
|
150 | - */ |
|
151 | - function espresso_load_required($classname, $full_path_to_file) |
|
152 | - { |
|
153 | - if (is_readable($full_path_to_file)) { |
|
154 | - require_once $full_path_to_file; |
|
155 | - } else { |
|
156 | - throw new \EE_Error ( |
|
157 | - sprintf( |
|
158 | - esc_html__( |
|
159 | - 'The %s class file could not be located or is not readable due to file permissions.', |
|
160 | - 'event_espresso' |
|
161 | - ), |
|
162 | - $classname |
|
163 | - ) |
|
164 | - ); |
|
165 | - } |
|
166 | - } |
|
143 | + /** |
|
144 | + * espresso_load_required |
|
145 | + * given a class name and path, this function will load that file or throw an exception |
|
146 | + * |
|
147 | + * @param string $classname |
|
148 | + * @param string $full_path_to_file |
|
149 | + * @throws EE_Error |
|
150 | + */ |
|
151 | + function espresso_load_required($classname, $full_path_to_file) |
|
152 | + { |
|
153 | + if (is_readable($full_path_to_file)) { |
|
154 | + require_once $full_path_to_file; |
|
155 | + } else { |
|
156 | + throw new \EE_Error ( |
|
157 | + sprintf( |
|
158 | + esc_html__( |
|
159 | + 'The %s class file could not be located or is not readable due to file permissions.', |
|
160 | + 'event_espresso' |
|
161 | + ), |
|
162 | + $classname |
|
163 | + ) |
|
164 | + ); |
|
165 | + } |
|
166 | + } |
|
167 | 167 | |
168 | - /** |
|
169 | - * @since 4.9.27 |
|
170 | - * @throws \EE_Error |
|
171 | - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
172 | - * @throws \EventEspresso\core\exceptions\InvalidEntityException |
|
173 | - * @throws \EventEspresso\core\exceptions\InvalidIdentifierException |
|
174 | - * @throws \EventEspresso\core\exceptions\InvalidClassException |
|
175 | - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
176 | - * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException |
|
177 | - * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException |
|
178 | - * @throws \OutOfBoundsException |
|
179 | - */ |
|
180 | - function bootstrap_espresso() |
|
181 | - { |
|
182 | - require_once __DIR__ . '/core/espresso_definitions.php'; |
|
183 | - try { |
|
184 | - espresso_load_error_handling(); |
|
185 | - espresso_load_required( |
|
186 | - 'EEH_Base', |
|
187 | - EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php' |
|
188 | - ); |
|
189 | - espresso_load_required( |
|
190 | - 'EEH_File', |
|
191 | - EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php' |
|
192 | - ); |
|
193 | - espresso_load_required( |
|
194 | - 'EEH_File', |
|
195 | - EE_CORE . 'helpers' . DS . 'EEH_File.helper.php' |
|
196 | - ); |
|
197 | - espresso_load_required( |
|
198 | - 'EEH_Array', |
|
199 | - EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php' |
|
200 | - ); |
|
201 | - // instantiate and configure PSR4 autoloader |
|
202 | - espresso_load_required( |
|
203 | - 'Psr4Autoloader', |
|
204 | - EE_CORE . 'Psr4Autoloader.php' |
|
205 | - ); |
|
206 | - espresso_load_required( |
|
207 | - 'EE_Psr4AutoloaderInit', |
|
208 | - EE_CORE . 'EE_Psr4AutoloaderInit.core.php' |
|
209 | - ); |
|
210 | - $AutoloaderInit = new EE_Psr4AutoloaderInit(); |
|
211 | - $AutoloaderInit->initializeAutoloader(); |
|
212 | - espresso_load_required( |
|
213 | - 'EE_Request', |
|
214 | - EE_CORE . 'request_stack' . DS . 'EE_Request.core.php' |
|
215 | - ); |
|
216 | - espresso_load_required( |
|
217 | - 'EE_Response', |
|
218 | - EE_CORE . 'request_stack' . DS . 'EE_Response.core.php' |
|
219 | - ); |
|
220 | - espresso_load_required( |
|
221 | - 'EE_Bootstrap', |
|
222 | - EE_CORE . 'EE_Bootstrap.core.php' |
|
223 | - ); |
|
224 | - // bootstrap EE and the request stack |
|
225 | - new EE_Bootstrap( |
|
226 | - new EE_Request($_GET, $_POST, $_COOKIE), |
|
227 | - new EE_Response() |
|
228 | - ); |
|
229 | - } catch (Exception $e) { |
|
230 | - require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php'; |
|
231 | - new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e); |
|
232 | - } |
|
233 | - } |
|
234 | - bootstrap_espresso(); |
|
235 | - } |
|
168 | + /** |
|
169 | + * @since 4.9.27 |
|
170 | + * @throws \EE_Error |
|
171 | + * @throws \EventEspresso\core\exceptions\InvalidInterfaceException |
|
172 | + * @throws \EventEspresso\core\exceptions\InvalidEntityException |
|
173 | + * @throws \EventEspresso\core\exceptions\InvalidIdentifierException |
|
174 | + * @throws \EventEspresso\core\exceptions\InvalidClassException |
|
175 | + * @throws \EventEspresso\core\exceptions\InvalidDataTypeException |
|
176 | + * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException |
|
177 | + * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException |
|
178 | + * @throws \OutOfBoundsException |
|
179 | + */ |
|
180 | + function bootstrap_espresso() |
|
181 | + { |
|
182 | + require_once __DIR__ . '/core/espresso_definitions.php'; |
|
183 | + try { |
|
184 | + espresso_load_error_handling(); |
|
185 | + espresso_load_required( |
|
186 | + 'EEH_Base', |
|
187 | + EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php' |
|
188 | + ); |
|
189 | + espresso_load_required( |
|
190 | + 'EEH_File', |
|
191 | + EE_CORE . 'interfaces' . DS . 'EEHI_File.interface.php' |
|
192 | + ); |
|
193 | + espresso_load_required( |
|
194 | + 'EEH_File', |
|
195 | + EE_CORE . 'helpers' . DS . 'EEH_File.helper.php' |
|
196 | + ); |
|
197 | + espresso_load_required( |
|
198 | + 'EEH_Array', |
|
199 | + EE_CORE . 'helpers' . DS . 'EEH_Array.helper.php' |
|
200 | + ); |
|
201 | + // instantiate and configure PSR4 autoloader |
|
202 | + espresso_load_required( |
|
203 | + 'Psr4Autoloader', |
|
204 | + EE_CORE . 'Psr4Autoloader.php' |
|
205 | + ); |
|
206 | + espresso_load_required( |
|
207 | + 'EE_Psr4AutoloaderInit', |
|
208 | + EE_CORE . 'EE_Psr4AutoloaderInit.core.php' |
|
209 | + ); |
|
210 | + $AutoloaderInit = new EE_Psr4AutoloaderInit(); |
|
211 | + $AutoloaderInit->initializeAutoloader(); |
|
212 | + espresso_load_required( |
|
213 | + 'EE_Request', |
|
214 | + EE_CORE . 'request_stack' . DS . 'EE_Request.core.php' |
|
215 | + ); |
|
216 | + espresso_load_required( |
|
217 | + 'EE_Response', |
|
218 | + EE_CORE . 'request_stack' . DS . 'EE_Response.core.php' |
|
219 | + ); |
|
220 | + espresso_load_required( |
|
221 | + 'EE_Bootstrap', |
|
222 | + EE_CORE . 'EE_Bootstrap.core.php' |
|
223 | + ); |
|
224 | + // bootstrap EE and the request stack |
|
225 | + new EE_Bootstrap( |
|
226 | + new EE_Request($_GET, $_POST, $_COOKIE), |
|
227 | + new EE_Response() |
|
228 | + ); |
|
229 | + } catch (Exception $e) { |
|
230 | + require_once EE_CORE . 'exceptions' . DS . 'ExceptionStackTraceDisplay.php'; |
|
231 | + new EventEspresso\core\exceptions\ExceptionStackTraceDisplay($e); |
|
232 | + } |
|
233 | + } |
|
234 | + bootstrap_espresso(); |
|
235 | + } |
|
236 | 236 | } |
237 | 237 | if (! function_exists('espresso_deactivate_plugin')) { |
238 | - /** |
|
239 | - * deactivate_plugin |
|
240 | - * usage: espresso_deactivate_plugin( plugin_basename( __FILE__ )); |
|
241 | - * |
|
242 | - * @access public |
|
243 | - * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file |
|
244 | - * @return void |
|
245 | - */ |
|
246 | - function espresso_deactivate_plugin($plugin_basename = '') |
|
247 | - { |
|
248 | - if (! function_exists('deactivate_plugins')) { |
|
249 | - require_once ABSPATH . 'wp-admin/includes/plugin.php'; |
|
250 | - } |
|
251 | - unset($_GET['activate'], $_REQUEST['activate']); |
|
252 | - deactivate_plugins($plugin_basename); |
|
253 | - } |
|
238 | + /** |
|
239 | + * deactivate_plugin |
|
240 | + * usage: espresso_deactivate_plugin( plugin_basename( __FILE__ )); |
|
241 | + * |
|
242 | + * @access public |
|
243 | + * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file |
|
244 | + * @return void |
|
245 | + */ |
|
246 | + function espresso_deactivate_plugin($plugin_basename = '') |
|
247 | + { |
|
248 | + if (! function_exists('deactivate_plugins')) { |
|
249 | + require_once ABSPATH . 'wp-admin/includes/plugin.php'; |
|
250 | + } |
|
251 | + unset($_GET['activate'], $_REQUEST['activate']); |
|
252 | + deactivate_plugins($plugin_basename); |
|
253 | + } |
|
254 | 254 | } |
@@ -20,1198 +20,1198 @@ discard block |
||
20 | 20 | class EE_Session implements SessionIdentifierInterface |
21 | 21 | { |
22 | 22 | |
23 | - const session_id_prefix = 'ee_ssn_'; |
|
24 | - |
|
25 | - const hash_check_prefix = 'ee_shc_'; |
|
26 | - |
|
27 | - const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
28 | - |
|
29 | - /** |
|
30 | - * instance of the EE_Session object |
|
31 | - * |
|
32 | - * @var EE_Session |
|
33 | - */ |
|
34 | - private static $_instance; |
|
35 | - |
|
36 | - /** |
|
37 | - * @var CacheStorageInterface $cache_storage |
|
38 | - */ |
|
39 | - protected $cache_storage; |
|
40 | - |
|
41 | - /** |
|
42 | - * EE_Encryption object |
|
43 | - * |
|
44 | - * @var EE_Encryption |
|
45 | - */ |
|
46 | - protected $encryption; |
|
47 | - |
|
48 | - /** |
|
49 | - * the session id |
|
50 | - * |
|
51 | - * @var string |
|
52 | - */ |
|
53 | - private $_sid; |
|
54 | - |
|
55 | - /** |
|
56 | - * session id salt |
|
57 | - * |
|
58 | - * @var string |
|
59 | - */ |
|
60 | - private $_sid_salt; |
|
61 | - |
|
62 | - /** |
|
63 | - * session data |
|
64 | - * |
|
65 | - * @var array |
|
66 | - */ |
|
67 | - private $_session_data = array(); |
|
68 | - |
|
69 | - /** |
|
70 | - * how long an EE session lasts |
|
71 | - * default session lifespan of 2 hours (for not so instant IPNs) |
|
72 | - * |
|
73 | - * @var int |
|
74 | - */ |
|
75 | - private $_lifespan; |
|
76 | - |
|
77 | - /** |
|
78 | - * session expiration time as Unix timestamp in GMT |
|
79 | - * |
|
80 | - * @var int |
|
81 | - */ |
|
82 | - private $_expiration; |
|
83 | - |
|
84 | - /** |
|
85 | - * whether or not session has expired at some point |
|
86 | - * |
|
87 | - * @var boolean |
|
88 | - */ |
|
89 | - private $_expired = false; |
|
90 | - |
|
91 | - /** |
|
92 | - * current time as Unix timestamp in GMT |
|
93 | - * |
|
94 | - * @var int |
|
95 | - */ |
|
96 | - private $_time; |
|
97 | - |
|
98 | - /** |
|
99 | - * whether to encrypt session data |
|
100 | - * |
|
101 | - * @var bool |
|
102 | - */ |
|
103 | - private $_use_encryption; |
|
104 | - |
|
105 | - /** |
|
106 | - * well... according to the server... |
|
107 | - * |
|
108 | - * @var null |
|
109 | - */ |
|
110 | - private $_user_agent; |
|
111 | - |
|
112 | - /** |
|
113 | - * do you really trust the server ? |
|
114 | - * |
|
115 | - * @var null |
|
116 | - */ |
|
117 | - private $_ip_address; |
|
118 | - |
|
119 | - /** |
|
120 | - * current WP user_id |
|
121 | - * |
|
122 | - * @var null |
|
123 | - */ |
|
124 | - private $_wp_user_id; |
|
125 | - |
|
126 | - /** |
|
127 | - * array for defining default session vars |
|
128 | - * |
|
129 | - * @var array |
|
130 | - */ |
|
131 | - private $_default_session_vars = array( |
|
132 | - 'id' => null, |
|
133 | - 'user_id' => null, |
|
134 | - 'ip_address' => null, |
|
135 | - 'user_agent' => null, |
|
136 | - 'init_access' => null, |
|
137 | - 'last_access' => null, |
|
138 | - 'expiration' => null, |
|
139 | - 'pages_visited' => array(), |
|
140 | - ); |
|
141 | - |
|
142 | - /** |
|
143 | - * timestamp for when last garbage collection cycle was performed |
|
144 | - * |
|
145 | - * @var int $_last_gc |
|
146 | - */ |
|
147 | - private $_last_gc; |
|
148 | - |
|
149 | - /** |
|
150 | - * @var EE_Request |
|
151 | - */ |
|
152 | - protected $request; |
|
153 | - |
|
154 | - |
|
155 | - |
|
156 | - /** |
|
157 | - * @singleton method used to instantiate class object |
|
158 | - * @param CacheStorageInterface $cache_storage |
|
159 | - * @param EE_Request $request |
|
160 | - * @param EE_Encryption $encryption |
|
161 | - * @return EE_Session |
|
162 | - * @throws InvalidArgumentException |
|
163 | - * @throws InvalidDataTypeException |
|
164 | - * @throws InvalidInterfaceException |
|
165 | - */ |
|
166 | - public static function instance( |
|
167 | - CacheStorageInterface $cache_storage = null, |
|
168 | - EE_Request $request = null, |
|
169 | - EE_Encryption $encryption = null |
|
170 | - ) { |
|
171 | - // check if class object is instantiated |
|
172 | - // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
173 | - // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
174 | - if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) { |
|
175 | - self::$_instance = new self($cache_storage, $request, $encryption); |
|
176 | - } |
|
177 | - return self::$_instance; |
|
178 | - } |
|
179 | - |
|
180 | - |
|
181 | - |
|
182 | - /** |
|
183 | - * protected constructor to prevent direct creation |
|
184 | - * |
|
185 | - * @param CacheStorageInterface $cache_storage |
|
186 | - * @param EE_Request $request |
|
187 | - * @param EE_Encryption $encryption |
|
188 | - * @throws InvalidArgumentException |
|
189 | - * @throws InvalidDataTypeException |
|
190 | - * @throws InvalidInterfaceException |
|
191 | - */ |
|
192 | - protected function __construct( |
|
193 | - CacheStorageInterface $cache_storage, |
|
194 | - EE_Request $request, |
|
195 | - EE_Encryption $encryption = null |
|
196 | - ) { |
|
197 | - // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
198 | - if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
199 | - return; |
|
200 | - } |
|
201 | - $this->request = $request; |
|
202 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
203 | - if (! defined('ESPRESSO_SESSION')) { |
|
204 | - define('ESPRESSO_SESSION', true); |
|
205 | - } |
|
206 | - // default session lifespan in seconds |
|
207 | - $this->_lifespan = apply_filters( |
|
208 | - 'FHEE__EE_Session__construct___lifespan', |
|
209 | - 60 * MINUTE_IN_SECONDS |
|
210 | - ) + 1; |
|
211 | - /* |
|
23 | + const session_id_prefix = 'ee_ssn_'; |
|
24 | + |
|
25 | + const hash_check_prefix = 'ee_shc_'; |
|
26 | + |
|
27 | + const OPTION_NAME_SETTINGS = 'ee_session_settings'; |
|
28 | + |
|
29 | + /** |
|
30 | + * instance of the EE_Session object |
|
31 | + * |
|
32 | + * @var EE_Session |
|
33 | + */ |
|
34 | + private static $_instance; |
|
35 | + |
|
36 | + /** |
|
37 | + * @var CacheStorageInterface $cache_storage |
|
38 | + */ |
|
39 | + protected $cache_storage; |
|
40 | + |
|
41 | + /** |
|
42 | + * EE_Encryption object |
|
43 | + * |
|
44 | + * @var EE_Encryption |
|
45 | + */ |
|
46 | + protected $encryption; |
|
47 | + |
|
48 | + /** |
|
49 | + * the session id |
|
50 | + * |
|
51 | + * @var string |
|
52 | + */ |
|
53 | + private $_sid; |
|
54 | + |
|
55 | + /** |
|
56 | + * session id salt |
|
57 | + * |
|
58 | + * @var string |
|
59 | + */ |
|
60 | + private $_sid_salt; |
|
61 | + |
|
62 | + /** |
|
63 | + * session data |
|
64 | + * |
|
65 | + * @var array |
|
66 | + */ |
|
67 | + private $_session_data = array(); |
|
68 | + |
|
69 | + /** |
|
70 | + * how long an EE session lasts |
|
71 | + * default session lifespan of 2 hours (for not so instant IPNs) |
|
72 | + * |
|
73 | + * @var int |
|
74 | + */ |
|
75 | + private $_lifespan; |
|
76 | + |
|
77 | + /** |
|
78 | + * session expiration time as Unix timestamp in GMT |
|
79 | + * |
|
80 | + * @var int |
|
81 | + */ |
|
82 | + private $_expiration; |
|
83 | + |
|
84 | + /** |
|
85 | + * whether or not session has expired at some point |
|
86 | + * |
|
87 | + * @var boolean |
|
88 | + */ |
|
89 | + private $_expired = false; |
|
90 | + |
|
91 | + /** |
|
92 | + * current time as Unix timestamp in GMT |
|
93 | + * |
|
94 | + * @var int |
|
95 | + */ |
|
96 | + private $_time; |
|
97 | + |
|
98 | + /** |
|
99 | + * whether to encrypt session data |
|
100 | + * |
|
101 | + * @var bool |
|
102 | + */ |
|
103 | + private $_use_encryption; |
|
104 | + |
|
105 | + /** |
|
106 | + * well... according to the server... |
|
107 | + * |
|
108 | + * @var null |
|
109 | + */ |
|
110 | + private $_user_agent; |
|
111 | + |
|
112 | + /** |
|
113 | + * do you really trust the server ? |
|
114 | + * |
|
115 | + * @var null |
|
116 | + */ |
|
117 | + private $_ip_address; |
|
118 | + |
|
119 | + /** |
|
120 | + * current WP user_id |
|
121 | + * |
|
122 | + * @var null |
|
123 | + */ |
|
124 | + private $_wp_user_id; |
|
125 | + |
|
126 | + /** |
|
127 | + * array for defining default session vars |
|
128 | + * |
|
129 | + * @var array |
|
130 | + */ |
|
131 | + private $_default_session_vars = array( |
|
132 | + 'id' => null, |
|
133 | + 'user_id' => null, |
|
134 | + 'ip_address' => null, |
|
135 | + 'user_agent' => null, |
|
136 | + 'init_access' => null, |
|
137 | + 'last_access' => null, |
|
138 | + 'expiration' => null, |
|
139 | + 'pages_visited' => array(), |
|
140 | + ); |
|
141 | + |
|
142 | + /** |
|
143 | + * timestamp for when last garbage collection cycle was performed |
|
144 | + * |
|
145 | + * @var int $_last_gc |
|
146 | + */ |
|
147 | + private $_last_gc; |
|
148 | + |
|
149 | + /** |
|
150 | + * @var EE_Request |
|
151 | + */ |
|
152 | + protected $request; |
|
153 | + |
|
154 | + |
|
155 | + |
|
156 | + /** |
|
157 | + * @singleton method used to instantiate class object |
|
158 | + * @param CacheStorageInterface $cache_storage |
|
159 | + * @param EE_Request $request |
|
160 | + * @param EE_Encryption $encryption |
|
161 | + * @return EE_Session |
|
162 | + * @throws InvalidArgumentException |
|
163 | + * @throws InvalidDataTypeException |
|
164 | + * @throws InvalidInterfaceException |
|
165 | + */ |
|
166 | + public static function instance( |
|
167 | + CacheStorageInterface $cache_storage = null, |
|
168 | + EE_Request $request = null, |
|
169 | + EE_Encryption $encryption = null |
|
170 | + ) { |
|
171 | + // check if class object is instantiated |
|
172 | + // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: |
|
173 | + // add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
174 | + if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) { |
|
175 | + self::$_instance = new self($cache_storage, $request, $encryption); |
|
176 | + } |
|
177 | + return self::$_instance; |
|
178 | + } |
|
179 | + |
|
180 | + |
|
181 | + |
|
182 | + /** |
|
183 | + * protected constructor to prevent direct creation |
|
184 | + * |
|
185 | + * @param CacheStorageInterface $cache_storage |
|
186 | + * @param EE_Request $request |
|
187 | + * @param EE_Encryption $encryption |
|
188 | + * @throws InvalidArgumentException |
|
189 | + * @throws InvalidDataTypeException |
|
190 | + * @throws InvalidInterfaceException |
|
191 | + */ |
|
192 | + protected function __construct( |
|
193 | + CacheStorageInterface $cache_storage, |
|
194 | + EE_Request $request, |
|
195 | + EE_Encryption $encryption = null |
|
196 | + ) { |
|
197 | + // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' ); |
|
198 | + if (! apply_filters('FHEE_load_EE_Session', true)) { |
|
199 | + return; |
|
200 | + } |
|
201 | + $this->request = $request; |
|
202 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
203 | + if (! defined('ESPRESSO_SESSION')) { |
|
204 | + define('ESPRESSO_SESSION', true); |
|
205 | + } |
|
206 | + // default session lifespan in seconds |
|
207 | + $this->_lifespan = apply_filters( |
|
208 | + 'FHEE__EE_Session__construct___lifespan', |
|
209 | + 60 * MINUTE_IN_SECONDS |
|
210 | + ) + 1; |
|
211 | + /* |
|
212 | 212 | * do something like the following to adjust the session lifespan: |
213 | 213 | * public static function session_lifespan() { |
214 | 214 | * return 15 * MINUTE_IN_SECONDS; |
215 | 215 | * } |
216 | 216 | */ |
217 | - // retrieve session options from db |
|
218 | - $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
219 | - if (! empty($session_settings)) { |
|
220 | - // cycle though existing session options |
|
221 | - foreach ($session_settings as $var_name => $session_setting) { |
|
222 | - // set values for class properties |
|
223 | - $var_name = '_' . $var_name; |
|
224 | - $this->{$var_name} = $session_setting; |
|
225 | - } |
|
226 | - } |
|
227 | - $this->cache_storage = $cache_storage; |
|
228 | - // are we using encryption? |
|
229 | - $this->_use_encryption = $encryption instanceof EE_Encryption |
|
230 | - && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
231 | - // \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__); |
|
232 | - // encrypt data via: $this->encryption->encrypt(); |
|
233 | - $this->encryption = $encryption; |
|
234 | - // filter hook allows outside functions/classes/plugins to change default empty cart |
|
235 | - $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
236 | - array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
237 | - // apply default session vars |
|
238 | - $this->_set_defaults(); |
|
239 | - add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
240 | - // check request for 'clear_session' param |
|
241 | - add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
242 | - // once everything is all said and done, |
|
243 | - add_action('shutdown', array($this, 'update'), 100); |
|
244 | - add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
245 | - $this->configure_garbage_collection_filters(); |
|
246 | - } |
|
247 | - |
|
248 | - |
|
249 | - |
|
250 | - /** |
|
251 | - * @return void |
|
252 | - * @throws EE_Error |
|
253 | - * @throws InvalidArgumentException |
|
254 | - * @throws InvalidDataTypeException |
|
255 | - * @throws InvalidInterfaceException |
|
256 | - * @throws InvalidSessionDataException |
|
257 | - */ |
|
258 | - public function open_session() |
|
259 | - { |
|
260 | - // check for existing session and retrieve it from db |
|
261 | - if (! $this->_espresso_session()) { |
|
262 | - // or just start a new one |
|
263 | - $this->_create_espresso_session(); |
|
264 | - } |
|
265 | - } |
|
266 | - |
|
267 | - |
|
268 | - |
|
269 | - /** |
|
270 | - * @return bool |
|
271 | - */ |
|
272 | - public function expired() |
|
273 | - { |
|
274 | - return $this->_expired; |
|
275 | - } |
|
276 | - |
|
277 | - |
|
278 | - |
|
279 | - /** |
|
280 | - * @return void |
|
281 | - */ |
|
282 | - public function reset_expired() |
|
283 | - { |
|
284 | - $this->_expired = false; |
|
285 | - } |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * @return int |
|
290 | - */ |
|
291 | - public function expiration() |
|
292 | - { |
|
293 | - return $this->_expiration; |
|
294 | - } |
|
295 | - |
|
296 | - |
|
297 | - |
|
298 | - /** |
|
299 | - * @return int |
|
300 | - */ |
|
301 | - public function extension() |
|
302 | - { |
|
303 | - return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
304 | - } |
|
305 | - |
|
306 | - |
|
307 | - |
|
308 | - /** |
|
309 | - * @param int $time number of seconds to add to session expiration |
|
310 | - */ |
|
311 | - public function extend_expiration($time = 0) |
|
312 | - { |
|
313 | - $time = $time ? $time : $this->extension(); |
|
314 | - $this->_expiration += absint($time); |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - |
|
319 | - /** |
|
320 | - * @return int |
|
321 | - */ |
|
322 | - public function lifespan() |
|
323 | - { |
|
324 | - return $this->_lifespan; |
|
325 | - } |
|
326 | - |
|
327 | - |
|
328 | - |
|
329 | - /** |
|
330 | - * This just sets some defaults for the _session data property |
|
331 | - * |
|
332 | - * @access private |
|
333 | - * @return void |
|
334 | - */ |
|
335 | - private function _set_defaults() |
|
336 | - { |
|
337 | - // set some defaults |
|
338 | - foreach ($this->_default_session_vars as $key => $default_var) { |
|
339 | - if (is_array($default_var)) { |
|
340 | - $this->_session_data[ $key ] = array(); |
|
341 | - } else { |
|
342 | - $this->_session_data[ $key ] = ''; |
|
343 | - } |
|
344 | - } |
|
345 | - } |
|
217 | + // retrieve session options from db |
|
218 | + $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
219 | + if (! empty($session_settings)) { |
|
220 | + // cycle though existing session options |
|
221 | + foreach ($session_settings as $var_name => $session_setting) { |
|
222 | + // set values for class properties |
|
223 | + $var_name = '_' . $var_name; |
|
224 | + $this->{$var_name} = $session_setting; |
|
225 | + } |
|
226 | + } |
|
227 | + $this->cache_storage = $cache_storage; |
|
228 | + // are we using encryption? |
|
229 | + $this->_use_encryption = $encryption instanceof EE_Encryption |
|
230 | + && EE_Registry::instance()->CFG->admin->encode_session_data(); |
|
231 | + // \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__); |
|
232 | + // encrypt data via: $this->encryption->encrypt(); |
|
233 | + $this->encryption = $encryption; |
|
234 | + // filter hook allows outside functions/classes/plugins to change default empty cart |
|
235 | + $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array()); |
|
236 | + array_merge($this->_default_session_vars, $extra_default_session_vars); |
|
237 | + // apply default session vars |
|
238 | + $this->_set_defaults(); |
|
239 | + add_action('AHEE__EE_System__initialize', array($this, 'open_session')); |
|
240 | + // check request for 'clear_session' param |
|
241 | + add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded')); |
|
242 | + // once everything is all said and done, |
|
243 | + add_action('shutdown', array($this, 'update'), 100); |
|
244 | + add_action('shutdown', array($this, 'garbageCollection'), 1000); |
|
245 | + $this->configure_garbage_collection_filters(); |
|
246 | + } |
|
247 | + |
|
248 | + |
|
249 | + |
|
250 | + /** |
|
251 | + * @return void |
|
252 | + * @throws EE_Error |
|
253 | + * @throws InvalidArgumentException |
|
254 | + * @throws InvalidDataTypeException |
|
255 | + * @throws InvalidInterfaceException |
|
256 | + * @throws InvalidSessionDataException |
|
257 | + */ |
|
258 | + public function open_session() |
|
259 | + { |
|
260 | + // check for existing session and retrieve it from db |
|
261 | + if (! $this->_espresso_session()) { |
|
262 | + // or just start a new one |
|
263 | + $this->_create_espresso_session(); |
|
264 | + } |
|
265 | + } |
|
266 | + |
|
267 | + |
|
268 | + |
|
269 | + /** |
|
270 | + * @return bool |
|
271 | + */ |
|
272 | + public function expired() |
|
273 | + { |
|
274 | + return $this->_expired; |
|
275 | + } |
|
276 | + |
|
277 | + |
|
278 | + |
|
279 | + /** |
|
280 | + * @return void |
|
281 | + */ |
|
282 | + public function reset_expired() |
|
283 | + { |
|
284 | + $this->_expired = false; |
|
285 | + } |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * @return int |
|
290 | + */ |
|
291 | + public function expiration() |
|
292 | + { |
|
293 | + return $this->_expiration; |
|
294 | + } |
|
295 | + |
|
296 | + |
|
297 | + |
|
298 | + /** |
|
299 | + * @return int |
|
300 | + */ |
|
301 | + public function extension() |
|
302 | + { |
|
303 | + return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS); |
|
304 | + } |
|
305 | + |
|
306 | + |
|
307 | + |
|
308 | + /** |
|
309 | + * @param int $time number of seconds to add to session expiration |
|
310 | + */ |
|
311 | + public function extend_expiration($time = 0) |
|
312 | + { |
|
313 | + $time = $time ? $time : $this->extension(); |
|
314 | + $this->_expiration += absint($time); |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + |
|
319 | + /** |
|
320 | + * @return int |
|
321 | + */ |
|
322 | + public function lifespan() |
|
323 | + { |
|
324 | + return $this->_lifespan; |
|
325 | + } |
|
326 | + |
|
327 | + |
|
328 | + |
|
329 | + /** |
|
330 | + * This just sets some defaults for the _session data property |
|
331 | + * |
|
332 | + * @access private |
|
333 | + * @return void |
|
334 | + */ |
|
335 | + private function _set_defaults() |
|
336 | + { |
|
337 | + // set some defaults |
|
338 | + foreach ($this->_default_session_vars as $key => $default_var) { |
|
339 | + if (is_array($default_var)) { |
|
340 | + $this->_session_data[ $key ] = array(); |
|
341 | + } else { |
|
342 | + $this->_session_data[ $key ] = ''; |
|
343 | + } |
|
344 | + } |
|
345 | + } |
|
346 | 346 | |
347 | 347 | |
348 | - |
|
349 | - /** |
|
350 | - * @retrieve session data |
|
351 | - * @access public |
|
352 | - * @return string |
|
353 | - */ |
|
354 | - public function id() |
|
355 | - { |
|
356 | - return $this->_sid; |
|
357 | - } |
|
348 | + |
|
349 | + /** |
|
350 | + * @retrieve session data |
|
351 | + * @access public |
|
352 | + * @return string |
|
353 | + */ |
|
354 | + public function id() |
|
355 | + { |
|
356 | + return $this->_sid; |
|
357 | + } |
|
358 | 358 | |
359 | 359 | |
360 | 360 | |
361 | - /** |
|
362 | - * @param \EE_Cart $cart |
|
363 | - * @return bool |
|
364 | - */ |
|
365 | - public function set_cart(EE_Cart $cart) |
|
366 | - { |
|
367 | - $this->_session_data['cart'] = $cart; |
|
368 | - return true; |
|
369 | - } |
|
361 | + /** |
|
362 | + * @param \EE_Cart $cart |
|
363 | + * @return bool |
|
364 | + */ |
|
365 | + public function set_cart(EE_Cart $cart) |
|
366 | + { |
|
367 | + $this->_session_data['cart'] = $cart; |
|
368 | + return true; |
|
369 | + } |
|
370 | 370 | |
371 | 371 | |
372 | 372 | |
373 | - /** |
|
374 | - * reset_cart |
|
375 | - */ |
|
376 | - public function reset_cart() |
|
377 | - { |
|
378 | - do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
379 | - $this->_session_data['cart'] = null; |
|
380 | - } |
|
381 | - |
|
382 | - |
|
383 | - |
|
384 | - /** |
|
385 | - * @return \EE_Cart |
|
386 | - */ |
|
387 | - public function cart() |
|
388 | - { |
|
389 | - return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
390 | - ? $this->_session_data['cart'] |
|
391 | - : null; |
|
392 | - } |
|
393 | - |
|
394 | - |
|
395 | - |
|
396 | - /** |
|
397 | - * @param \EE_Checkout $checkout |
|
398 | - * @return bool |
|
399 | - */ |
|
400 | - public function set_checkout(EE_Checkout $checkout) |
|
401 | - { |
|
402 | - $this->_session_data['checkout'] = $checkout; |
|
403 | - return true; |
|
404 | - } |
|
405 | - |
|
406 | - |
|
407 | - |
|
408 | - /** |
|
409 | - * reset_checkout |
|
410 | - */ |
|
411 | - public function reset_checkout() |
|
412 | - { |
|
413 | - do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
414 | - $this->_session_data['checkout'] = null; |
|
415 | - } |
|
416 | - |
|
417 | - |
|
418 | - |
|
419 | - /** |
|
420 | - * @return \EE_Checkout |
|
421 | - */ |
|
422 | - public function checkout() |
|
423 | - { |
|
424 | - return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
425 | - ? $this->_session_data['checkout'] |
|
426 | - : null; |
|
427 | - } |
|
428 | - |
|
429 | - |
|
430 | - |
|
431 | - /** |
|
432 | - * @param \EE_Transaction $transaction |
|
433 | - * @return bool |
|
434 | - * @throws EE_Error |
|
435 | - */ |
|
436 | - public function set_transaction(EE_Transaction $transaction) |
|
437 | - { |
|
438 | - // first remove the session from the transaction before we save the transaction in the session |
|
439 | - $transaction->set_txn_session_data(null); |
|
440 | - $this->_session_data['transaction'] = $transaction; |
|
441 | - return true; |
|
442 | - } |
|
443 | - |
|
444 | - |
|
445 | - |
|
446 | - /** |
|
447 | - * reset_transaction |
|
448 | - */ |
|
449 | - public function reset_transaction() |
|
450 | - { |
|
451 | - do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
452 | - $this->_session_data['transaction'] = null; |
|
453 | - } |
|
454 | - |
|
455 | - |
|
456 | - |
|
457 | - /** |
|
458 | - * @return \EE_Transaction |
|
459 | - */ |
|
460 | - public function transaction() |
|
461 | - { |
|
462 | - return isset($this->_session_data['transaction']) |
|
463 | - && $this->_session_data['transaction'] instanceof EE_Transaction |
|
464 | - ? $this->_session_data['transaction'] |
|
465 | - : null; |
|
466 | - } |
|
467 | - |
|
468 | - |
|
469 | - |
|
470 | - /** |
|
471 | - * retrieve session data |
|
472 | - * |
|
473 | - * @access public |
|
474 | - * @param null $key |
|
475 | - * @param bool $reset_cache |
|
476 | - * @return array |
|
477 | - */ |
|
478 | - public function get_session_data($key = null, $reset_cache = false) |
|
479 | - { |
|
480 | - if ($reset_cache) { |
|
481 | - $this->reset_cart(); |
|
482 | - $this->reset_checkout(); |
|
483 | - $this->reset_transaction(); |
|
484 | - } |
|
485 | - if (! empty($key)) { |
|
486 | - return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
487 | - } |
|
488 | - return $this->_session_data; |
|
489 | - } |
|
490 | - |
|
491 | - |
|
492 | - |
|
493 | - /** |
|
494 | - * set session data |
|
495 | - * |
|
496 | - * @access public |
|
497 | - * @param array $data |
|
498 | - * @return TRUE on success, FALSE on fail |
|
499 | - */ |
|
500 | - public function set_session_data($data) |
|
501 | - { |
|
502 | - |
|
503 | - // nothing ??? bad data ??? go home! |
|
504 | - if (empty($data) || ! is_array($data)) { |
|
505 | - EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__, |
|
506 | - __FUNCTION__, __LINE__); |
|
507 | - return false; |
|
508 | - } |
|
509 | - foreach ($data as $key => $value) { |
|
510 | - if (isset($this->_default_session_vars[ $key ])) { |
|
511 | - EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
512 | - 'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__); |
|
513 | - return false; |
|
514 | - } |
|
515 | - $this->_session_data[ $key ] = $value; |
|
516 | - } |
|
517 | - return true; |
|
518 | - } |
|
519 | - |
|
520 | - |
|
521 | - |
|
522 | - /** |
|
523 | - * @initiate session |
|
524 | - * @access private |
|
525 | - * @return TRUE on success, FALSE on fail |
|
526 | - * @throws EE_Error |
|
527 | - * @throws InvalidArgumentException |
|
528 | - * @throws InvalidDataTypeException |
|
529 | - * @throws InvalidInterfaceException |
|
530 | - * @throws InvalidSessionDataException |
|
531 | - */ |
|
532 | - private function _espresso_session() |
|
533 | - { |
|
534 | - do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
535 | - // check that session has started |
|
536 | - if (session_id() === '') { |
|
537 | - //starts a new session if one doesn't already exist, or re-initiates an existing one |
|
538 | - session_start(); |
|
539 | - } |
|
540 | - // get our modified session ID |
|
541 | - $this->_sid = $this->_generate_session_id(); |
|
542 | - // and the visitors IP |
|
543 | - $this->_ip_address = $this->request->ip_address(); |
|
544 | - // set the "user agent" |
|
545 | - $this->_user_agent = $this->request->userAgent(); |
|
546 | - // now let's retrieve what's in the db |
|
547 | - $session_data = $this->_retrieve_session_data(); |
|
548 | - if (! empty($session_data)) { |
|
549 | - // get the current time in UTC |
|
550 | - $this->_time = $this->_time !== null ? $this->_time : time(); |
|
551 | - // and reset the session expiration |
|
552 | - $this->_expiration = isset($session_data['expiration']) |
|
553 | - ? $session_data['expiration'] |
|
554 | - : $this->_time + $this->_lifespan; |
|
555 | - } else { |
|
556 | - // set initial site access time and the session expiration |
|
557 | - $this->_set_init_access_and_expiration(); |
|
558 | - // set referer |
|
559 | - $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER']) |
|
560 | - ? esc_attr($_SERVER['HTTP_REFERER']) |
|
561 | - : ''; |
|
562 | - // no previous session = go back and create one (on top of the data above) |
|
563 | - return false; |
|
564 | - } |
|
565 | - // now the user agent |
|
566 | - if ($session_data['user_agent'] !== $this->_user_agent) { |
|
567 | - return false; |
|
568 | - } |
|
569 | - // wait a minute... how old are you? |
|
570 | - if ($this->_time > $this->_expiration) { |
|
571 | - // yer too old fer me! |
|
572 | - $this->_expired = true; |
|
573 | - // wipe out everything that isn't a default session datum |
|
574 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
575 | - } |
|
576 | - // make event espresso session data available to plugin |
|
577 | - $this->_session_data = array_merge($this->_session_data, $session_data); |
|
578 | - return true; |
|
579 | - } |
|
580 | - |
|
581 | - |
|
582 | - |
|
583 | - /** |
|
584 | - * _get_session_data |
|
585 | - * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
586 | - * databases |
|
587 | - * |
|
588 | - * @return array |
|
589 | - * @throws EE_Error |
|
590 | - * @throws InvalidArgumentException |
|
591 | - * @throws InvalidSessionDataException |
|
592 | - * @throws InvalidDataTypeException |
|
593 | - * @throws InvalidInterfaceException |
|
594 | - */ |
|
595 | - protected function _retrieve_session_data() |
|
596 | - { |
|
597 | - $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
598 | - try { |
|
599 | - // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
600 | - $session_data = $this->cache_storage->get($ssn_key, false); |
|
601 | - if (empty($session_data)) { |
|
602 | - return array(); |
|
603 | - } |
|
604 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
605 | - $hash_check = $this->cache_storage->get( |
|
606 | - EE_Session::hash_check_prefix . $this->_sid, |
|
607 | - false |
|
608 | - ); |
|
609 | - if ($hash_check && $hash_check !== md5($session_data)) { |
|
610 | - EE_Error::add_error( |
|
611 | - sprintf( |
|
612 | - __( |
|
613 | - 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
614 | - 'event_espresso' |
|
615 | - ), |
|
616 | - EE_Session::session_id_prefix . $this->_sid |
|
617 | - ), |
|
618 | - __FILE__, __FUNCTION__, __LINE__ |
|
619 | - ); |
|
620 | - } |
|
621 | - } |
|
622 | - } catch (Exception $e) { |
|
623 | - // let's just eat that error for now and attempt to correct any corrupted data |
|
624 | - global $wpdb; |
|
625 | - $row = $wpdb->get_row( |
|
626 | - $wpdb->prepare( |
|
627 | - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
628 | - '_transient_' . $ssn_key |
|
629 | - ) |
|
630 | - ); |
|
631 | - $session_data = is_object($row) ? $row->option_value : null; |
|
632 | - if ($session_data) { |
|
633 | - $session_data = preg_replace_callback( |
|
634 | - '!s:(d+):"(.*?)";!', |
|
635 | - function ($match) |
|
636 | - { |
|
637 | - return $match[1] === strlen($match[2]) |
|
638 | - ? $match[0] |
|
639 | - : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
640 | - }, |
|
641 | - $session_data |
|
642 | - ); |
|
643 | - } |
|
644 | - $session_data = maybe_unserialize($session_data); |
|
645 | - } |
|
646 | - // in case the data is encoded... try to decode it |
|
647 | - $session_data = $this->encryption instanceof EE_Encryption |
|
648 | - ? $this->encryption->base64_string_decode($session_data) |
|
649 | - : $session_data; |
|
650 | - if (! is_array($session_data)) { |
|
651 | - try { |
|
652 | - $session_data = maybe_unserialize($session_data); |
|
653 | - } catch (Exception $e) { |
|
654 | - $msg = esc_html__( |
|
655 | - 'An error occurred while attempting to unserialize the session data.', |
|
656 | - 'event_espresso' |
|
657 | - ); |
|
658 | - $msg .= WP_DEBUG |
|
659 | - ? '<br><pre>' |
|
660 | - . print_r($session_data, true) |
|
661 | - . '</pre><br>' |
|
662 | - . $this->find_serialize_error($session_data) |
|
663 | - : ''; |
|
664 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
665 | - throw new InvalidSessionDataException($msg, 0, $e); |
|
666 | - } |
|
667 | - } |
|
668 | - // just a check to make sure the session array is indeed an array |
|
669 | - if (! is_array($session_data)) { |
|
670 | - // no?!?! then something is wrong |
|
671 | - $msg = esc_html__( |
|
672 | - 'The session data is missing, invalid, or corrupted.', |
|
673 | - 'event_espresso' |
|
674 | - ); |
|
675 | - $msg .= WP_DEBUG |
|
676 | - ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
677 | - : ''; |
|
678 | - $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
679 | - throw new InvalidSessionDataException($msg); |
|
680 | - } |
|
681 | - if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
682 | - $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
683 | - $session_data['transaction'] |
|
684 | - ); |
|
685 | - } |
|
686 | - return $session_data; |
|
687 | - } |
|
688 | - |
|
689 | - |
|
690 | - |
|
691 | - /** |
|
692 | - * _generate_session_id |
|
693 | - * Retrieves the PHP session id either directly from the PHP session, |
|
694 | - * or from the $_REQUEST array if it was passed in from an AJAX request. |
|
695 | - * The session id is then salted and hashed (mmm sounds tasty) |
|
696 | - * so that it can be safely used as a $_REQUEST param |
|
697 | - * |
|
698 | - * @return string |
|
699 | - */ |
|
700 | - protected function _generate_session_id() |
|
701 | - { |
|
702 | - // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
703 | - if (isset($_REQUEST['EESID'])) { |
|
704 | - $session_id = sanitize_text_field($_REQUEST['EESID']); |
|
705 | - } else { |
|
706 | - $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
707 | - } |
|
708 | - return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
709 | - } |
|
710 | - |
|
711 | - |
|
712 | - |
|
713 | - /** |
|
714 | - * _get_sid_salt |
|
715 | - * |
|
716 | - * @return string |
|
717 | - */ |
|
718 | - protected function _get_sid_salt() |
|
719 | - { |
|
720 | - // was session id salt already saved to db ? |
|
721 | - if (empty($this->_sid_salt)) { |
|
722 | - // no? then maybe use WP defined constant |
|
723 | - if (defined('AUTH_SALT')) { |
|
724 | - $this->_sid_salt = AUTH_SALT; |
|
725 | - } |
|
726 | - // if salt doesn't exist or is too short |
|
727 | - if (strlen($this->_sid_salt) < 32) { |
|
728 | - // create a new one |
|
729 | - $this->_sid_salt = wp_generate_password(64); |
|
730 | - } |
|
731 | - // and save it as a permanent session setting |
|
732 | - $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
733 | - } |
|
734 | - return $this->_sid_salt; |
|
735 | - } |
|
736 | - |
|
737 | - |
|
738 | - |
|
739 | - /** |
|
740 | - * _set_init_access_and_expiration |
|
741 | - * |
|
742 | - * @return void |
|
743 | - */ |
|
744 | - protected function _set_init_access_and_expiration() |
|
745 | - { |
|
746 | - $this->_time = time(); |
|
747 | - $this->_expiration = $this->_time + $this->_lifespan; |
|
748 | - // set initial site access time |
|
749 | - $this->_session_data['init_access'] = $this->_time; |
|
750 | - // and the session expiration |
|
751 | - $this->_session_data['expiration'] = $this->_expiration; |
|
752 | - } |
|
753 | - |
|
754 | - |
|
755 | - |
|
756 | - /** |
|
757 | - * @update session data prior to saving to the db |
|
758 | - * @access public |
|
759 | - * @param bool $new_session |
|
760 | - * @return TRUE on success, FALSE on fail |
|
761 | - * @throws EE_Error |
|
762 | - * @throws InvalidArgumentException |
|
763 | - * @throws InvalidDataTypeException |
|
764 | - * @throws InvalidInterfaceException |
|
765 | - */ |
|
766 | - public function update($new_session = false) |
|
767 | - { |
|
768 | - $this->_session_data = $this->_session_data !== null |
|
769 | - && is_array($this->_session_data) |
|
770 | - && isset($this->_session_data['id']) |
|
771 | - ? $this->_session_data |
|
772 | - : array(); |
|
773 | - if (empty($this->_session_data)) { |
|
774 | - $this->_set_defaults(); |
|
775 | - } |
|
776 | - $session_data = array(); |
|
777 | - foreach ($this->_session_data as $key => $value) { |
|
778 | - |
|
779 | - switch ($key) { |
|
780 | - |
|
781 | - case 'id' : |
|
782 | - // session ID |
|
783 | - $session_data['id'] = $this->_sid; |
|
784 | - break; |
|
785 | - case 'ip_address' : |
|
786 | - // visitor ip address |
|
787 | - $session_data['ip_address'] = $this->request->ip_address(); |
|
788 | - break; |
|
789 | - case 'user_agent' : |
|
790 | - // visitor user_agent |
|
791 | - $session_data['user_agent'] = $this->_user_agent; |
|
792 | - break; |
|
793 | - case 'init_access' : |
|
794 | - $session_data['init_access'] = absint($value); |
|
795 | - break; |
|
796 | - case 'last_access' : |
|
797 | - // current access time |
|
798 | - $session_data['last_access'] = $this->_time; |
|
799 | - break; |
|
800 | - case 'expiration' : |
|
801 | - // when the session expires |
|
802 | - $session_data['expiration'] = ! empty($this->_expiration) |
|
803 | - ? $this->_expiration |
|
804 | - : $session_data['init_access'] + $this->_lifespan; |
|
805 | - break; |
|
806 | - case 'user_id' : |
|
807 | - // current user if logged in |
|
808 | - $session_data['user_id'] = $this->_wp_user_id(); |
|
809 | - break; |
|
810 | - case 'pages_visited' : |
|
811 | - $page_visit = $this->_get_page_visit(); |
|
812 | - if ($page_visit) { |
|
813 | - // set pages visited where the first will be the http referrer |
|
814 | - $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
815 | - // we'll only save the last 10 page visits. |
|
816 | - $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
817 | - } |
|
818 | - break; |
|
819 | - default : |
|
820 | - // carry any other data over |
|
821 | - $session_data[ $key ] = $this->_session_data[ $key ]; |
|
822 | - } |
|
823 | - } |
|
824 | - $this->_session_data = $session_data; |
|
825 | - // creating a new session does not require saving to the db just yet |
|
826 | - if (! $new_session) { |
|
827 | - // ready? let's save |
|
828 | - if ($this->_save_session_to_db()) { |
|
829 | - return true; |
|
830 | - } |
|
831 | - return false; |
|
832 | - } |
|
833 | - // meh, why not? |
|
834 | - return true; |
|
835 | - } |
|
836 | - |
|
837 | - |
|
838 | - |
|
839 | - /** |
|
840 | - * @create session data array |
|
841 | - * @access public |
|
842 | - * @return bool |
|
843 | - * @throws EE_Error |
|
844 | - * @throws InvalidArgumentException |
|
845 | - * @throws InvalidDataTypeException |
|
846 | - * @throws InvalidInterfaceException |
|
847 | - */ |
|
848 | - private function _create_espresso_session() |
|
849 | - { |
|
850 | - do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
851 | - // use the update function for now with $new_session arg set to TRUE |
|
852 | - return $this->update(true) ? true : false; |
|
853 | - } |
|
854 | - |
|
855 | - |
|
856 | - |
|
857 | - /** |
|
858 | - * _save_session_to_db |
|
859 | - * |
|
860 | - * @access public |
|
861 | - * @return string |
|
862 | - * @throws EE_Error |
|
863 | - * @throws InvalidArgumentException |
|
864 | - * @throws InvalidDataTypeException |
|
865 | - * @throws InvalidInterfaceException |
|
866 | - */ |
|
867 | - private function _save_session_to_db() |
|
868 | - { |
|
869 | - if ( |
|
870 | - $this->request->isBot() |
|
871 | - // if the current request is NOT one of the following |
|
872 | - || ! ( |
|
873 | - // an an AJAX request from the frontend |
|
874 | - EE_Registry::instance()->REQ->front_ajax |
|
875 | - || ( |
|
876 | - // OR an admin request that is NOT AJAX |
|
877 | - ! (defined('DOING_AJAX') && DOING_AJAX) |
|
878 | - && is_admin() |
|
879 | - ) |
|
880 | - || ( |
|
881 | - // OR an espresso page |
|
882 | - EE_Registry::instance()->REQ instanceof EE_Request_Handler |
|
883 | - && EE_Registry::instance()->REQ->is_espresso_page() |
|
884 | - ) |
|
885 | - ) |
|
886 | - ) { |
|
887 | - return false; |
|
888 | - } |
|
889 | - $transaction = $this->transaction(); |
|
890 | - if ($transaction instanceof EE_Transaction) { |
|
891 | - if (! $transaction->ID()) { |
|
892 | - $transaction->save(); |
|
893 | - } |
|
894 | - $this->_session_data['transaction'] = $transaction->ID(); |
|
895 | - } |
|
896 | - // then serialize all of our session data |
|
897 | - $session_data = serialize($this->_session_data); |
|
898 | - // do we need to also encode it to avoid corrupted data when saved to the db? |
|
899 | - $session_data = $this->_use_encryption |
|
900 | - ? $this->encryption->base64_string_encode($session_data) |
|
901 | - : $session_data; |
|
902 | - // maybe save hash check |
|
903 | - if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
904 | - $this->cache_storage->add( |
|
905 | - EE_Session::hash_check_prefix . $this->_sid, |
|
906 | - md5($session_data), |
|
907 | - $this->_lifespan |
|
908 | - ); |
|
909 | - } |
|
910 | - // we're using the Transient API for storing session data, |
|
911 | - return $this->cache_storage->add( |
|
912 | - EE_Session::session_id_prefix . $this->_sid, |
|
913 | - $session_data, |
|
914 | - $this->_lifespan |
|
915 | - ); |
|
916 | - } |
|
917 | - |
|
918 | - |
|
919 | - /** |
|
920 | - * @get the full page request the visitor is accessing |
|
921 | - * @access public |
|
922 | - * @return string |
|
923 | - */ |
|
924 | - public function _get_page_visit() |
|
925 | - { |
|
926 | - $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
927 | - // check for request url |
|
928 | - if (isset($_SERVER['REQUEST_URI'])) { |
|
929 | - $http_host = ''; |
|
930 | - $page_id = '?'; |
|
931 | - $e_reg = ''; |
|
932 | - $request_uri = esc_url($_SERVER['REQUEST_URI']); |
|
933 | - $ru_bits = explode('?', $request_uri); |
|
934 | - $request_uri = $ru_bits[0]; |
|
935 | - // check for and grab host as well |
|
936 | - if (isset($_SERVER['HTTP_HOST'])) { |
|
937 | - $http_host = esc_url($_SERVER['HTTP_HOST']); |
|
938 | - } |
|
939 | - // check for page_id in SERVER REQUEST |
|
940 | - if (isset($_REQUEST['page_id'])) { |
|
941 | - // rebuild $e_reg without any of the extra parameters |
|
942 | - $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&'; |
|
943 | - } |
|
944 | - // check for $e_reg in SERVER REQUEST |
|
945 | - if (isset($_REQUEST['ee'])) { |
|
946 | - // rebuild $e_reg without any of the extra parameters |
|
947 | - $e_reg = 'ee=' . esc_attr($_REQUEST['ee']); |
|
948 | - } |
|
949 | - $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?'); |
|
950 | - } |
|
951 | - return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
952 | - } |
|
953 | - |
|
954 | - |
|
955 | - |
|
956 | - /** |
|
957 | - * @the current wp user id |
|
958 | - * @access public |
|
959 | - * @return int |
|
960 | - */ |
|
961 | - public function _wp_user_id() |
|
962 | - { |
|
963 | - // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
964 | - $this->_wp_user_id = get_current_user_id(); |
|
965 | - return $this->_wp_user_id; |
|
966 | - } |
|
967 | - |
|
968 | - |
|
969 | - |
|
970 | - /** |
|
971 | - * Clear EE_Session data |
|
972 | - * |
|
973 | - * @access public |
|
974 | - * @param string $class |
|
975 | - * @param string $function |
|
976 | - * @return void |
|
977 | - * @throws EE_Error |
|
978 | - * @throws InvalidArgumentException |
|
979 | - * @throws InvalidDataTypeException |
|
980 | - * @throws InvalidInterfaceException |
|
981 | - */ |
|
982 | - public function clear_session($class = '', $function = '') |
|
983 | - { |
|
984 | - do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
985 | - $this->reset_cart(); |
|
986 | - $this->reset_checkout(); |
|
987 | - $this->reset_transaction(); |
|
988 | - // wipe out everything that isn't a default session datum |
|
989 | - $this->reset_data(array_keys($this->_session_data)); |
|
990 | - // reset initial site access time and the session expiration |
|
991 | - $this->_set_init_access_and_expiration(); |
|
992 | - $this->_save_session_to_db(); |
|
993 | - } |
|
994 | - |
|
995 | - |
|
996 | - |
|
997 | - /** |
|
998 | - * @resets all non-default session vars |
|
999 | - * @access public |
|
1000 | - * @param array|mixed $data_to_reset |
|
1001 | - * @param bool $show_all_notices |
|
1002 | - * @return TRUE on success, FALSE on fail |
|
1003 | - */ |
|
1004 | - public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1005 | - { |
|
1006 | - // if $data_to_reset is not in an array, then put it in one |
|
1007 | - if (! is_array($data_to_reset)) { |
|
1008 | - $data_to_reset = array($data_to_reset); |
|
1009 | - } |
|
1010 | - // nothing ??? go home! |
|
1011 | - if (empty($data_to_reset)) { |
|
1012 | - EE_Error::add_error(__('No session data could be reset, because no session var name was provided.', |
|
1013 | - 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
|
1014 | - return false; |
|
1015 | - } |
|
1016 | - $return_value = true; |
|
1017 | - // since $data_to_reset is an array, cycle through the values |
|
1018 | - foreach ($data_to_reset as $reset) { |
|
1019 | - |
|
1020 | - // first check to make sure it is a valid session var |
|
1021 | - if (isset($this->_session_data[ $reset ])) { |
|
1022 | - // then check to make sure it is not a default var |
|
1023 | - if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1024 | - // remove session var |
|
1025 | - unset($this->_session_data[ $reset ]); |
|
1026 | - if ($show_all_notices) { |
|
1027 | - EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'), |
|
1028 | - $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1029 | - } |
|
1030 | - } else { |
|
1031 | - // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1032 | - if ($show_all_notices) { |
|
1033 | - EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
1034 | - 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1035 | - } |
|
1036 | - $return_value = false; |
|
1037 | - } |
|
1038 | - } elseif ($show_all_notices) { |
|
1039 | - // oops! that session var does not exist! |
|
1040 | - EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.', |
|
1041 | - 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1042 | - $return_value = false; |
|
1043 | - } |
|
1044 | - } // end of foreach |
|
1045 | - return $return_value; |
|
1046 | - } |
|
1047 | - |
|
1048 | - |
|
1049 | - |
|
1050 | - /** |
|
1051 | - * wp_loaded |
|
1052 | - * |
|
1053 | - * @access public |
|
1054 | - * @throws EE_Error |
|
1055 | - * @throws InvalidDataTypeException |
|
1056 | - * @throws InvalidInterfaceException |
|
1057 | - * @throws InvalidArgumentException |
|
1058 | - */ |
|
1059 | - public function wp_loaded() |
|
1060 | - { |
|
1061 | - if ($this->request->is_set('clear_session')) { |
|
1062 | - $this->clear_session(__CLASS__, __FUNCTION__); |
|
1063 | - } |
|
1064 | - } |
|
1065 | - |
|
1066 | - |
|
1067 | - |
|
1068 | - /** |
|
1069 | - * Used to reset the entire object (for tests). |
|
1070 | - * |
|
1071 | - * @since 4.3.0 |
|
1072 | - * @throws EE_Error |
|
1073 | - * @throws InvalidDataTypeException |
|
1074 | - * @throws InvalidInterfaceException |
|
1075 | - * @throws InvalidArgumentException |
|
1076 | - */ |
|
1077 | - public function reset_instance() |
|
1078 | - { |
|
1079 | - $this->clear_session(); |
|
1080 | - self::$_instance = null; |
|
1081 | - } |
|
1082 | - |
|
1083 | - |
|
1084 | - |
|
1085 | - public function configure_garbage_collection_filters() |
|
1086 | - { |
|
1087 | - // run old filter we had for controlling session cleanup |
|
1088 | - $expired_session_transient_delete_query_limit = absint( |
|
1089 | - apply_filters( |
|
1090 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1091 | - 50 |
|
1092 | - ) |
|
1093 | - ); |
|
1094 | - // is there a value? or one that is different than the default 50 records? |
|
1095 | - if ($expired_session_transient_delete_query_limit === 0) { |
|
1096 | - // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1097 | - add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1098 | - } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1099 | - // or use that for the new transient cleanup query limit |
|
1100 | - add_filter( |
|
1101 | - 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1102 | - function () use ($expired_session_transient_delete_query_limit) |
|
1103 | - { |
|
1104 | - return $expired_session_transient_delete_query_limit; |
|
1105 | - } |
|
1106 | - ); |
|
1107 | - } |
|
1108 | - } |
|
1109 | - |
|
1110 | - |
|
1111 | - |
|
1112 | - /** |
|
1113 | - * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1114 | - * @param $data1 |
|
1115 | - * @return string |
|
1116 | - */ |
|
1117 | - private function find_serialize_error($data1) |
|
1118 | - { |
|
1119 | - $error = '<pre>'; |
|
1120 | - $data2 = preg_replace_callback( |
|
1121 | - '!s:(\d+):"(.*?)";!', |
|
1122 | - function ($match) |
|
1123 | - { |
|
1124 | - return ($match[1] === strlen($match[2])) |
|
1125 | - ? $match[0] |
|
1126 | - : 's:' |
|
1127 | - . strlen($match[2]) |
|
1128 | - . ':"' |
|
1129 | - . $match[2] |
|
1130 | - . '";'; |
|
1131 | - }, |
|
1132 | - $data1 |
|
1133 | - ); |
|
1134 | - $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1135 | - $error .= $data1 . PHP_EOL; |
|
1136 | - $error .= $data2 . PHP_EOL; |
|
1137 | - for ($i = 0; $i < $max; $i++) { |
|
1138 | - if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1139 | - $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1140 | - $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1141 | - $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1142 | - $start = ($i - 20); |
|
1143 | - $start = ($start < 0) ? 0 : $start; |
|
1144 | - $length = 40; |
|
1145 | - $point = $max - $i; |
|
1146 | - if ($point < 20) { |
|
1147 | - $rlength = 1; |
|
1148 | - $rpoint = -$point; |
|
1149 | - } else { |
|
1150 | - $rpoint = $length - 20; |
|
1151 | - $rlength = 1; |
|
1152 | - } |
|
1153 | - $error .= "\t-> Section Data1 = "; |
|
1154 | - $error .= substr_replace( |
|
1155 | - substr($data1, $start, $length), |
|
1156 | - "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1157 | - $rpoint, |
|
1158 | - $rlength |
|
1159 | - ); |
|
1160 | - $error .= PHP_EOL; |
|
1161 | - $error .= "\t-> Section Data2 = "; |
|
1162 | - $error .= substr_replace( |
|
1163 | - substr($data2, $start, $length), |
|
1164 | - "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1165 | - $rpoint, |
|
1166 | - $rlength |
|
1167 | - ); |
|
1168 | - $error .= PHP_EOL; |
|
1169 | - } |
|
1170 | - } |
|
1171 | - $error .= '</pre>'; |
|
1172 | - return $error; |
|
1173 | - } |
|
1174 | - |
|
1175 | - |
|
1176 | - /** |
|
1177 | - * Saves an array of settings used for configuring aspects of session behaviour |
|
1178 | - * |
|
1179 | - * @param array $updated_settings |
|
1180 | - */ |
|
1181 | - private function updateSessionSettings(array $updated_settings = array()) |
|
1182 | - { |
|
1183 | - // add existing settings, but only if not included in incoming $updated_settings array |
|
1184 | - $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1185 | - update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1186 | - } |
|
1187 | - |
|
1188 | - |
|
1189 | - /** |
|
1190 | - * garbage_collection |
|
1191 | - */ |
|
1192 | - public function garbageCollection() |
|
1193 | - { |
|
1194 | - // only perform during regular requests if last garbage collection was over an hour ago |
|
1195 | - if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1196 | - $this->_last_gc = time(); |
|
1197 | - $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1198 | - /** @type WPDB $wpdb */ |
|
1199 | - global $wpdb; |
|
1200 | - // filter the query limit. Set to 0 to turn off garbage collection |
|
1201 | - $expired_session_transient_delete_query_limit = absint( |
|
1202 | - apply_filters( |
|
1203 | - 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1204 | - 50 |
|
1205 | - ) |
|
1206 | - ); |
|
1207 | - // non-zero LIMIT means take out the trash |
|
1208 | - if ($expired_session_transient_delete_query_limit) { |
|
1209 | - $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1210 | - $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1211 | - // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1212 | - // but we only want to pick up any trash that's been around for more than a day |
|
1213 | - $expiration = time() - DAY_IN_SECONDS; |
|
1214 | - $SQL = " |
|
373 | + /** |
|
374 | + * reset_cart |
|
375 | + */ |
|
376 | + public function reset_cart() |
|
377 | + { |
|
378 | + do_action('AHEE__EE_Session__reset_cart__before_reset', $this); |
|
379 | + $this->_session_data['cart'] = null; |
|
380 | + } |
|
381 | + |
|
382 | + |
|
383 | + |
|
384 | + /** |
|
385 | + * @return \EE_Cart |
|
386 | + */ |
|
387 | + public function cart() |
|
388 | + { |
|
389 | + return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart |
|
390 | + ? $this->_session_data['cart'] |
|
391 | + : null; |
|
392 | + } |
|
393 | + |
|
394 | + |
|
395 | + |
|
396 | + /** |
|
397 | + * @param \EE_Checkout $checkout |
|
398 | + * @return bool |
|
399 | + */ |
|
400 | + public function set_checkout(EE_Checkout $checkout) |
|
401 | + { |
|
402 | + $this->_session_data['checkout'] = $checkout; |
|
403 | + return true; |
|
404 | + } |
|
405 | + |
|
406 | + |
|
407 | + |
|
408 | + /** |
|
409 | + * reset_checkout |
|
410 | + */ |
|
411 | + public function reset_checkout() |
|
412 | + { |
|
413 | + do_action('AHEE__EE_Session__reset_checkout__before_reset', $this); |
|
414 | + $this->_session_data['checkout'] = null; |
|
415 | + } |
|
416 | + |
|
417 | + |
|
418 | + |
|
419 | + /** |
|
420 | + * @return \EE_Checkout |
|
421 | + */ |
|
422 | + public function checkout() |
|
423 | + { |
|
424 | + return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout |
|
425 | + ? $this->_session_data['checkout'] |
|
426 | + : null; |
|
427 | + } |
|
428 | + |
|
429 | + |
|
430 | + |
|
431 | + /** |
|
432 | + * @param \EE_Transaction $transaction |
|
433 | + * @return bool |
|
434 | + * @throws EE_Error |
|
435 | + */ |
|
436 | + public function set_transaction(EE_Transaction $transaction) |
|
437 | + { |
|
438 | + // first remove the session from the transaction before we save the transaction in the session |
|
439 | + $transaction->set_txn_session_data(null); |
|
440 | + $this->_session_data['transaction'] = $transaction; |
|
441 | + return true; |
|
442 | + } |
|
443 | + |
|
444 | + |
|
445 | + |
|
446 | + /** |
|
447 | + * reset_transaction |
|
448 | + */ |
|
449 | + public function reset_transaction() |
|
450 | + { |
|
451 | + do_action('AHEE__EE_Session__reset_transaction__before_reset', $this); |
|
452 | + $this->_session_data['transaction'] = null; |
|
453 | + } |
|
454 | + |
|
455 | + |
|
456 | + |
|
457 | + /** |
|
458 | + * @return \EE_Transaction |
|
459 | + */ |
|
460 | + public function transaction() |
|
461 | + { |
|
462 | + return isset($this->_session_data['transaction']) |
|
463 | + && $this->_session_data['transaction'] instanceof EE_Transaction |
|
464 | + ? $this->_session_data['transaction'] |
|
465 | + : null; |
|
466 | + } |
|
467 | + |
|
468 | + |
|
469 | + |
|
470 | + /** |
|
471 | + * retrieve session data |
|
472 | + * |
|
473 | + * @access public |
|
474 | + * @param null $key |
|
475 | + * @param bool $reset_cache |
|
476 | + * @return array |
|
477 | + */ |
|
478 | + public function get_session_data($key = null, $reset_cache = false) |
|
479 | + { |
|
480 | + if ($reset_cache) { |
|
481 | + $this->reset_cart(); |
|
482 | + $this->reset_checkout(); |
|
483 | + $this->reset_transaction(); |
|
484 | + } |
|
485 | + if (! empty($key)) { |
|
486 | + return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null; |
|
487 | + } |
|
488 | + return $this->_session_data; |
|
489 | + } |
|
490 | + |
|
491 | + |
|
492 | + |
|
493 | + /** |
|
494 | + * set session data |
|
495 | + * |
|
496 | + * @access public |
|
497 | + * @param array $data |
|
498 | + * @return TRUE on success, FALSE on fail |
|
499 | + */ |
|
500 | + public function set_session_data($data) |
|
501 | + { |
|
502 | + |
|
503 | + // nothing ??? bad data ??? go home! |
|
504 | + if (empty($data) || ! is_array($data)) { |
|
505 | + EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__, |
|
506 | + __FUNCTION__, __LINE__); |
|
507 | + return false; |
|
508 | + } |
|
509 | + foreach ($data as $key => $value) { |
|
510 | + if (isset($this->_default_session_vars[ $key ])) { |
|
511 | + EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
512 | + 'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__); |
|
513 | + return false; |
|
514 | + } |
|
515 | + $this->_session_data[ $key ] = $value; |
|
516 | + } |
|
517 | + return true; |
|
518 | + } |
|
519 | + |
|
520 | + |
|
521 | + |
|
522 | + /** |
|
523 | + * @initiate session |
|
524 | + * @access private |
|
525 | + * @return TRUE on success, FALSE on fail |
|
526 | + * @throws EE_Error |
|
527 | + * @throws InvalidArgumentException |
|
528 | + * @throws InvalidDataTypeException |
|
529 | + * @throws InvalidInterfaceException |
|
530 | + * @throws InvalidSessionDataException |
|
531 | + */ |
|
532 | + private function _espresso_session() |
|
533 | + { |
|
534 | + do_action('AHEE_log', __FILE__, __FUNCTION__, ''); |
|
535 | + // check that session has started |
|
536 | + if (session_id() === '') { |
|
537 | + //starts a new session if one doesn't already exist, or re-initiates an existing one |
|
538 | + session_start(); |
|
539 | + } |
|
540 | + // get our modified session ID |
|
541 | + $this->_sid = $this->_generate_session_id(); |
|
542 | + // and the visitors IP |
|
543 | + $this->_ip_address = $this->request->ip_address(); |
|
544 | + // set the "user agent" |
|
545 | + $this->_user_agent = $this->request->userAgent(); |
|
546 | + // now let's retrieve what's in the db |
|
547 | + $session_data = $this->_retrieve_session_data(); |
|
548 | + if (! empty($session_data)) { |
|
549 | + // get the current time in UTC |
|
550 | + $this->_time = $this->_time !== null ? $this->_time : time(); |
|
551 | + // and reset the session expiration |
|
552 | + $this->_expiration = isset($session_data['expiration']) |
|
553 | + ? $session_data['expiration'] |
|
554 | + : $this->_time + $this->_lifespan; |
|
555 | + } else { |
|
556 | + // set initial site access time and the session expiration |
|
557 | + $this->_set_init_access_and_expiration(); |
|
558 | + // set referer |
|
559 | + $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER']) |
|
560 | + ? esc_attr($_SERVER['HTTP_REFERER']) |
|
561 | + : ''; |
|
562 | + // no previous session = go back and create one (on top of the data above) |
|
563 | + return false; |
|
564 | + } |
|
565 | + // now the user agent |
|
566 | + if ($session_data['user_agent'] !== $this->_user_agent) { |
|
567 | + return false; |
|
568 | + } |
|
569 | + // wait a minute... how old are you? |
|
570 | + if ($this->_time > $this->_expiration) { |
|
571 | + // yer too old fer me! |
|
572 | + $this->_expired = true; |
|
573 | + // wipe out everything that isn't a default session datum |
|
574 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
575 | + } |
|
576 | + // make event espresso session data available to plugin |
|
577 | + $this->_session_data = array_merge($this->_session_data, $session_data); |
|
578 | + return true; |
|
579 | + } |
|
580 | + |
|
581 | + |
|
582 | + |
|
583 | + /** |
|
584 | + * _get_session_data |
|
585 | + * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup |
|
586 | + * databases |
|
587 | + * |
|
588 | + * @return array |
|
589 | + * @throws EE_Error |
|
590 | + * @throws InvalidArgumentException |
|
591 | + * @throws InvalidSessionDataException |
|
592 | + * @throws InvalidDataTypeException |
|
593 | + * @throws InvalidInterfaceException |
|
594 | + */ |
|
595 | + protected function _retrieve_session_data() |
|
596 | + { |
|
597 | + $ssn_key = EE_Session::session_id_prefix . $this->_sid; |
|
598 | + try { |
|
599 | + // we're using WP's Transient API to store session data using the PHP session ID as the option name |
|
600 | + $session_data = $this->cache_storage->get($ssn_key, false); |
|
601 | + if (empty($session_data)) { |
|
602 | + return array(); |
|
603 | + } |
|
604 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
605 | + $hash_check = $this->cache_storage->get( |
|
606 | + EE_Session::hash_check_prefix . $this->_sid, |
|
607 | + false |
|
608 | + ); |
|
609 | + if ($hash_check && $hash_check !== md5($session_data)) { |
|
610 | + EE_Error::add_error( |
|
611 | + sprintf( |
|
612 | + __( |
|
613 | + 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.', |
|
614 | + 'event_espresso' |
|
615 | + ), |
|
616 | + EE_Session::session_id_prefix . $this->_sid |
|
617 | + ), |
|
618 | + __FILE__, __FUNCTION__, __LINE__ |
|
619 | + ); |
|
620 | + } |
|
621 | + } |
|
622 | + } catch (Exception $e) { |
|
623 | + // let's just eat that error for now and attempt to correct any corrupted data |
|
624 | + global $wpdb; |
|
625 | + $row = $wpdb->get_row( |
|
626 | + $wpdb->prepare( |
|
627 | + "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1", |
|
628 | + '_transient_' . $ssn_key |
|
629 | + ) |
|
630 | + ); |
|
631 | + $session_data = is_object($row) ? $row->option_value : null; |
|
632 | + if ($session_data) { |
|
633 | + $session_data = preg_replace_callback( |
|
634 | + '!s:(d+):"(.*?)";!', |
|
635 | + function ($match) |
|
636 | + { |
|
637 | + return $match[1] === strlen($match[2]) |
|
638 | + ? $match[0] |
|
639 | + : 's:' . strlen($match[2]) . ':"' . $match[2] . '";'; |
|
640 | + }, |
|
641 | + $session_data |
|
642 | + ); |
|
643 | + } |
|
644 | + $session_data = maybe_unserialize($session_data); |
|
645 | + } |
|
646 | + // in case the data is encoded... try to decode it |
|
647 | + $session_data = $this->encryption instanceof EE_Encryption |
|
648 | + ? $this->encryption->base64_string_decode($session_data) |
|
649 | + : $session_data; |
|
650 | + if (! is_array($session_data)) { |
|
651 | + try { |
|
652 | + $session_data = maybe_unserialize($session_data); |
|
653 | + } catch (Exception $e) { |
|
654 | + $msg = esc_html__( |
|
655 | + 'An error occurred while attempting to unserialize the session data.', |
|
656 | + 'event_espresso' |
|
657 | + ); |
|
658 | + $msg .= WP_DEBUG |
|
659 | + ? '<br><pre>' |
|
660 | + . print_r($session_data, true) |
|
661 | + . '</pre><br>' |
|
662 | + . $this->find_serialize_error($session_data) |
|
663 | + : ''; |
|
664 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
665 | + throw new InvalidSessionDataException($msg, 0, $e); |
|
666 | + } |
|
667 | + } |
|
668 | + // just a check to make sure the session array is indeed an array |
|
669 | + if (! is_array($session_data)) { |
|
670 | + // no?!?! then something is wrong |
|
671 | + $msg = esc_html__( |
|
672 | + 'The session data is missing, invalid, or corrupted.', |
|
673 | + 'event_espresso' |
|
674 | + ); |
|
675 | + $msg .= WP_DEBUG |
|
676 | + ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data) |
|
677 | + : ''; |
|
678 | + $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid); |
|
679 | + throw new InvalidSessionDataException($msg); |
|
680 | + } |
|
681 | + if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) { |
|
682 | + $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID( |
|
683 | + $session_data['transaction'] |
|
684 | + ); |
|
685 | + } |
|
686 | + return $session_data; |
|
687 | + } |
|
688 | + |
|
689 | + |
|
690 | + |
|
691 | + /** |
|
692 | + * _generate_session_id |
|
693 | + * Retrieves the PHP session id either directly from the PHP session, |
|
694 | + * or from the $_REQUEST array if it was passed in from an AJAX request. |
|
695 | + * The session id is then salted and hashed (mmm sounds tasty) |
|
696 | + * so that it can be safely used as a $_REQUEST param |
|
697 | + * |
|
698 | + * @return string |
|
699 | + */ |
|
700 | + protected function _generate_session_id() |
|
701 | + { |
|
702 | + // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length |
|
703 | + if (isset($_REQUEST['EESID'])) { |
|
704 | + $session_id = sanitize_text_field($_REQUEST['EESID']); |
|
705 | + } else { |
|
706 | + $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt()); |
|
707 | + } |
|
708 | + return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id); |
|
709 | + } |
|
710 | + |
|
711 | + |
|
712 | + |
|
713 | + /** |
|
714 | + * _get_sid_salt |
|
715 | + * |
|
716 | + * @return string |
|
717 | + */ |
|
718 | + protected function _get_sid_salt() |
|
719 | + { |
|
720 | + // was session id salt already saved to db ? |
|
721 | + if (empty($this->_sid_salt)) { |
|
722 | + // no? then maybe use WP defined constant |
|
723 | + if (defined('AUTH_SALT')) { |
|
724 | + $this->_sid_salt = AUTH_SALT; |
|
725 | + } |
|
726 | + // if salt doesn't exist or is too short |
|
727 | + if (strlen($this->_sid_salt) < 32) { |
|
728 | + // create a new one |
|
729 | + $this->_sid_salt = wp_generate_password(64); |
|
730 | + } |
|
731 | + // and save it as a permanent session setting |
|
732 | + $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt)); |
|
733 | + } |
|
734 | + return $this->_sid_salt; |
|
735 | + } |
|
736 | + |
|
737 | + |
|
738 | + |
|
739 | + /** |
|
740 | + * _set_init_access_and_expiration |
|
741 | + * |
|
742 | + * @return void |
|
743 | + */ |
|
744 | + protected function _set_init_access_and_expiration() |
|
745 | + { |
|
746 | + $this->_time = time(); |
|
747 | + $this->_expiration = $this->_time + $this->_lifespan; |
|
748 | + // set initial site access time |
|
749 | + $this->_session_data['init_access'] = $this->_time; |
|
750 | + // and the session expiration |
|
751 | + $this->_session_data['expiration'] = $this->_expiration; |
|
752 | + } |
|
753 | + |
|
754 | + |
|
755 | + |
|
756 | + /** |
|
757 | + * @update session data prior to saving to the db |
|
758 | + * @access public |
|
759 | + * @param bool $new_session |
|
760 | + * @return TRUE on success, FALSE on fail |
|
761 | + * @throws EE_Error |
|
762 | + * @throws InvalidArgumentException |
|
763 | + * @throws InvalidDataTypeException |
|
764 | + * @throws InvalidInterfaceException |
|
765 | + */ |
|
766 | + public function update($new_session = false) |
|
767 | + { |
|
768 | + $this->_session_data = $this->_session_data !== null |
|
769 | + && is_array($this->_session_data) |
|
770 | + && isset($this->_session_data['id']) |
|
771 | + ? $this->_session_data |
|
772 | + : array(); |
|
773 | + if (empty($this->_session_data)) { |
|
774 | + $this->_set_defaults(); |
|
775 | + } |
|
776 | + $session_data = array(); |
|
777 | + foreach ($this->_session_data as $key => $value) { |
|
778 | + |
|
779 | + switch ($key) { |
|
780 | + |
|
781 | + case 'id' : |
|
782 | + // session ID |
|
783 | + $session_data['id'] = $this->_sid; |
|
784 | + break; |
|
785 | + case 'ip_address' : |
|
786 | + // visitor ip address |
|
787 | + $session_data['ip_address'] = $this->request->ip_address(); |
|
788 | + break; |
|
789 | + case 'user_agent' : |
|
790 | + // visitor user_agent |
|
791 | + $session_data['user_agent'] = $this->_user_agent; |
|
792 | + break; |
|
793 | + case 'init_access' : |
|
794 | + $session_data['init_access'] = absint($value); |
|
795 | + break; |
|
796 | + case 'last_access' : |
|
797 | + // current access time |
|
798 | + $session_data['last_access'] = $this->_time; |
|
799 | + break; |
|
800 | + case 'expiration' : |
|
801 | + // when the session expires |
|
802 | + $session_data['expiration'] = ! empty($this->_expiration) |
|
803 | + ? $this->_expiration |
|
804 | + : $session_data['init_access'] + $this->_lifespan; |
|
805 | + break; |
|
806 | + case 'user_id' : |
|
807 | + // current user if logged in |
|
808 | + $session_data['user_id'] = $this->_wp_user_id(); |
|
809 | + break; |
|
810 | + case 'pages_visited' : |
|
811 | + $page_visit = $this->_get_page_visit(); |
|
812 | + if ($page_visit) { |
|
813 | + // set pages visited where the first will be the http referrer |
|
814 | + $this->_session_data['pages_visited'][ $this->_time ] = $page_visit; |
|
815 | + // we'll only save the last 10 page visits. |
|
816 | + $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10); |
|
817 | + } |
|
818 | + break; |
|
819 | + default : |
|
820 | + // carry any other data over |
|
821 | + $session_data[ $key ] = $this->_session_data[ $key ]; |
|
822 | + } |
|
823 | + } |
|
824 | + $this->_session_data = $session_data; |
|
825 | + // creating a new session does not require saving to the db just yet |
|
826 | + if (! $new_session) { |
|
827 | + // ready? let's save |
|
828 | + if ($this->_save_session_to_db()) { |
|
829 | + return true; |
|
830 | + } |
|
831 | + return false; |
|
832 | + } |
|
833 | + // meh, why not? |
|
834 | + return true; |
|
835 | + } |
|
836 | + |
|
837 | + |
|
838 | + |
|
839 | + /** |
|
840 | + * @create session data array |
|
841 | + * @access public |
|
842 | + * @return bool |
|
843 | + * @throws EE_Error |
|
844 | + * @throws InvalidArgumentException |
|
845 | + * @throws InvalidDataTypeException |
|
846 | + * @throws InvalidInterfaceException |
|
847 | + */ |
|
848 | + private function _create_espresso_session() |
|
849 | + { |
|
850 | + do_action('AHEE_log', __CLASS__, __FUNCTION__, ''); |
|
851 | + // use the update function for now with $new_session arg set to TRUE |
|
852 | + return $this->update(true) ? true : false; |
|
853 | + } |
|
854 | + |
|
855 | + |
|
856 | + |
|
857 | + /** |
|
858 | + * _save_session_to_db |
|
859 | + * |
|
860 | + * @access public |
|
861 | + * @return string |
|
862 | + * @throws EE_Error |
|
863 | + * @throws InvalidArgumentException |
|
864 | + * @throws InvalidDataTypeException |
|
865 | + * @throws InvalidInterfaceException |
|
866 | + */ |
|
867 | + private function _save_session_to_db() |
|
868 | + { |
|
869 | + if ( |
|
870 | + $this->request->isBot() |
|
871 | + // if the current request is NOT one of the following |
|
872 | + || ! ( |
|
873 | + // an an AJAX request from the frontend |
|
874 | + EE_Registry::instance()->REQ->front_ajax |
|
875 | + || ( |
|
876 | + // OR an admin request that is NOT AJAX |
|
877 | + ! (defined('DOING_AJAX') && DOING_AJAX) |
|
878 | + && is_admin() |
|
879 | + ) |
|
880 | + || ( |
|
881 | + // OR an espresso page |
|
882 | + EE_Registry::instance()->REQ instanceof EE_Request_Handler |
|
883 | + && EE_Registry::instance()->REQ->is_espresso_page() |
|
884 | + ) |
|
885 | + ) |
|
886 | + ) { |
|
887 | + return false; |
|
888 | + } |
|
889 | + $transaction = $this->transaction(); |
|
890 | + if ($transaction instanceof EE_Transaction) { |
|
891 | + if (! $transaction->ID()) { |
|
892 | + $transaction->save(); |
|
893 | + } |
|
894 | + $this->_session_data['transaction'] = $transaction->ID(); |
|
895 | + } |
|
896 | + // then serialize all of our session data |
|
897 | + $session_data = serialize($this->_session_data); |
|
898 | + // do we need to also encode it to avoid corrupted data when saved to the db? |
|
899 | + $session_data = $this->_use_encryption |
|
900 | + ? $this->encryption->base64_string_encode($session_data) |
|
901 | + : $session_data; |
|
902 | + // maybe save hash check |
|
903 | + if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) { |
|
904 | + $this->cache_storage->add( |
|
905 | + EE_Session::hash_check_prefix . $this->_sid, |
|
906 | + md5($session_data), |
|
907 | + $this->_lifespan |
|
908 | + ); |
|
909 | + } |
|
910 | + // we're using the Transient API for storing session data, |
|
911 | + return $this->cache_storage->add( |
|
912 | + EE_Session::session_id_prefix . $this->_sid, |
|
913 | + $session_data, |
|
914 | + $this->_lifespan |
|
915 | + ); |
|
916 | + } |
|
917 | + |
|
918 | + |
|
919 | + /** |
|
920 | + * @get the full page request the visitor is accessing |
|
921 | + * @access public |
|
922 | + * @return string |
|
923 | + */ |
|
924 | + public function _get_page_visit() |
|
925 | + { |
|
926 | + $page_visit = home_url('/') . 'wp-admin/admin-ajax.php'; |
|
927 | + // check for request url |
|
928 | + if (isset($_SERVER['REQUEST_URI'])) { |
|
929 | + $http_host = ''; |
|
930 | + $page_id = '?'; |
|
931 | + $e_reg = ''; |
|
932 | + $request_uri = esc_url($_SERVER['REQUEST_URI']); |
|
933 | + $ru_bits = explode('?', $request_uri); |
|
934 | + $request_uri = $ru_bits[0]; |
|
935 | + // check for and grab host as well |
|
936 | + if (isset($_SERVER['HTTP_HOST'])) { |
|
937 | + $http_host = esc_url($_SERVER['HTTP_HOST']); |
|
938 | + } |
|
939 | + // check for page_id in SERVER REQUEST |
|
940 | + if (isset($_REQUEST['page_id'])) { |
|
941 | + // rebuild $e_reg without any of the extra parameters |
|
942 | + $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&'; |
|
943 | + } |
|
944 | + // check for $e_reg in SERVER REQUEST |
|
945 | + if (isset($_REQUEST['ee'])) { |
|
946 | + // rebuild $e_reg without any of the extra parameters |
|
947 | + $e_reg = 'ee=' . esc_attr($_REQUEST['ee']); |
|
948 | + } |
|
949 | + $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?'); |
|
950 | + } |
|
951 | + return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : ''; |
|
952 | + } |
|
953 | + |
|
954 | + |
|
955 | + |
|
956 | + /** |
|
957 | + * @the current wp user id |
|
958 | + * @access public |
|
959 | + * @return int |
|
960 | + */ |
|
961 | + public function _wp_user_id() |
|
962 | + { |
|
963 | + // if I need to explain the following lines of code, then you shouldn't be looking at this! |
|
964 | + $this->_wp_user_id = get_current_user_id(); |
|
965 | + return $this->_wp_user_id; |
|
966 | + } |
|
967 | + |
|
968 | + |
|
969 | + |
|
970 | + /** |
|
971 | + * Clear EE_Session data |
|
972 | + * |
|
973 | + * @access public |
|
974 | + * @param string $class |
|
975 | + * @param string $function |
|
976 | + * @return void |
|
977 | + * @throws EE_Error |
|
978 | + * @throws InvalidArgumentException |
|
979 | + * @throws InvalidDataTypeException |
|
980 | + * @throws InvalidInterfaceException |
|
981 | + */ |
|
982 | + public function clear_session($class = '', $function = '') |
|
983 | + { |
|
984 | + do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()'); |
|
985 | + $this->reset_cart(); |
|
986 | + $this->reset_checkout(); |
|
987 | + $this->reset_transaction(); |
|
988 | + // wipe out everything that isn't a default session datum |
|
989 | + $this->reset_data(array_keys($this->_session_data)); |
|
990 | + // reset initial site access time and the session expiration |
|
991 | + $this->_set_init_access_and_expiration(); |
|
992 | + $this->_save_session_to_db(); |
|
993 | + } |
|
994 | + |
|
995 | + |
|
996 | + |
|
997 | + /** |
|
998 | + * @resets all non-default session vars |
|
999 | + * @access public |
|
1000 | + * @param array|mixed $data_to_reset |
|
1001 | + * @param bool $show_all_notices |
|
1002 | + * @return TRUE on success, FALSE on fail |
|
1003 | + */ |
|
1004 | + public function reset_data($data_to_reset = array(), $show_all_notices = false) |
|
1005 | + { |
|
1006 | + // if $data_to_reset is not in an array, then put it in one |
|
1007 | + if (! is_array($data_to_reset)) { |
|
1008 | + $data_to_reset = array($data_to_reset); |
|
1009 | + } |
|
1010 | + // nothing ??? go home! |
|
1011 | + if (empty($data_to_reset)) { |
|
1012 | + EE_Error::add_error(__('No session data could be reset, because no session var name was provided.', |
|
1013 | + 'event_espresso'), __FILE__, __FUNCTION__, __LINE__); |
|
1014 | + return false; |
|
1015 | + } |
|
1016 | + $return_value = true; |
|
1017 | + // since $data_to_reset is an array, cycle through the values |
|
1018 | + foreach ($data_to_reset as $reset) { |
|
1019 | + |
|
1020 | + // first check to make sure it is a valid session var |
|
1021 | + if (isset($this->_session_data[ $reset ])) { |
|
1022 | + // then check to make sure it is not a default var |
|
1023 | + if (! array_key_exists($reset, $this->_default_session_vars)) { |
|
1024 | + // remove session var |
|
1025 | + unset($this->_session_data[ $reset ]); |
|
1026 | + if ($show_all_notices) { |
|
1027 | + EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'), |
|
1028 | + $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1029 | + } |
|
1030 | + } else { |
|
1031 | + // yeeeeeeeeerrrrrrrrrrr OUT !!!! |
|
1032 | + if ($show_all_notices) { |
|
1033 | + EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.', |
|
1034 | + 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1035 | + } |
|
1036 | + $return_value = false; |
|
1037 | + } |
|
1038 | + } elseif ($show_all_notices) { |
|
1039 | + // oops! that session var does not exist! |
|
1040 | + EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.', |
|
1041 | + 'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__); |
|
1042 | + $return_value = false; |
|
1043 | + } |
|
1044 | + } // end of foreach |
|
1045 | + return $return_value; |
|
1046 | + } |
|
1047 | + |
|
1048 | + |
|
1049 | + |
|
1050 | + /** |
|
1051 | + * wp_loaded |
|
1052 | + * |
|
1053 | + * @access public |
|
1054 | + * @throws EE_Error |
|
1055 | + * @throws InvalidDataTypeException |
|
1056 | + * @throws InvalidInterfaceException |
|
1057 | + * @throws InvalidArgumentException |
|
1058 | + */ |
|
1059 | + public function wp_loaded() |
|
1060 | + { |
|
1061 | + if ($this->request->is_set('clear_session')) { |
|
1062 | + $this->clear_session(__CLASS__, __FUNCTION__); |
|
1063 | + } |
|
1064 | + } |
|
1065 | + |
|
1066 | + |
|
1067 | + |
|
1068 | + /** |
|
1069 | + * Used to reset the entire object (for tests). |
|
1070 | + * |
|
1071 | + * @since 4.3.0 |
|
1072 | + * @throws EE_Error |
|
1073 | + * @throws InvalidDataTypeException |
|
1074 | + * @throws InvalidInterfaceException |
|
1075 | + * @throws InvalidArgumentException |
|
1076 | + */ |
|
1077 | + public function reset_instance() |
|
1078 | + { |
|
1079 | + $this->clear_session(); |
|
1080 | + self::$_instance = null; |
|
1081 | + } |
|
1082 | + |
|
1083 | + |
|
1084 | + |
|
1085 | + public function configure_garbage_collection_filters() |
|
1086 | + { |
|
1087 | + // run old filter we had for controlling session cleanup |
|
1088 | + $expired_session_transient_delete_query_limit = absint( |
|
1089 | + apply_filters( |
|
1090 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1091 | + 50 |
|
1092 | + ) |
|
1093 | + ); |
|
1094 | + // is there a value? or one that is different than the default 50 records? |
|
1095 | + if ($expired_session_transient_delete_query_limit === 0) { |
|
1096 | + // hook into TransientCacheStorage in case Session cleanup was turned off |
|
1097 | + add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero'); |
|
1098 | + } elseif ($expired_session_transient_delete_query_limit !== 50) { |
|
1099 | + // or use that for the new transient cleanup query limit |
|
1100 | + add_filter( |
|
1101 | + 'FHEE__TransientCacheStorage__clearExpiredTransients__limit', |
|
1102 | + function () use ($expired_session_transient_delete_query_limit) |
|
1103 | + { |
|
1104 | + return $expired_session_transient_delete_query_limit; |
|
1105 | + } |
|
1106 | + ); |
|
1107 | + } |
|
1108 | + } |
|
1109 | + |
|
1110 | + |
|
1111 | + |
|
1112 | + /** |
|
1113 | + * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996 |
|
1114 | + * @param $data1 |
|
1115 | + * @return string |
|
1116 | + */ |
|
1117 | + private function find_serialize_error($data1) |
|
1118 | + { |
|
1119 | + $error = '<pre>'; |
|
1120 | + $data2 = preg_replace_callback( |
|
1121 | + '!s:(\d+):"(.*?)";!', |
|
1122 | + function ($match) |
|
1123 | + { |
|
1124 | + return ($match[1] === strlen($match[2])) |
|
1125 | + ? $match[0] |
|
1126 | + : 's:' |
|
1127 | + . strlen($match[2]) |
|
1128 | + . ':"' |
|
1129 | + . $match[2] |
|
1130 | + . '";'; |
|
1131 | + }, |
|
1132 | + $data1 |
|
1133 | + ); |
|
1134 | + $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2); |
|
1135 | + $error .= $data1 . PHP_EOL; |
|
1136 | + $error .= $data2 . PHP_EOL; |
|
1137 | + for ($i = 0; $i < $max; $i++) { |
|
1138 | + if (@$data1[ $i ] !== @$data2[ $i ]) { |
|
1139 | + $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL; |
|
1140 | + $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL; |
|
1141 | + $error .= "\t-> Line Number = $i" . PHP_EOL; |
|
1142 | + $start = ($i - 20); |
|
1143 | + $start = ($start < 0) ? 0 : $start; |
|
1144 | + $length = 40; |
|
1145 | + $point = $max - $i; |
|
1146 | + if ($point < 20) { |
|
1147 | + $rlength = 1; |
|
1148 | + $rpoint = -$point; |
|
1149 | + } else { |
|
1150 | + $rpoint = $length - 20; |
|
1151 | + $rlength = 1; |
|
1152 | + } |
|
1153 | + $error .= "\t-> Section Data1 = "; |
|
1154 | + $error .= substr_replace( |
|
1155 | + substr($data1, $start, $length), |
|
1156 | + "<b style=\"color:green\">{$data1[ $i ]}</b>", |
|
1157 | + $rpoint, |
|
1158 | + $rlength |
|
1159 | + ); |
|
1160 | + $error .= PHP_EOL; |
|
1161 | + $error .= "\t-> Section Data2 = "; |
|
1162 | + $error .= substr_replace( |
|
1163 | + substr($data2, $start, $length), |
|
1164 | + "<b style=\"color:red\">{$data2[ $i ]}</b>", |
|
1165 | + $rpoint, |
|
1166 | + $rlength |
|
1167 | + ); |
|
1168 | + $error .= PHP_EOL; |
|
1169 | + } |
|
1170 | + } |
|
1171 | + $error .= '</pre>'; |
|
1172 | + return $error; |
|
1173 | + } |
|
1174 | + |
|
1175 | + |
|
1176 | + /** |
|
1177 | + * Saves an array of settings used for configuring aspects of session behaviour |
|
1178 | + * |
|
1179 | + * @param array $updated_settings |
|
1180 | + */ |
|
1181 | + private function updateSessionSettings(array $updated_settings = array()) |
|
1182 | + { |
|
1183 | + // add existing settings, but only if not included in incoming $updated_settings array |
|
1184 | + $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array()); |
|
1185 | + update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings); |
|
1186 | + } |
|
1187 | + |
|
1188 | + |
|
1189 | + /** |
|
1190 | + * garbage_collection |
|
1191 | + */ |
|
1192 | + public function garbageCollection() |
|
1193 | + { |
|
1194 | + // only perform during regular requests if last garbage collection was over an hour ago |
|
1195 | + if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) { |
|
1196 | + $this->_last_gc = time(); |
|
1197 | + $this->updateSessionSettings(array('last_gc' => $this->_last_gc)); |
|
1198 | + /** @type WPDB $wpdb */ |
|
1199 | + global $wpdb; |
|
1200 | + // filter the query limit. Set to 0 to turn off garbage collection |
|
1201 | + $expired_session_transient_delete_query_limit = absint( |
|
1202 | + apply_filters( |
|
1203 | + 'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit', |
|
1204 | + 50 |
|
1205 | + ) |
|
1206 | + ); |
|
1207 | + // non-zero LIMIT means take out the trash |
|
1208 | + if ($expired_session_transient_delete_query_limit) { |
|
1209 | + $session_key = str_replace('_', '\_', EE_Session::session_id_prefix); |
|
1210 | + $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix); |
|
1211 | + // since transient expiration timestamps are set in the future, we can compare against NOW |
|
1212 | + // but we only want to pick up any trash that's been around for more than a day |
|
1213 | + $expiration = time() - DAY_IN_SECONDS; |
|
1214 | + $SQL = " |
|
1215 | 1215 | SELECT option_name |
1216 | 1216 | FROM {$wpdb->options} |
1217 | 1217 | WHERE |
@@ -1220,19 +1220,19 @@ discard block |
||
1220 | 1220 | AND option_value < {$expiration} |
1221 | 1221 | LIMIT {$expired_session_transient_delete_query_limit} |
1222 | 1222 | "; |
1223 | - // produces something like: |
|
1224 | - // SELECT option_name FROM wp_options |
|
1225 | - // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1226 | - // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1227 | - // AND option_value < 1508368198 LIMIT 50 |
|
1228 | - $expired_sessions = $wpdb->get_col($SQL); |
|
1229 | - // valid results? |
|
1230 | - if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1231 | - $this->cache_storage->deleteMany($expired_sessions, true); |
|
1232 | - } |
|
1233 | - } |
|
1234 | - } |
|
1235 | - } |
|
1223 | + // produces something like: |
|
1224 | + // SELECT option_name FROM wp_options |
|
1225 | + // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%' |
|
1226 | + // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' ) |
|
1227 | + // AND option_value < 1508368198 LIMIT 50 |
|
1228 | + $expired_sessions = $wpdb->get_col($SQL); |
|
1229 | + // valid results? |
|
1230 | + if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) { |
|
1231 | + $this->cache_storage->deleteMany($expired_sessions, true); |
|
1232 | + } |
|
1233 | + } |
|
1234 | + } |
|
1235 | + } |
|
1236 | 1236 | |
1237 | 1237 | |
1238 | 1238 |
@@ -32,76 +32,76 @@ |
||
32 | 32 | class CoreLoader implements LoaderDecoratorInterface |
33 | 33 | { |
34 | 34 | |
35 | - /** |
|
36 | - * @var EE_Registry|CoffeeShop $generator |
|
37 | - */ |
|
38 | - private $generator; |
|
39 | - |
|
40 | - |
|
41 | - |
|
42 | - /** |
|
43 | - * CoreLoader constructor. |
|
44 | - * |
|
45 | - * @param EE_Registry|CoffeeShop $generator |
|
46 | - * @throws InvalidArgumentException |
|
47 | - */ |
|
48 | - public function __construct($generator) |
|
49 | - { |
|
50 | - if(!($generator instanceof EE_Registry || $generator instanceof CoffeeShop)) { |
|
51 | - throw new InvalidArgumentException( |
|
52 | - esc_html__( |
|
53 | - 'The CoreLoader class must receive an instance of EE_Registry or the CoffeeShop DI container.', |
|
54 | - 'event_espresso' |
|
55 | - ) |
|
56 | - ); |
|
57 | - } |
|
58 | - $this->generator = $generator; |
|
59 | - } |
|
60 | - |
|
61 | - |
|
62 | - |
|
63 | - /** |
|
64 | - * @param string $fqcn |
|
65 | - * @param array $arguments |
|
66 | - * @param bool $shared |
|
67 | - * @return mixed |
|
68 | - * @throws OutOfBoundsException |
|
69 | - * @throws ServiceExistsException |
|
70 | - * @throws InstantiationException |
|
71 | - * @throws InvalidIdentifierException |
|
72 | - * @throws InvalidDataTypeException |
|
73 | - * @throws InvalidClassException |
|
74 | - * @throws EE_Error |
|
75 | - * @throws ServiceNotFoundException |
|
76 | - * @throws ReflectionException |
|
77 | - */ |
|
78 | - public function load($fqcn, $arguments = array(), $shared = true) |
|
79 | - { |
|
80 | - if($this->generator instanceof EE_Registry) { |
|
81 | - return $this->generator->create($fqcn, $arguments, $shared); |
|
82 | - } |
|
83 | - return $this->generator->brew( |
|
84 | - $fqcn, |
|
85 | - $arguments, |
|
86 | - $shared ? CoffeeMaker::BREW_SHARED : CoffeeMaker::BREW_NEW |
|
87 | - ); |
|
88 | - |
|
89 | - } |
|
90 | - |
|
91 | - |
|
92 | - |
|
93 | - /** |
|
94 | - * calls reset() on generator if method exists |
|
95 | - * |
|
96 | - * @throws EE_Error |
|
97 | - * @throws ReflectionException |
|
98 | - */ |
|
99 | - public function reset() |
|
100 | - { |
|
101 | - if ($this->generator instanceof EE_Registry) { |
|
102 | - EE_Registry::reset(); |
|
103 | - } |
|
104 | - } |
|
35 | + /** |
|
36 | + * @var EE_Registry|CoffeeShop $generator |
|
37 | + */ |
|
38 | + private $generator; |
|
39 | + |
|
40 | + |
|
41 | + |
|
42 | + /** |
|
43 | + * CoreLoader constructor. |
|
44 | + * |
|
45 | + * @param EE_Registry|CoffeeShop $generator |
|
46 | + * @throws InvalidArgumentException |
|
47 | + */ |
|
48 | + public function __construct($generator) |
|
49 | + { |
|
50 | + if(!($generator instanceof EE_Registry || $generator instanceof CoffeeShop)) { |
|
51 | + throw new InvalidArgumentException( |
|
52 | + esc_html__( |
|
53 | + 'The CoreLoader class must receive an instance of EE_Registry or the CoffeeShop DI container.', |
|
54 | + 'event_espresso' |
|
55 | + ) |
|
56 | + ); |
|
57 | + } |
|
58 | + $this->generator = $generator; |
|
59 | + } |
|
60 | + |
|
61 | + |
|
62 | + |
|
63 | + /** |
|
64 | + * @param string $fqcn |
|
65 | + * @param array $arguments |
|
66 | + * @param bool $shared |
|
67 | + * @return mixed |
|
68 | + * @throws OutOfBoundsException |
|
69 | + * @throws ServiceExistsException |
|
70 | + * @throws InstantiationException |
|
71 | + * @throws InvalidIdentifierException |
|
72 | + * @throws InvalidDataTypeException |
|
73 | + * @throws InvalidClassException |
|
74 | + * @throws EE_Error |
|
75 | + * @throws ServiceNotFoundException |
|
76 | + * @throws ReflectionException |
|
77 | + */ |
|
78 | + public function load($fqcn, $arguments = array(), $shared = true) |
|
79 | + { |
|
80 | + if($this->generator instanceof EE_Registry) { |
|
81 | + return $this->generator->create($fqcn, $arguments, $shared); |
|
82 | + } |
|
83 | + return $this->generator->brew( |
|
84 | + $fqcn, |
|
85 | + $arguments, |
|
86 | + $shared ? CoffeeMaker::BREW_SHARED : CoffeeMaker::BREW_NEW |
|
87 | + ); |
|
88 | + |
|
89 | + } |
|
90 | + |
|
91 | + |
|
92 | + |
|
93 | + /** |
|
94 | + * calls reset() on generator if method exists |
|
95 | + * |
|
96 | + * @throws EE_Error |
|
97 | + * @throws ReflectionException |
|
98 | + */ |
|
99 | + public function reset() |
|
100 | + { |
|
101 | + if ($this->generator instanceof EE_Registry) { |
|
102 | + EE_Registry::reset(); |
|
103 | + } |
|
104 | + } |
|
105 | 105 | |
106 | 106 | } |
107 | 107 | // End of file CoreLoader.php |
@@ -47,7 +47,7 @@ discard block |
||
47 | 47 | */ |
48 | 48 | public function __construct($generator) |
49 | 49 | { |
50 | - if(!($generator instanceof EE_Registry || $generator instanceof CoffeeShop)) { |
|
50 | + if ( ! ($generator instanceof EE_Registry || $generator instanceof CoffeeShop)) { |
|
51 | 51 | throw new InvalidArgumentException( |
52 | 52 | esc_html__( |
53 | 53 | 'The CoreLoader class must receive an instance of EE_Registry or the CoffeeShop DI container.', |
@@ -77,7 +77,7 @@ discard block |
||
77 | 77 | */ |
78 | 78 | public function load($fqcn, $arguments = array(), $shared = true) |
79 | 79 | { |
80 | - if($this->generator instanceof EE_Registry) { |
|
80 | + if ($this->generator instanceof EE_Registry) { |
|
81 | 81 | return $this->generator->create($fqcn, $arguments, $shared); |
82 | 82 | } |
83 | 83 | return $this->generator->brew( |
@@ -8,7 +8,7 @@ discard block |
||
8 | 8 | use UnexpectedValueException; |
9 | 9 | |
10 | 10 | if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
11 | - exit('No direct script access allowed'); |
|
11 | + exit('No direct script access allowed'); |
|
12 | 12 | } |
13 | 13 | |
14 | 14 | |
@@ -26,223 +26,223 @@ discard block |
||
26 | 26 | class DependencyInjector implements InjectorInterface |
27 | 27 | { |
28 | 28 | |
29 | - /** |
|
30 | - * @var CoffeePotInterface $coffee_pot |
|
31 | - */ |
|
32 | - private $coffee_pot; |
|
33 | - |
|
34 | - /** |
|
35 | - * @var EEH_Array $array_helper |
|
36 | - */ |
|
37 | - private $array_helper; |
|
38 | - |
|
39 | - /** |
|
40 | - * @var ReflectionClass[] $reflectors |
|
41 | - */ |
|
42 | - private $reflectors; |
|
43 | - |
|
44 | - /** |
|
45 | - * @var ReflectionMethod[] $constructors |
|
46 | - */ |
|
47 | - private $constructors; |
|
48 | - |
|
49 | - /** |
|
50 | - * @var ReflectionParameter[] $parameters |
|
51 | - */ |
|
52 | - private $parameters; |
|
53 | - |
|
54 | - |
|
55 | - |
|
56 | - /** |
|
57 | - * DependencyInjector constructor |
|
58 | - * |
|
59 | - * @param CoffeePotInterface $coffee_pot |
|
60 | - * @param EEH_Array $array_helper |
|
61 | - */ |
|
62 | - public function __construct(CoffeePotInterface $coffee_pot, EEH_Array $array_helper) |
|
63 | - { |
|
64 | - $this->coffee_pot = $coffee_pot; |
|
65 | - $this->array_helper = $array_helper; |
|
66 | - } |
|
67 | - |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * getReflectionClass |
|
72 | - * checks if a ReflectionClass object has already been generated for a class |
|
73 | - * and returns that instead of creating a new one |
|
74 | - * |
|
75 | - * @param string $class_name |
|
76 | - * @return ReflectionClass |
|
77 | - */ |
|
78 | - public function getReflectionClass($class_name) |
|
79 | - { |
|
80 | - if ( |
|
81 | - ! isset($this->reflectors[$class_name]) |
|
82 | - || ! $this->reflectors[$class_name] instanceof ReflectionClass |
|
83 | - ) { |
|
84 | - $this->reflectors[$class_name] = new ReflectionClass($class_name); |
|
85 | - } |
|
86 | - return $this->reflectors[$class_name]; |
|
87 | - } |
|
88 | - |
|
89 | - |
|
90 | - |
|
91 | - /** |
|
92 | - * getConstructor |
|
93 | - * checks if a ReflectionMethod object has already been generated for the class constructor |
|
94 | - * and returns that instead of creating a new one |
|
95 | - * |
|
96 | - * @param ReflectionClass $reflector |
|
97 | - * @return ReflectionMethod |
|
98 | - */ |
|
99 | - protected function getConstructor(ReflectionClass $reflector) |
|
100 | - { |
|
101 | - if ( |
|
102 | - ! isset($this->constructors[$reflector->getName()]) |
|
103 | - || ! $this->constructors[$reflector->getName()] instanceof ReflectionMethod |
|
104 | - ) { |
|
105 | - $this->constructors[$reflector->getName()] = $reflector->getConstructor(); |
|
106 | - } |
|
107 | - return $this->constructors[$reflector->getName()]; |
|
108 | - } |
|
109 | - |
|
110 | - |
|
111 | - |
|
112 | - /** |
|
113 | - * getParameters |
|
114 | - * checks if an array of ReflectionParameter objects has already been generated for the class constructor |
|
115 | - * and returns that instead of creating a new one |
|
116 | - * |
|
117 | - * @param ReflectionMethod $constructor |
|
118 | - * @return ReflectionParameter[] |
|
119 | - */ |
|
120 | - protected function getParameters(ReflectionMethod $constructor) |
|
121 | - { |
|
122 | - if ( ! isset($this->parameters[$constructor->class])) { |
|
123 | - $this->parameters[$constructor->class] = $constructor->getParameters(); |
|
124 | - } |
|
125 | - return $this->parameters[$constructor->class]; |
|
126 | - } |
|
127 | - |
|
128 | - |
|
129 | - |
|
130 | - /** |
|
131 | - * resolveDependencies |
|
132 | - * examines the constructor for the requested class to determine |
|
133 | - * if any dependencies exist, and if they can be injected. |
|
134 | - * If so, then those classes will be added to the array of arguments passed to the constructor |
|
135 | - * PLZ NOTE: this is achieved by type hinting the constructor params |
|
136 | - * For example: |
|
137 | - * if attempting to load a class "Foo" with the following constructor: |
|
138 | - * __construct( Bar $bar_class, Fighter $grohl_class ) |
|
139 | - * then $bar_class and $grohl_class will be added to the $arguments array, |
|
140 | - * but only IF they are NOT already present in the incoming arguments array, |
|
141 | - * and the correct classes can be loaded |
|
142 | - * |
|
143 | - * @param RecipeInterface $recipe |
|
144 | - * @param ReflectionClass $reflector |
|
145 | - * @param array $arguments |
|
146 | - * @return array |
|
147 | - * @throws UnexpectedValueException |
|
148 | - */ |
|
149 | - public function resolveDependencies(RecipeInterface $recipe, ReflectionClass $reflector, $arguments = array()) |
|
150 | - { |
|
151 | - // if arguments array is numerically and sequentially indexed, then we want it to remain as is, |
|
152 | - // else wrap it in an additional array so that it doesn't get split into multiple parameters |
|
153 | - $arguments = $this->array_helper->is_array_numerically_and_sequentially_indexed($arguments) |
|
154 | - ? $arguments |
|
155 | - : array($arguments); |
|
156 | - $resolved_parameters = array(); |
|
157 | - // let's examine the constructor |
|
158 | - // let's examine the constructor |
|
159 | - $constructor = $this->getConstructor($reflector); |
|
160 | - // whu? huh? nothing? |
|
161 | - if ( ! $constructor) { |
|
162 | - return $arguments; |
|
163 | - } |
|
164 | - // get constructor parameters |
|
165 | - $params = $this->getParameters($constructor); |
|
166 | - if (empty($params)) { |
|
167 | - return $resolved_parameters; |
|
168 | - } |
|
169 | - $ingredients = $recipe->ingredients(); |
|
170 | - // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected |
|
171 | - $argument_keys = array_keys($arguments); |
|
172 | - // now loop thru all of the constructors expected parameters |
|
173 | - foreach ($params as $index => $param) { |
|
174 | - if ( ! $param instanceof ReflectionParameter) { |
|
175 | - continue; |
|
176 | - } |
|
177 | - // is this a dependency for a specific class ? |
|
178 | - $param_class = $param->getClass() ? $param->getClass()->name : ''; |
|
179 | - $param_name = $param->getName() ? $param->getName() : ''; |
|
180 | - if ( |
|
181 | - // param is not a class but is specified in the list of ingredients for this Recipe |
|
182 | - is_string($param_name) && isset($ingredients[$param_name]) |
|
183 | - ) { |
|
184 | - // attempt to inject the dependency |
|
185 | - $resolved_parameters[$index] = $ingredients[ $param_name ]; |
|
186 | - } else if ( |
|
187 | - // param is specified in the list of ingredients for this Recipe |
|
188 | - isset($ingredients[$param_class]) |
|
189 | - ) { |
|
190 | - // attempt to inject the dependency |
|
191 | - $resolved_parameters[$index] = $this->injectDependency($ingredients[$param_class]); |
|
192 | - } else if ( |
|
193 | - // param is not even a class |
|
194 | - empty($param_class) |
|
195 | - // and something already exists in the incoming arguments for this param |
|
196 | - && isset($argument_keys[$index], $arguments[$argument_keys[$index]]) |
|
197 | - ) { |
|
198 | - // add parameter from incoming arguments |
|
199 | - $resolved_parameters[$index] = $arguments[$argument_keys[$index]]; |
|
200 | - } else if ( |
|
201 | - // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class |
|
202 | - ! empty($param_class) |
|
203 | - && isset($argument_keys[$index], $arguments[$argument_keys[$index]]) |
|
204 | - && $arguments[$argument_keys[$index]] instanceof $param_class |
|
205 | - ) { |
|
206 | - // add parameter from incoming arguments |
|
207 | - $resolved_parameters[$index] = $arguments[$argument_keys[$index]]; |
|
208 | - } else if ( |
|
209 | - // parameter is type hinted as a class, and should be injected |
|
210 | - ! empty($param_class) |
|
211 | - ) { |
|
212 | - // attempt to inject the dependency |
|
213 | - $resolved_parameters[$index] = $this->injectDependency($param_class); |
|
214 | - } else if ($param->isOptional()) { |
|
215 | - $resolved_parameters[$index] = $param->getDefaultValue(); |
|
216 | - } else { |
|
217 | - $resolved_parameters[$index] = null; |
|
218 | - } |
|
219 | - } |
|
220 | - return $resolved_parameters; |
|
221 | - } |
|
222 | - |
|
223 | - |
|
224 | - |
|
225 | - /** |
|
226 | - * @param string $param_class |
|
227 | - * @return mixed |
|
228 | - * @throws UnexpectedValueException |
|
229 | - */ |
|
230 | - private function injectDependency($param_class) |
|
231 | - { |
|
232 | - $dependency = $this->coffee_pot->brew($param_class); |
|
233 | - if ( ! $dependency instanceof $param_class) { |
|
234 | - throw new UnexpectedValueException( |
|
235 | - sprintf( |
|
236 | - __( |
|
237 | - 'Could not resolve dependency for "%1$s" for the "%2$s" class constructor.', |
|
238 | - 'event_espresso' |
|
239 | - ), |
|
240 | - $param_class |
|
241 | - ) |
|
242 | - ); |
|
243 | - } |
|
244 | - return $dependency; |
|
245 | - } |
|
29 | + /** |
|
30 | + * @var CoffeePotInterface $coffee_pot |
|
31 | + */ |
|
32 | + private $coffee_pot; |
|
33 | + |
|
34 | + /** |
|
35 | + * @var EEH_Array $array_helper |
|
36 | + */ |
|
37 | + private $array_helper; |
|
38 | + |
|
39 | + /** |
|
40 | + * @var ReflectionClass[] $reflectors |
|
41 | + */ |
|
42 | + private $reflectors; |
|
43 | + |
|
44 | + /** |
|
45 | + * @var ReflectionMethod[] $constructors |
|
46 | + */ |
|
47 | + private $constructors; |
|
48 | + |
|
49 | + /** |
|
50 | + * @var ReflectionParameter[] $parameters |
|
51 | + */ |
|
52 | + private $parameters; |
|
53 | + |
|
54 | + |
|
55 | + |
|
56 | + /** |
|
57 | + * DependencyInjector constructor |
|
58 | + * |
|
59 | + * @param CoffeePotInterface $coffee_pot |
|
60 | + * @param EEH_Array $array_helper |
|
61 | + */ |
|
62 | + public function __construct(CoffeePotInterface $coffee_pot, EEH_Array $array_helper) |
|
63 | + { |
|
64 | + $this->coffee_pot = $coffee_pot; |
|
65 | + $this->array_helper = $array_helper; |
|
66 | + } |
|
67 | + |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * getReflectionClass |
|
72 | + * checks if a ReflectionClass object has already been generated for a class |
|
73 | + * and returns that instead of creating a new one |
|
74 | + * |
|
75 | + * @param string $class_name |
|
76 | + * @return ReflectionClass |
|
77 | + */ |
|
78 | + public function getReflectionClass($class_name) |
|
79 | + { |
|
80 | + if ( |
|
81 | + ! isset($this->reflectors[$class_name]) |
|
82 | + || ! $this->reflectors[$class_name] instanceof ReflectionClass |
|
83 | + ) { |
|
84 | + $this->reflectors[$class_name] = new ReflectionClass($class_name); |
|
85 | + } |
|
86 | + return $this->reflectors[$class_name]; |
|
87 | + } |
|
88 | + |
|
89 | + |
|
90 | + |
|
91 | + /** |
|
92 | + * getConstructor |
|
93 | + * checks if a ReflectionMethod object has already been generated for the class constructor |
|
94 | + * and returns that instead of creating a new one |
|
95 | + * |
|
96 | + * @param ReflectionClass $reflector |
|
97 | + * @return ReflectionMethod |
|
98 | + */ |
|
99 | + protected function getConstructor(ReflectionClass $reflector) |
|
100 | + { |
|
101 | + if ( |
|
102 | + ! isset($this->constructors[$reflector->getName()]) |
|
103 | + || ! $this->constructors[$reflector->getName()] instanceof ReflectionMethod |
|
104 | + ) { |
|
105 | + $this->constructors[$reflector->getName()] = $reflector->getConstructor(); |
|
106 | + } |
|
107 | + return $this->constructors[$reflector->getName()]; |
|
108 | + } |
|
109 | + |
|
110 | + |
|
111 | + |
|
112 | + /** |
|
113 | + * getParameters |
|
114 | + * checks if an array of ReflectionParameter objects has already been generated for the class constructor |
|
115 | + * and returns that instead of creating a new one |
|
116 | + * |
|
117 | + * @param ReflectionMethod $constructor |
|
118 | + * @return ReflectionParameter[] |
|
119 | + */ |
|
120 | + protected function getParameters(ReflectionMethod $constructor) |
|
121 | + { |
|
122 | + if ( ! isset($this->parameters[$constructor->class])) { |
|
123 | + $this->parameters[$constructor->class] = $constructor->getParameters(); |
|
124 | + } |
|
125 | + return $this->parameters[$constructor->class]; |
|
126 | + } |
|
127 | + |
|
128 | + |
|
129 | + |
|
130 | + /** |
|
131 | + * resolveDependencies |
|
132 | + * examines the constructor for the requested class to determine |
|
133 | + * if any dependencies exist, and if they can be injected. |
|
134 | + * If so, then those classes will be added to the array of arguments passed to the constructor |
|
135 | + * PLZ NOTE: this is achieved by type hinting the constructor params |
|
136 | + * For example: |
|
137 | + * if attempting to load a class "Foo" with the following constructor: |
|
138 | + * __construct( Bar $bar_class, Fighter $grohl_class ) |
|
139 | + * then $bar_class and $grohl_class will be added to the $arguments array, |
|
140 | + * but only IF they are NOT already present in the incoming arguments array, |
|
141 | + * and the correct classes can be loaded |
|
142 | + * |
|
143 | + * @param RecipeInterface $recipe |
|
144 | + * @param ReflectionClass $reflector |
|
145 | + * @param array $arguments |
|
146 | + * @return array |
|
147 | + * @throws UnexpectedValueException |
|
148 | + */ |
|
149 | + public function resolveDependencies(RecipeInterface $recipe, ReflectionClass $reflector, $arguments = array()) |
|
150 | + { |
|
151 | + // if arguments array is numerically and sequentially indexed, then we want it to remain as is, |
|
152 | + // else wrap it in an additional array so that it doesn't get split into multiple parameters |
|
153 | + $arguments = $this->array_helper->is_array_numerically_and_sequentially_indexed($arguments) |
|
154 | + ? $arguments |
|
155 | + : array($arguments); |
|
156 | + $resolved_parameters = array(); |
|
157 | + // let's examine the constructor |
|
158 | + // let's examine the constructor |
|
159 | + $constructor = $this->getConstructor($reflector); |
|
160 | + // whu? huh? nothing? |
|
161 | + if ( ! $constructor) { |
|
162 | + return $arguments; |
|
163 | + } |
|
164 | + // get constructor parameters |
|
165 | + $params = $this->getParameters($constructor); |
|
166 | + if (empty($params)) { |
|
167 | + return $resolved_parameters; |
|
168 | + } |
|
169 | + $ingredients = $recipe->ingredients(); |
|
170 | + // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected |
|
171 | + $argument_keys = array_keys($arguments); |
|
172 | + // now loop thru all of the constructors expected parameters |
|
173 | + foreach ($params as $index => $param) { |
|
174 | + if ( ! $param instanceof ReflectionParameter) { |
|
175 | + continue; |
|
176 | + } |
|
177 | + // is this a dependency for a specific class ? |
|
178 | + $param_class = $param->getClass() ? $param->getClass()->name : ''; |
|
179 | + $param_name = $param->getName() ? $param->getName() : ''; |
|
180 | + if ( |
|
181 | + // param is not a class but is specified in the list of ingredients for this Recipe |
|
182 | + is_string($param_name) && isset($ingredients[$param_name]) |
|
183 | + ) { |
|
184 | + // attempt to inject the dependency |
|
185 | + $resolved_parameters[$index] = $ingredients[ $param_name ]; |
|
186 | + } else if ( |
|
187 | + // param is specified in the list of ingredients for this Recipe |
|
188 | + isset($ingredients[$param_class]) |
|
189 | + ) { |
|
190 | + // attempt to inject the dependency |
|
191 | + $resolved_parameters[$index] = $this->injectDependency($ingredients[$param_class]); |
|
192 | + } else if ( |
|
193 | + // param is not even a class |
|
194 | + empty($param_class) |
|
195 | + // and something already exists in the incoming arguments for this param |
|
196 | + && isset($argument_keys[$index], $arguments[$argument_keys[$index]]) |
|
197 | + ) { |
|
198 | + // add parameter from incoming arguments |
|
199 | + $resolved_parameters[$index] = $arguments[$argument_keys[$index]]; |
|
200 | + } else if ( |
|
201 | + // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class |
|
202 | + ! empty($param_class) |
|
203 | + && isset($argument_keys[$index], $arguments[$argument_keys[$index]]) |
|
204 | + && $arguments[$argument_keys[$index]] instanceof $param_class |
|
205 | + ) { |
|
206 | + // add parameter from incoming arguments |
|
207 | + $resolved_parameters[$index] = $arguments[$argument_keys[$index]]; |
|
208 | + } else if ( |
|
209 | + // parameter is type hinted as a class, and should be injected |
|
210 | + ! empty($param_class) |
|
211 | + ) { |
|
212 | + // attempt to inject the dependency |
|
213 | + $resolved_parameters[$index] = $this->injectDependency($param_class); |
|
214 | + } else if ($param->isOptional()) { |
|
215 | + $resolved_parameters[$index] = $param->getDefaultValue(); |
|
216 | + } else { |
|
217 | + $resolved_parameters[$index] = null; |
|
218 | + } |
|
219 | + } |
|
220 | + return $resolved_parameters; |
|
221 | + } |
|
222 | + |
|
223 | + |
|
224 | + |
|
225 | + /** |
|
226 | + * @param string $param_class |
|
227 | + * @return mixed |
|
228 | + * @throws UnexpectedValueException |
|
229 | + */ |
|
230 | + private function injectDependency($param_class) |
|
231 | + { |
|
232 | + $dependency = $this->coffee_pot->brew($param_class); |
|
233 | + if ( ! $dependency instanceof $param_class) { |
|
234 | + throw new UnexpectedValueException( |
|
235 | + sprintf( |
|
236 | + __( |
|
237 | + 'Could not resolve dependency for "%1$s" for the "%2$s" class constructor.', |
|
238 | + 'event_espresso' |
|
239 | + ), |
|
240 | + $param_class |
|
241 | + ) |
|
242 | + ); |
|
243 | + } |
|
244 | + return $dependency; |
|
245 | + } |
|
246 | 246 | |
247 | 247 | } |
248 | 248 | // End of file DependencyInjector.php |
@@ -182,7 +182,7 @@ |
||
182 | 182 | is_string($param_name) && isset($ingredients[$param_name]) |
183 | 183 | ) { |
184 | 184 | // attempt to inject the dependency |
185 | - $resolved_parameters[$index] = $ingredients[ $param_name ]; |
|
185 | + $resolved_parameters[$index] = $ingredients[$param_name]; |
|
186 | 186 | } else if ( |
187 | 187 | // param is specified in the list of ingredients for this Recipe |
188 | 188 | isset($ingredients[$param_class]) |
@@ -8,7 +8,7 @@ discard block |
||
8 | 8 | use RuntimeException; |
9 | 9 | |
10 | 10 | if ( ! defined('EVENT_ESPRESSO_VERSION')) { |
11 | - exit('No direct script access allowed'); |
|
11 | + exit('No direct script access allowed'); |
|
12 | 12 | } |
13 | 13 | |
14 | 14 | |
@@ -24,326 +24,326 @@ discard block |
||
24 | 24 | class Recipe implements RecipeInterface |
25 | 25 | { |
26 | 26 | |
27 | - /** |
|
28 | - * A default Recipe to use if none is specified for a class |
|
29 | - */ |
|
30 | - const DEFAULT_ID = '*'; |
|
31 | - |
|
32 | - /** |
|
33 | - * Identifier for the entity class to be constructed. |
|
34 | - * Typically a Fully Qualified Class Name |
|
35 | - * |
|
36 | - * @var string $identifier |
|
37 | - */ |
|
38 | - private $identifier; |
|
39 | - |
|
40 | - /** |
|
41 | - * Fully Qualified Class Name |
|
42 | - * |
|
43 | - * @var string $fqcn |
|
44 | - */ |
|
45 | - private $fqcn; |
|
46 | - |
|
47 | - /** |
|
48 | - * a dependency class map array |
|
49 | - * If a Recipe is for a single class (or group of classes that shares the EXACT SAME constructor arguments), |
|
50 | - * and that class type hints for an interface, then this property allows you to configure what dependencies |
|
51 | - * get used when instantiating the class. |
|
52 | - * For example: |
|
53 | - * There's a class called Coffee, and one of its constructor arguments is BeanInterface |
|
54 | - * There are two implementations of BeanInterface: HonduranBean, and KenyanBean |
|
55 | - * We want one Coffee object to use HonduranBean for its BeanInterface, |
|
56 | - * and the 2nd Coffee object to use KenyanBean for its BeanInterface. |
|
57 | - * To do this, we need to create two Recipes: |
|
58 | - * one with an identifier of 'HonduranCoffee' using the following ingredients : |
|
59 | - * array('BeanInterface' => 'HonduranBean') |
|
60 | - * and the other with an identifier of 'KenyanCoffee' using the following ingredients : |
|
61 | - * array('BeanInterface' => 'KenyanBean') |
|
62 | - * Then, whenever the CoffeeShop brews an instance of HonduranCoffee, |
|
63 | - * an instance of HonduranBean will get injected for the BeanInterface dependency, |
|
64 | - * and whenever the CoffeeShop brews an instance of KenyanCoffee, |
|
65 | - * an instance of KenyanBean will get injected for the BeanInterface dependency |
|
66 | - * |
|
67 | - * @var array $ingredients |
|
68 | - */ |
|
69 | - private $ingredients = array(); |
|
70 | - |
|
71 | - /** |
|
72 | - * one of the class constants from CoffeeShop: |
|
73 | - * CoffeeMaker::BREW_NEW - creates a new instance |
|
74 | - * CoffeeMaker::BREW_SHARED - creates a shared instance |
|
75 | - * CoffeeMaker::BREW_LOAD_ONLY - loads but does not instantiate |
|
76 | - * |
|
77 | - * @var string $type |
|
78 | - */ |
|
79 | - private $type; |
|
80 | - |
|
81 | - /** |
|
82 | - * class name aliases - typically a Fully Qualified Interface that the class implements |
|
83 | - * identifiers passed to the CoffeeShop will be run through the filters to find the correct class name |
|
84 | - * |
|
85 | - * @var array $filters |
|
86 | - */ |
|
87 | - private $filters = array(); |
|
88 | - |
|
89 | - /** |
|
90 | - * array of full server filepaths to files that may contain the class |
|
91 | - * |
|
92 | - * @var array $paths |
|
93 | - */ |
|
94 | - private $paths = array(); |
|
95 | - |
|
96 | - |
|
97 | - |
|
98 | - /** |
|
99 | - * Recipe constructor. |
|
100 | - * |
|
101 | - * @param string $identifier class identifier, can be an alias, or FQCN, or whatever |
|
102 | - * @param string $fqcn \Fully\Qualified\ClassName, optional if $identifier is FQCN |
|
103 | - * @param array $ingredients array of dependencies that can not be resolved automatically, |
|
104 | - * used for resolving concrete classes for type hinted interfaces |
|
105 | - * for the dependencies of THIS class |
|
106 | - * @param string $type recipe type: one of the class constants on |
|
107 | - * \EventEspresso\core\services\container\CoffeeMaker |
|
108 | - * @param array $filters array of class aliases, or class interfaces |
|
109 | - * this works somewhat opposite to the $ingredients array above, |
|
110 | - * in that this array specifies interfaces or aliases |
|
111 | - * that this Recipe can be used for when resolving OTHER class's dependencies |
|
112 | - * @param array $paths if class can not be loaded via PSR-4 autoloading, |
|
113 | - * then supply a filepath, or array of filepaths, so that it can be included |
|
114 | - * @throws InvalidIdentifierException |
|
115 | - * @throws RuntimeException |
|
116 | - * @throws InvalidInterfaceException |
|
117 | - * @throws InvalidClassException |
|
118 | - * @throws InvalidDataTypeException |
|
119 | - */ |
|
120 | - public function __construct( |
|
121 | - $identifier, |
|
122 | - $fqcn = '', |
|
123 | - array $filters = array(), |
|
124 | - array $ingredients = array(), |
|
125 | - $type = CoffeeMaker::BREW_NEW, |
|
126 | - array $paths = array() |
|
127 | - ) |
|
128 | - { |
|
129 | - $this->setIdentifier($identifier); |
|
130 | - $this->setFilters($filters); |
|
131 | - $this->setIngredients($ingredients); |
|
132 | - $this->setType($type); |
|
133 | - $this->setPaths($paths); |
|
134 | - $this->setFqcn($fqcn); |
|
135 | - } |
|
136 | - |
|
137 | - |
|
138 | - |
|
139 | - /** |
|
140 | - * @return string |
|
141 | - */ |
|
142 | - public function identifier() |
|
143 | - { |
|
144 | - return $this->identifier; |
|
145 | - } |
|
146 | - |
|
147 | - |
|
148 | - |
|
149 | - /** |
|
150 | - * @return string |
|
151 | - */ |
|
152 | - public function fqcn() |
|
153 | - { |
|
154 | - return $this->fqcn; |
|
155 | - } |
|
156 | - |
|
157 | - |
|
158 | - |
|
159 | - /** |
|
160 | - * @return array |
|
161 | - */ |
|
162 | - public function filters() |
|
163 | - { |
|
164 | - return $this->filters; |
|
165 | - } |
|
166 | - |
|
167 | - |
|
168 | - |
|
169 | - /** |
|
170 | - * @return array |
|
171 | - */ |
|
172 | - public function ingredients() |
|
173 | - { |
|
174 | - return $this->ingredients; |
|
175 | - } |
|
176 | - |
|
177 | - |
|
178 | - |
|
179 | - /** |
|
180 | - * @return string |
|
181 | - */ |
|
182 | - public function type() |
|
183 | - { |
|
184 | - return $this->type; |
|
185 | - } |
|
186 | - |
|
187 | - |
|
188 | - |
|
189 | - /** |
|
190 | - * @return array |
|
191 | - */ |
|
192 | - public function paths() |
|
193 | - { |
|
194 | - return $this->paths; |
|
195 | - } |
|
196 | - |
|
197 | - |
|
198 | - |
|
199 | - /** |
|
200 | - * @param string $identifier Identifier for the entity class that the Recipe applies to |
|
201 | - * Typically a Fully Qualified Class Name |
|
202 | - * @throws InvalidIdentifierException |
|
203 | - */ |
|
204 | - public function setIdentifier($identifier) |
|
205 | - { |
|
206 | - if ( ! is_string($identifier) || empty($identifier)) { |
|
207 | - throw new InvalidIdentifierException( |
|
208 | - is_object($identifier) ? get_class($identifier) : gettype($identifier), |
|
209 | - __('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso') |
|
210 | - ); |
|
211 | - } |
|
212 | - $this->identifier = $identifier; |
|
213 | - } |
|
214 | - |
|
215 | - |
|
216 | - |
|
217 | - /** |
|
218 | - * Ensures incoming string is a valid Fully Qualified Class Name, |
|
219 | - * except if this is the default wildcard Recipe ( * ), |
|
220 | - * or it's NOT an actual FQCN because the Recipe is using filepaths |
|
221 | - * for classes that are not PSR-4 compatible |
|
222 | - * PLZ NOTE: |
|
223 | - * Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not, |
|
224 | - * therefore you should always call Recipe::setPaths() before Recipe::setFqcn() |
|
225 | - * |
|
226 | - * @param string $fqcn |
|
227 | - * @throws InvalidDataTypeException |
|
228 | - * @throws InvalidClassException |
|
229 | - * @throws InvalidInterfaceException |
|
230 | - */ |
|
231 | - public function setFqcn($fqcn) |
|
232 | - { |
|
233 | - $fqcn = ! empty($fqcn) ? $fqcn : $this->identifier; |
|
234 | - if ( ! is_string($fqcn)) { |
|
235 | - throw new InvalidDataTypeException( |
|
236 | - '$fqcn', |
|
237 | - is_object($fqcn) ? get_class($fqcn) : gettype($fqcn), |
|
238 | - __('string (Fully\Qualified\ClassName)', 'event_espresso') |
|
239 | - ); |
|
240 | - } |
|
241 | - $fqcn = ltrim($fqcn, '\\'); |
|
242 | - if ( |
|
243 | - $fqcn !== Recipe::DEFAULT_ID |
|
244 | - && ! empty($fqcn) |
|
245 | - && empty($this->paths) |
|
246 | - && ! (class_exists($fqcn) || interface_exists($fqcn)) |
|
247 | - ) { |
|
248 | - throw new InvalidClassException($fqcn); |
|
249 | - } |
|
250 | - $this->fqcn = $fqcn; |
|
251 | - } |
|
252 | - |
|
253 | - |
|
254 | - |
|
255 | - /** |
|
256 | - * @param array $ingredients an array of dependencies where keys are the aliases and values are the FQCNs |
|
257 | - * example: |
|
258 | - * array( 'ClassInterface' => 'Fully\Qualified\ClassName' ) |
|
259 | - * @throws InvalidDataTypeException |
|
260 | - */ |
|
261 | - public function setIngredients(array $ingredients) |
|
262 | - { |
|
263 | - if (empty($ingredients)) { |
|
264 | - return; |
|
265 | - } |
|
266 | - if ( ! is_array($ingredients)) { |
|
267 | - throw new InvalidDataTypeException( |
|
268 | - '$ingredients', |
|
269 | - is_object($ingredients) ? get_class($ingredients) : gettype($ingredients), |
|
270 | - __('array of class dependencies', 'event_espresso') |
|
271 | - ); |
|
272 | - } |
|
273 | - $this->ingredients = array_merge($this->ingredients, $ingredients); |
|
274 | - } |
|
275 | - |
|
276 | - |
|
277 | - /** |
|
278 | - * @param string $type one of the class constants returned from CoffeeMaker::getTypes() |
|
279 | - * @throws InvalidIdentifierException |
|
280 | - */ |
|
281 | - public function setType($type = CoffeeMaker::BREW_NEW) |
|
282 | - { |
|
283 | - $this->type = CoffeeMaker::validateType($type); |
|
284 | - } |
|
285 | - |
|
286 | - |
|
287 | - |
|
288 | - /** |
|
289 | - * @param array $filters an array of filters where keys are the aliases and values are the FQCNs |
|
290 | - * example: |
|
291 | - * array( 'ClassInterface' => 'Fully\Qualified\ClassName' ) |
|
292 | - * @throws InvalidDataTypeException |
|
293 | - */ |
|
294 | - public function setFilters(array $filters) |
|
295 | - { |
|
296 | - if (empty($filters)) { |
|
297 | - return; |
|
298 | - } |
|
299 | - if ( ! is_array($filters)) { |
|
300 | - throw new InvalidDataTypeException( |
|
301 | - '$filters', |
|
302 | - is_object($filters) ? get_class($filters) : gettype($filters), |
|
303 | - __('array of class aliases', 'event_espresso') |
|
304 | - ); |
|
305 | - } |
|
306 | - $this->filters = array_merge($this->filters, $filters); |
|
307 | - } |
|
308 | - |
|
309 | - |
|
310 | - |
|
311 | - /** |
|
312 | - * Ensures incoming paths is a valid filepath, or array of valid filepaths, |
|
313 | - * and merges them in with any existing filepaths |
|
314 | - * PLZ NOTE: |
|
315 | - * Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not, |
|
316 | - * therefore you should always call Recipe::setPaths() before Recipe::setFqcn() |
|
317 | - * |
|
318 | - * @param string|array $paths |
|
319 | - * @throws RuntimeException |
|
320 | - * @throws InvalidDataTypeException |
|
321 | - */ |
|
322 | - public function setPaths($paths = array()) |
|
323 | - { |
|
324 | - if (empty($paths)) { |
|
325 | - return; |
|
326 | - } |
|
327 | - if ( ! (is_string($paths) || is_array($paths))) { |
|
328 | - throw new InvalidDataTypeException( |
|
329 | - '$path', |
|
330 | - is_object($paths) ? get_class($paths) : gettype($paths), |
|
331 | - __('string or array of strings (full server filepath(s))', 'event_espresso') |
|
332 | - ); |
|
333 | - } |
|
334 | - $paths = (array)$paths; |
|
335 | - foreach ($paths as $path) { |
|
336 | - if (strpos($path, '*') === false && ! is_readable($path)) { |
|
337 | - throw new RuntimeException( |
|
338 | - sprintf( |
|
339 | - __('The following filepath is not readable: "%1$s"', 'event_espresso'), |
|
340 | - $path |
|
341 | - ) |
|
342 | - ); |
|
343 | - } |
|
344 | - } |
|
345 | - $this->paths = array_merge($this->paths, $paths); |
|
346 | - } |
|
27 | + /** |
|
28 | + * A default Recipe to use if none is specified for a class |
|
29 | + */ |
|
30 | + const DEFAULT_ID = '*'; |
|
31 | + |
|
32 | + /** |
|
33 | + * Identifier for the entity class to be constructed. |
|
34 | + * Typically a Fully Qualified Class Name |
|
35 | + * |
|
36 | + * @var string $identifier |
|
37 | + */ |
|
38 | + private $identifier; |
|
39 | + |
|
40 | + /** |
|
41 | + * Fully Qualified Class Name |
|
42 | + * |
|
43 | + * @var string $fqcn |
|
44 | + */ |
|
45 | + private $fqcn; |
|
46 | + |
|
47 | + /** |
|
48 | + * a dependency class map array |
|
49 | + * If a Recipe is for a single class (or group of classes that shares the EXACT SAME constructor arguments), |
|
50 | + * and that class type hints for an interface, then this property allows you to configure what dependencies |
|
51 | + * get used when instantiating the class. |
|
52 | + * For example: |
|
53 | + * There's a class called Coffee, and one of its constructor arguments is BeanInterface |
|
54 | + * There are two implementations of BeanInterface: HonduranBean, and KenyanBean |
|
55 | + * We want one Coffee object to use HonduranBean for its BeanInterface, |
|
56 | + * and the 2nd Coffee object to use KenyanBean for its BeanInterface. |
|
57 | + * To do this, we need to create two Recipes: |
|
58 | + * one with an identifier of 'HonduranCoffee' using the following ingredients : |
|
59 | + * array('BeanInterface' => 'HonduranBean') |
|
60 | + * and the other with an identifier of 'KenyanCoffee' using the following ingredients : |
|
61 | + * array('BeanInterface' => 'KenyanBean') |
|
62 | + * Then, whenever the CoffeeShop brews an instance of HonduranCoffee, |
|
63 | + * an instance of HonduranBean will get injected for the BeanInterface dependency, |
|
64 | + * and whenever the CoffeeShop brews an instance of KenyanCoffee, |
|
65 | + * an instance of KenyanBean will get injected for the BeanInterface dependency |
|
66 | + * |
|
67 | + * @var array $ingredients |
|
68 | + */ |
|
69 | + private $ingredients = array(); |
|
70 | + |
|
71 | + /** |
|
72 | + * one of the class constants from CoffeeShop: |
|
73 | + * CoffeeMaker::BREW_NEW - creates a new instance |
|
74 | + * CoffeeMaker::BREW_SHARED - creates a shared instance |
|
75 | + * CoffeeMaker::BREW_LOAD_ONLY - loads but does not instantiate |
|
76 | + * |
|
77 | + * @var string $type |
|
78 | + */ |
|
79 | + private $type; |
|
80 | + |
|
81 | + /** |
|
82 | + * class name aliases - typically a Fully Qualified Interface that the class implements |
|
83 | + * identifiers passed to the CoffeeShop will be run through the filters to find the correct class name |
|
84 | + * |
|
85 | + * @var array $filters |
|
86 | + */ |
|
87 | + private $filters = array(); |
|
88 | + |
|
89 | + /** |
|
90 | + * array of full server filepaths to files that may contain the class |
|
91 | + * |
|
92 | + * @var array $paths |
|
93 | + */ |
|
94 | + private $paths = array(); |
|
95 | + |
|
96 | + |
|
97 | + |
|
98 | + /** |
|
99 | + * Recipe constructor. |
|
100 | + * |
|
101 | + * @param string $identifier class identifier, can be an alias, or FQCN, or whatever |
|
102 | + * @param string $fqcn \Fully\Qualified\ClassName, optional if $identifier is FQCN |
|
103 | + * @param array $ingredients array of dependencies that can not be resolved automatically, |
|
104 | + * used for resolving concrete classes for type hinted interfaces |
|
105 | + * for the dependencies of THIS class |
|
106 | + * @param string $type recipe type: one of the class constants on |
|
107 | + * \EventEspresso\core\services\container\CoffeeMaker |
|
108 | + * @param array $filters array of class aliases, or class interfaces |
|
109 | + * this works somewhat opposite to the $ingredients array above, |
|
110 | + * in that this array specifies interfaces or aliases |
|
111 | + * that this Recipe can be used for when resolving OTHER class's dependencies |
|
112 | + * @param array $paths if class can not be loaded via PSR-4 autoloading, |
|
113 | + * then supply a filepath, or array of filepaths, so that it can be included |
|
114 | + * @throws InvalidIdentifierException |
|
115 | + * @throws RuntimeException |
|
116 | + * @throws InvalidInterfaceException |
|
117 | + * @throws InvalidClassException |
|
118 | + * @throws InvalidDataTypeException |
|
119 | + */ |
|
120 | + public function __construct( |
|
121 | + $identifier, |
|
122 | + $fqcn = '', |
|
123 | + array $filters = array(), |
|
124 | + array $ingredients = array(), |
|
125 | + $type = CoffeeMaker::BREW_NEW, |
|
126 | + array $paths = array() |
|
127 | + ) |
|
128 | + { |
|
129 | + $this->setIdentifier($identifier); |
|
130 | + $this->setFilters($filters); |
|
131 | + $this->setIngredients($ingredients); |
|
132 | + $this->setType($type); |
|
133 | + $this->setPaths($paths); |
|
134 | + $this->setFqcn($fqcn); |
|
135 | + } |
|
136 | + |
|
137 | + |
|
138 | + |
|
139 | + /** |
|
140 | + * @return string |
|
141 | + */ |
|
142 | + public function identifier() |
|
143 | + { |
|
144 | + return $this->identifier; |
|
145 | + } |
|
146 | + |
|
147 | + |
|
148 | + |
|
149 | + /** |
|
150 | + * @return string |
|
151 | + */ |
|
152 | + public function fqcn() |
|
153 | + { |
|
154 | + return $this->fqcn; |
|
155 | + } |
|
156 | + |
|
157 | + |
|
158 | + |
|
159 | + /** |
|
160 | + * @return array |
|
161 | + */ |
|
162 | + public function filters() |
|
163 | + { |
|
164 | + return $this->filters; |
|
165 | + } |
|
166 | + |
|
167 | + |
|
168 | + |
|
169 | + /** |
|
170 | + * @return array |
|
171 | + */ |
|
172 | + public function ingredients() |
|
173 | + { |
|
174 | + return $this->ingredients; |
|
175 | + } |
|
176 | + |
|
177 | + |
|
178 | + |
|
179 | + /** |
|
180 | + * @return string |
|
181 | + */ |
|
182 | + public function type() |
|
183 | + { |
|
184 | + return $this->type; |
|
185 | + } |
|
186 | + |
|
187 | + |
|
188 | + |
|
189 | + /** |
|
190 | + * @return array |
|
191 | + */ |
|
192 | + public function paths() |
|
193 | + { |
|
194 | + return $this->paths; |
|
195 | + } |
|
196 | + |
|
197 | + |
|
198 | + |
|
199 | + /** |
|
200 | + * @param string $identifier Identifier for the entity class that the Recipe applies to |
|
201 | + * Typically a Fully Qualified Class Name |
|
202 | + * @throws InvalidIdentifierException |
|
203 | + */ |
|
204 | + public function setIdentifier($identifier) |
|
205 | + { |
|
206 | + if ( ! is_string($identifier) || empty($identifier)) { |
|
207 | + throw new InvalidIdentifierException( |
|
208 | + is_object($identifier) ? get_class($identifier) : gettype($identifier), |
|
209 | + __('class identifier (typically a \Fully\Qualified\ClassName)', 'event_espresso') |
|
210 | + ); |
|
211 | + } |
|
212 | + $this->identifier = $identifier; |
|
213 | + } |
|
214 | + |
|
215 | + |
|
216 | + |
|
217 | + /** |
|
218 | + * Ensures incoming string is a valid Fully Qualified Class Name, |
|
219 | + * except if this is the default wildcard Recipe ( * ), |
|
220 | + * or it's NOT an actual FQCN because the Recipe is using filepaths |
|
221 | + * for classes that are not PSR-4 compatible |
|
222 | + * PLZ NOTE: |
|
223 | + * Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not, |
|
224 | + * therefore you should always call Recipe::setPaths() before Recipe::setFqcn() |
|
225 | + * |
|
226 | + * @param string $fqcn |
|
227 | + * @throws InvalidDataTypeException |
|
228 | + * @throws InvalidClassException |
|
229 | + * @throws InvalidInterfaceException |
|
230 | + */ |
|
231 | + public function setFqcn($fqcn) |
|
232 | + { |
|
233 | + $fqcn = ! empty($fqcn) ? $fqcn : $this->identifier; |
|
234 | + if ( ! is_string($fqcn)) { |
|
235 | + throw new InvalidDataTypeException( |
|
236 | + '$fqcn', |
|
237 | + is_object($fqcn) ? get_class($fqcn) : gettype($fqcn), |
|
238 | + __('string (Fully\Qualified\ClassName)', 'event_espresso') |
|
239 | + ); |
|
240 | + } |
|
241 | + $fqcn = ltrim($fqcn, '\\'); |
|
242 | + if ( |
|
243 | + $fqcn !== Recipe::DEFAULT_ID |
|
244 | + && ! empty($fqcn) |
|
245 | + && empty($this->paths) |
|
246 | + && ! (class_exists($fqcn) || interface_exists($fqcn)) |
|
247 | + ) { |
|
248 | + throw new InvalidClassException($fqcn); |
|
249 | + } |
|
250 | + $this->fqcn = $fqcn; |
|
251 | + } |
|
252 | + |
|
253 | + |
|
254 | + |
|
255 | + /** |
|
256 | + * @param array $ingredients an array of dependencies where keys are the aliases and values are the FQCNs |
|
257 | + * example: |
|
258 | + * array( 'ClassInterface' => 'Fully\Qualified\ClassName' ) |
|
259 | + * @throws InvalidDataTypeException |
|
260 | + */ |
|
261 | + public function setIngredients(array $ingredients) |
|
262 | + { |
|
263 | + if (empty($ingredients)) { |
|
264 | + return; |
|
265 | + } |
|
266 | + if ( ! is_array($ingredients)) { |
|
267 | + throw new InvalidDataTypeException( |
|
268 | + '$ingredients', |
|
269 | + is_object($ingredients) ? get_class($ingredients) : gettype($ingredients), |
|
270 | + __('array of class dependencies', 'event_espresso') |
|
271 | + ); |
|
272 | + } |
|
273 | + $this->ingredients = array_merge($this->ingredients, $ingredients); |
|
274 | + } |
|
275 | + |
|
276 | + |
|
277 | + /** |
|
278 | + * @param string $type one of the class constants returned from CoffeeMaker::getTypes() |
|
279 | + * @throws InvalidIdentifierException |
|
280 | + */ |
|
281 | + public function setType($type = CoffeeMaker::BREW_NEW) |
|
282 | + { |
|
283 | + $this->type = CoffeeMaker::validateType($type); |
|
284 | + } |
|
285 | + |
|
286 | + |
|
287 | + |
|
288 | + /** |
|
289 | + * @param array $filters an array of filters where keys are the aliases and values are the FQCNs |
|
290 | + * example: |
|
291 | + * array( 'ClassInterface' => 'Fully\Qualified\ClassName' ) |
|
292 | + * @throws InvalidDataTypeException |
|
293 | + */ |
|
294 | + public function setFilters(array $filters) |
|
295 | + { |
|
296 | + if (empty($filters)) { |
|
297 | + return; |
|
298 | + } |
|
299 | + if ( ! is_array($filters)) { |
|
300 | + throw new InvalidDataTypeException( |
|
301 | + '$filters', |
|
302 | + is_object($filters) ? get_class($filters) : gettype($filters), |
|
303 | + __('array of class aliases', 'event_espresso') |
|
304 | + ); |
|
305 | + } |
|
306 | + $this->filters = array_merge($this->filters, $filters); |
|
307 | + } |
|
308 | + |
|
309 | + |
|
310 | + |
|
311 | + /** |
|
312 | + * Ensures incoming paths is a valid filepath, or array of valid filepaths, |
|
313 | + * and merges them in with any existing filepaths |
|
314 | + * PLZ NOTE: |
|
315 | + * Recipe::setFqcn() has a check to see if Recipe::$paths is empty or not, |
|
316 | + * therefore you should always call Recipe::setPaths() before Recipe::setFqcn() |
|
317 | + * |
|
318 | + * @param string|array $paths |
|
319 | + * @throws RuntimeException |
|
320 | + * @throws InvalidDataTypeException |
|
321 | + */ |
|
322 | + public function setPaths($paths = array()) |
|
323 | + { |
|
324 | + if (empty($paths)) { |
|
325 | + return; |
|
326 | + } |
|
327 | + if ( ! (is_string($paths) || is_array($paths))) { |
|
328 | + throw new InvalidDataTypeException( |
|
329 | + '$path', |
|
330 | + is_object($paths) ? get_class($paths) : gettype($paths), |
|
331 | + __('string or array of strings (full server filepath(s))', 'event_espresso') |
|
332 | + ); |
|
333 | + } |
|
334 | + $paths = (array)$paths; |
|
335 | + foreach ($paths as $path) { |
|
336 | + if (strpos($path, '*') === false && ! is_readable($path)) { |
|
337 | + throw new RuntimeException( |
|
338 | + sprintf( |
|
339 | + __('The following filepath is not readable: "%1$s"', 'event_espresso'), |
|
340 | + $path |
|
341 | + ) |
|
342 | + ); |
|
343 | + } |
|
344 | + } |
|
345 | + $this->paths = array_merge($this->paths, $paths); |
|
346 | + } |
|
347 | 347 | |
348 | 348 | |
349 | 349 |
@@ -331,7 +331,7 @@ |
||
331 | 331 | __('string or array of strings (full server filepath(s))', 'event_espresso') |
332 | 332 | ); |
333 | 333 | } |
334 | - $paths = (array)$paths; |
|
334 | + $paths = (array) $paths; |
|
335 | 335 | foreach ($paths as $path) { |
336 | 336 | if (strpos($path, '*') === false && ! is_readable($path)) { |
337 | 337 | throw new RuntimeException( |