Completed
Branch BUG/3608-REQ-loading (17482d)
by
unknown
06:01 queued 04:11
created
core/admin/EE_Admin_Page.core.php 2 patches
Spacing   +184 added lines, -184 removed lines patch added patch discarded remove patch
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
         $ee_menu_slugs = (array) $ee_menu_slugs;
537 537
         if (
538 538
             ! $this->request->isAjax()
539
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
539
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
540 540
         ) {
541 541
             return;
542 542
         }
@@ -556,7 +556,7 @@  discard block
 block discarded – undo
556 556
             : $req_action;
557 557
 
558 558
         $this->_current_view = $this->_req_action;
559
-        $this->_req_nonce    = $this->_req_action . '_nonce';
559
+        $this->_req_nonce    = $this->_req_action.'_nonce';
560 560
         $this->_define_page_props();
561 561
         $this->_current_page_view_url = add_query_arg(
562 562
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -594,21 +594,21 @@  discard block
 block discarded – undo
594 594
         }
595 595
         // filter routes and page_config so addons can add their stuff. Filtering done per class
596 596
         $this->_page_routes = apply_filters(
597
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
597
+            'FHEE__'.get_class($this).'__page_setup__page_routes',
598 598
             $this->_page_routes,
599 599
             $this
600 600
         );
601 601
         $this->_page_config = apply_filters(
602
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
602
+            'FHEE__'.get_class($this).'__page_setup__page_config',
603 603
             $this->_page_config,
604 604
             $this
605 605
         );
606 606
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
607 607
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
608
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
608
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
609 609
             add_action(
610 610
                 'AHEE__EE_Admin_Page__route_admin_request',
611
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
611
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
612 612
                 10,
613 613
                 2
614 614
             );
@@ -621,8 +621,8 @@  discard block
 block discarded – undo
621 621
             if ($this->_is_UI_request) {
622 622
                 // admin_init stuff - global, all views for this page class, specific view
623 623
                 add_action('admin_init', [$this, 'admin_init'], 10);
624
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
625
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
624
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
625
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
626 626
                 }
627 627
             } else {
628 628
                 // hijack regular WP loading and route admin request immediately
@@ -641,12 +641,12 @@  discard block
 block discarded – undo
641 641
      */
642 642
     private function _do_other_page_hooks()
643 643
     {
644
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
644
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
645 645
         foreach ($registered_pages as $page) {
646 646
             // now let's setup the file name and class that should be present
647 647
             $classname = str_replace('.class.php', '', $page);
648 648
             // autoloaders should take care of loading file
649
-            if (! class_exists($classname)) {
649
+            if ( ! class_exists($classname)) {
650 650
                 $error_msg[] = sprintf(
651 651
                     esc_html__(
652 652
                         'Something went wrong with loading the %s admin hooks page.',
@@ -663,7 +663,7 @@  discard block
 block discarded – undo
663 663
                                    ),
664 664
                                    $page,
665 665
                                    '<br />',
666
-                                   '<strong>' . $classname . '</strong>'
666
+                                   '<strong>'.$classname.'</strong>'
667 667
                                );
668 668
                 throw new EE_Error(implode('||', $error_msg));
669 669
             }
@@ -705,13 +705,13 @@  discard block
 block discarded – undo
705 705
         // load admin_notices - global, page class, and view specific
706 706
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
707 707
         add_action('admin_notices', [$this, 'admin_notices'], 10);
708
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
709
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
708
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
709
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
710 710
         }
711 711
         // load network admin_notices - global, page class, and view specific
712 712
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
713
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
714
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
713
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
714
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
715 715
         }
716 716
         // this will save any per_page screen options if they are present
717 717
         $this->_set_per_page_screen_options();
@@ -833,7 +833,7 @@  discard block
 block discarded – undo
833 833
     protected function _verify_routes()
834 834
     {
835 835
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
836
-        if (! $this->_current_page && ! $this->request->isAjax()) {
836
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
837 837
             return false;
838 838
         }
839 839
         $this->_route = false;
@@ -845,7 +845,7 @@  discard block
 block discarded – undo
845 845
                 $this->_admin_page_title
846 846
             );
847 847
             // developer error msg
848
-            $error_msg .= '||' . $error_msg
848
+            $error_msg .= '||'.$error_msg
849 849
                           . esc_html__(
850 850
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
851 851
                               'event_espresso'
@@ -854,9 +854,9 @@  discard block
 block discarded – undo
854 854
         }
855 855
         // and that the requested page route exists
856 856
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
857
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
858
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
859
-                ? $this->_page_config[ $this->_req_action ]
857
+            $this->_route        = $this->_page_routes[$this->_req_action];
858
+            $this->_route_config = isset($this->_page_config[$this->_req_action])
859
+                ? $this->_page_config[$this->_req_action]
860 860
                 : [];
861 861
         } else {
862 862
             // user error msg
@@ -868,7 +868,7 @@  discard block
 block discarded – undo
868 868
                 $this->_admin_page_title
869 869
             );
870 870
             // developer error msg
871
-            $error_msg .= '||' . $error_msg
871
+            $error_msg .= '||'.$error_msg
872 872
                           . sprintf(
873 873
                               esc_html__(
874 874
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -879,7 +879,7 @@  discard block
 block discarded – undo
879 879
             throw new EE_Error($error_msg);
880 880
         }
881 881
         // and that a default route exists
882
-        if (! array_key_exists('default', $this->_page_routes)) {
882
+        if ( ! array_key_exists('default', $this->_page_routes)) {
883 883
             // user error msg
884 884
             $error_msg = sprintf(
885 885
                 esc_html__(
@@ -889,7 +889,7 @@  discard block
 block discarded – undo
889 889
                 $this->_admin_page_title
890 890
             );
891 891
             // developer error msg
892
-            $error_msg .= '||' . $error_msg
892
+            $error_msg .= '||'.$error_msg
893 893
                           . esc_html__(
894 894
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
895 895
                               'event_espresso'
@@ -930,7 +930,7 @@  discard block
 block discarded – undo
930 930
             $this->_admin_page_title
931 931
         );
932 932
         // developer error msg
933
-        $error_msg .= '||' . $error_msg
933
+        $error_msg .= '||'.$error_msg
934 934
                       . sprintf(
935 935
                           esc_html__(
936 936
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -955,7 +955,7 @@  discard block
 block discarded – undo
955 955
     protected function _verify_nonce($nonce, $nonce_ref)
956 956
     {
957 957
         // verify nonce against expected value
958
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
958
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
959 959
             // these are not the droids you are looking for !!!
960 960
             $msg = sprintf(
961 961
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -972,7 +972,7 @@  discard block
 block discarded – undo
972 972
                     __CLASS__
973 973
                 );
974 974
             }
975
-            if (! $this->request->isAjax()) {
975
+            if ( ! $this->request->isAjax()) {
976 976
                 wp_die($msg);
977 977
             }
978 978
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -996,7 +996,7 @@  discard block
 block discarded – undo
996 996
      */
997 997
     protected function _route_admin_request()
998 998
     {
999
-        if (! $this->_is_UI_request) {
999
+        if ( ! $this->_is_UI_request) {
1000 1000
             $this->_verify_routes();
1001 1001
         }
1002 1002
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1016,7 +1016,7 @@  discard block
 block discarded – undo
1016 1016
         $error_msg = '';
1017 1017
         // action right before calling route
1018 1018
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1019
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1019
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1020 1020
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1021 1021
         }
1022 1022
         // right before calling the route, let's clean the _wp_http_referer
@@ -1027,7 +1027,7 @@  discard block
 block discarded – undo
1027 1027
                 wp_unslash($this->request->getServerParam('REQUEST_URI'))
1028 1028
             )
1029 1029
         );
1030
-        if (! empty($func)) {
1030
+        if ( ! empty($func)) {
1031 1031
             if (is_array($func)) {
1032 1032
                 list($class, $method) = $func;
1033 1033
             } elseif (strpos($func, '::') !== false) {
@@ -1036,7 +1036,7 @@  discard block
 block discarded – undo
1036 1036
                 $class  = $this;
1037 1037
                 $method = $func;
1038 1038
             }
1039
-            if (! (is_object($class) && $class === $this)) {
1039
+            if ( ! (is_object($class) && $class === $this)) {
1040 1040
                 // send along this admin page object for access by addons.
1041 1041
                 $args['admin_page_object'] = $this;
1042 1042
             }
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
                     $method
1078 1078
                 );
1079 1079
             }
1080
-            if (! empty($error_msg)) {
1080
+            if ( ! empty($error_msg)) {
1081 1081
                 throw new EE_Error($error_msg);
1082 1082
             }
1083 1083
         }
@@ -1162,7 +1162,7 @@  discard block
 block discarded – undo
1162 1162
                 if (strpos($key, 'nonce') !== false) {
1163 1163
                     continue;
1164 1164
                 }
1165
-                $args[ 'wp_referer[' . $key . ']' ] = $value;
1165
+                $args['wp_referer['.$key.']'] = $value;
1166 1166
             }
1167 1167
         }
1168 1168
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1202,8 +1202,8 @@  discard block
 block discarded – undo
1202 1202
     protected function _add_help_tabs()
1203 1203
     {
1204 1204
         $tour_buttons = '';
1205
-        if (isset($this->_page_config[ $this->_req_action ])) {
1206
-            $config = $this->_page_config[ $this->_req_action ];
1205
+        if (isset($this->_page_config[$this->_req_action])) {
1206
+            $config = $this->_page_config[$this->_req_action];
1207 1207
             // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1208 1208
             // is there a help tour for the current route?  if there is let's setup the tour buttons
1209 1209
             // if (isset($this->_help_tour[ $this->_req_action ])) {
@@ -1226,7 +1226,7 @@  discard block
 block discarded – undo
1226 1226
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1227 1227
             if (is_array($config) && isset($config['help_sidebar'])) {
1228 1228
                 // check that the callback given is valid
1229
-                if (! method_exists($this, $config['help_sidebar'])) {
1229
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1230 1230
                     throw new EE_Error(
1231 1231
                         sprintf(
1232 1232
                             esc_html__(
@@ -1239,7 +1239,7 @@  discard block
 block discarded – undo
1239 1239
                     );
1240 1240
                 }
1241 1241
                 $content = apply_filters(
1242
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1242
+                    'FHEE__'.get_class($this).'__add_help_tabs__help_sidebar',
1243 1243
                     $this->{$config['help_sidebar']}()
1244 1244
                 );
1245 1245
                 $content .= $tour_buttons; // add help tour buttons.
@@ -1247,27 +1247,27 @@  discard block
 block discarded – undo
1247 1247
                 $this->_current_screen->set_help_sidebar($content);
1248 1248
             }
1249 1249
             // if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1250
-            if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1250
+            if ( ! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1251 1251
                 $this->_current_screen->set_help_sidebar($tour_buttons);
1252 1252
             }
1253 1253
             // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1254
-            if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1254
+            if ( ! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1255 1255
                 $_ht['id']      = $this->page_slug;
1256 1256
                 $_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1257 1257
                 $_ht['content'] = '<p>'
1258 1258
                                   . esc_html__(
1259 1259
                                       'The buttons to the right allow you to start/restart any help tours available for this page',
1260 1260
                                       'event_espresso'
1261
-                                  ) . '</p>';
1261
+                                  ).'</p>';
1262 1262
                 $this->_current_screen->add_help_tab($_ht);
1263 1263
             }
1264
-            if (! isset($config['help_tabs'])) {
1264
+            if ( ! isset($config['help_tabs'])) {
1265 1265
                 return;
1266 1266
             } //no help tabs for this route
1267 1267
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1268 1268
                 // we're here so there ARE help tabs!
1269 1269
                 // make sure we've got what we need
1270
-                if (! isset($cfg['title'])) {
1270
+                if ( ! isset($cfg['title'])) {
1271 1271
                     throw new EE_Error(
1272 1272
                         esc_html__(
1273 1273
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1275,7 +1275,7 @@  discard block
 block discarded – undo
1275 1275
                         )
1276 1276
                     );
1277 1277
                 }
1278
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1278
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1279 1279
                     throw new EE_Error(
1280 1280
                         esc_html__(
1281 1281
                             'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
@@ -1284,11 +1284,11 @@  discard block
 block discarded – undo
1284 1284
                     );
1285 1285
                 }
1286 1286
                 // first priority goes to content.
1287
-                if (! empty($cfg['content'])) {
1287
+                if ( ! empty($cfg['content'])) {
1288 1288
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1289 1289
                     // second priority goes to filename
1290
-                } elseif (! empty($cfg['filename'])) {
1291
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1290
+                } elseif ( ! empty($cfg['filename'])) {
1291
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1292 1292
                     // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1293 1293
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1294 1294
                                                              . basename($this->_get_dir())
@@ -1296,7 +1296,7 @@  discard block
 block discarded – undo
1296 1296
                                                              . $cfg['filename']
1297 1297
                                                              . '.help_tab.php' : $file_path;
1298 1298
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1299
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1299
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1300 1300
                         EE_Error::add_error(
1301 1301
                             sprintf(
1302 1302
                                 esc_html__(
@@ -1344,7 +1344,7 @@  discard block
 block discarded – undo
1344 1344
                     return;
1345 1345
                 }
1346 1346
                 // setup config array for help tab method
1347
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1347
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1348 1348
                 $_ht = [
1349 1349
                     'id'       => $id,
1350 1350
                     'title'    => $cfg['title'],
@@ -1471,8 +1471,8 @@  discard block
 block discarded – undo
1471 1471
             $qtips = (array) $this->_route_config['qtips'];
1472 1472
             // load qtip loader
1473 1473
             $path = [
1474
-                $this->_get_dir() . '/qtips/',
1475
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1474
+                $this->_get_dir().'/qtips/',
1475
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1476 1476
             ];
1477 1477
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1478 1478
         }
@@ -1494,7 +1494,7 @@  discard block
 block discarded – undo
1494 1494
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1495 1495
         $i = 0;
1496 1496
         foreach ($this->_page_config as $slug => $config) {
1497
-            if (! is_array($config) || empty($config['nav'])) {
1497
+            if ( ! is_array($config) || empty($config['nav'])) {
1498 1498
                 continue;
1499 1499
             }
1500 1500
             // no nav tab for this config
@@ -1503,12 +1503,12 @@  discard block
 block discarded – undo
1503 1503
                 // nav tab is only to appear when route requested.
1504 1504
                 continue;
1505 1505
             }
1506
-            if (! $this->check_user_access($slug, true)) {
1506
+            if ( ! $this->check_user_access($slug, true)) {
1507 1507
                 // no nav tab because current user does not have access.
1508 1508
                 continue;
1509 1509
             }
1510
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1511
-            $this->_nav_tabs[ $slug ] = [
1510
+            $css_class                = isset($config['css_class']) ? $config['css_class'].' ' : '';
1511
+            $this->_nav_tabs[$slug] = [
1512 1512
                 'url'       => isset($config['nav']['url'])
1513 1513
                     ? $config['nav']['url']
1514 1514
                     : self::add_query_args_and_nonce(
@@ -1520,14 +1520,14 @@  discard block
 block discarded – undo
1520 1520
                     : ucwords(
1521 1521
                         str_replace('_', ' ', $slug)
1522 1522
                     ),
1523
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1523
+                'css_class' => $this->_req_action === $slug ? $css_class.'nav-tab-active' : $css_class,
1524 1524
                 'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1525 1525
             ];
1526 1526
             $i++;
1527 1527
         }
1528 1528
         // if $this->_nav_tabs is empty then lets set the default
1529 1529
         if (empty($this->_nav_tabs)) {
1530
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1530
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1531 1531
                 'url'       => $this->_admin_base_url,
1532 1532
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1533 1533
                 'css_class' => 'nav-tab-active',
@@ -1552,10 +1552,10 @@  discard block
 block discarded – undo
1552 1552
             foreach ($this->_route_config['labels'] as $label => $text) {
1553 1553
                 if (is_array($text)) {
1554 1554
                     foreach ($text as $sublabel => $subtext) {
1555
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1555
+                        $this->_labels[$label][$sublabel] = $subtext;
1556 1556
                     }
1557 1557
                 } else {
1558
-                    $this->_labels[ $label ] = $text;
1558
+                    $this->_labels[$label] = $text;
1559 1559
                 }
1560 1560
             }
1561 1561
         }
@@ -1577,12 +1577,12 @@  discard block
 block discarded – undo
1577 1577
     {
1578 1578
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1579 1579
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1580
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1580
+        $capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1581 1581
                           && is_array(
1582
-                              $this->_page_routes[ $route_to_check ]
1582
+                              $this->_page_routes[$route_to_check]
1583 1583
                           )
1584
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1585
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1584
+                          && ! empty($this->_page_routes[$route_to_check]['capability'])
1585
+            ? $this->_page_routes[$route_to_check]['capability'] : null;
1586 1586
         if (empty($capability) && empty($route_to_check)) {
1587 1587
             $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1588 1588
                 : $this->_route['capability'];
@@ -1707,7 +1707,7 @@  discard block
 block discarded – undo
1707 1707
         //     echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1708 1708
         // }
1709 1709
         // current set timezone for timezone js
1710
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1710
+        echo '<span id="current_timezone" class="hidden">'.esc_html(EEH_DTT_Helper::get_timezone()).'</span>';
1711 1711
     }
1712 1712
 
1713 1713
 
@@ -1741,7 +1741,7 @@  discard block
 block discarded – undo
1741 1741
         // loop through the array and setup content
1742 1742
         foreach ($help_array as $trigger => $help) {
1743 1743
             // make sure the array is setup properly
1744
-            if (! isset($help['title']) || ! isset($help['content'])) {
1744
+            if ( ! isset($help['title']) || ! isset($help['content'])) {
1745 1745
                 throw new EE_Error(
1746 1746
                     esc_html__(
1747 1747
                         'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
@@ -1755,8 +1755,8 @@  discard block
 block discarded – undo
1755 1755
                 'help_popup_title'   => $help['title'],
1756 1756
                 'help_popup_content' => $help['content'],
1757 1757
             ];
1758
-            $content       .= EEH_Template::display_template(
1759
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1758
+            $content .= EEH_Template::display_template(
1759
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1760 1760
                 $template_args,
1761 1761
                 true
1762 1762
             );
@@ -1778,15 +1778,15 @@  discard block
 block discarded – undo
1778 1778
     private function _get_help_content()
1779 1779
     {
1780 1780
         // what is the method we're looking for?
1781
-        $method_name = '_help_popup_content_' . $this->_req_action;
1781
+        $method_name = '_help_popup_content_'.$this->_req_action;
1782 1782
         // if method doesn't exist let's get out.
1783
-        if (! method_exists($this, $method_name)) {
1783
+        if ( ! method_exists($this, $method_name)) {
1784 1784
             return [];
1785 1785
         }
1786 1786
         // k we're good to go let's retrieve the help array
1787 1787
         $help_array = call_user_func([$this, $method_name]);
1788 1788
         // make sure we've got an array!
1789
-        if (! is_array($help_array)) {
1789
+        if ( ! is_array($help_array)) {
1790 1790
             throw new EE_Error(
1791 1791
                 esc_html__(
1792 1792
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1818,15 +1818,15 @@  discard block
 block discarded – undo
1818 1818
         // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1819 1819
         $help_array   = $this->_get_help_content();
1820 1820
         $help_content = '';
1821
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1822
-            $help_array[ $trigger_id ] = [
1821
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1822
+            $help_array[$trigger_id] = [
1823 1823
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1824 1824
                 'content' => esc_html__(
1825 1825
                     'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1826 1826
                     'event_espresso'
1827 1827
                 ),
1828 1828
             ];
1829
-            $help_content              = $this->_set_help_popup_content($help_array, false);
1829
+            $help_content = $this->_set_help_popup_content($help_array, false);
1830 1830
         }
1831 1831
         // let's setup the trigger
1832 1832
         $content = '<a class="ee-dialog" href="?height='
@@ -1894,15 +1894,15 @@  discard block
 block discarded – undo
1894 1894
         // register all styles
1895 1895
         wp_register_style(
1896 1896
             'espresso-ui-theme',
1897
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1897
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1898 1898
             [],
1899 1899
             EVENT_ESPRESSO_VERSION
1900 1900
         );
1901
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1901
+        wp_register_style('ee-admin-css', EE_ADMIN_URL.'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1902 1902
         // helpers styles
1903 1903
         wp_register_style(
1904 1904
             'ee-text-links',
1905
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1905
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.css',
1906 1906
             [],
1907 1907
             EVENT_ESPRESSO_VERSION
1908 1908
         );
@@ -1910,21 +1910,21 @@  discard block
 block discarded – undo
1910 1910
         // register all scripts
1911 1911
         wp_register_script(
1912 1912
             'ee-dialog',
1913
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1913
+            EE_ADMIN_URL.'assets/ee-dialog-helper.js',
1914 1914
             ['jquery', 'jquery-ui-draggable'],
1915 1915
             EVENT_ESPRESSO_VERSION,
1916 1916
             true
1917 1917
         );
1918 1918
         wp_register_script(
1919 1919
             'ee_admin_js',
1920
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1920
+            EE_ADMIN_URL.'assets/ee-admin-page.js',
1921 1921
             ['espresso_core', 'ee-parse-uri', 'ee-dialog'],
1922 1922
             EVENT_ESPRESSO_VERSION,
1923 1923
             true
1924 1924
         );
1925 1925
         wp_register_script(
1926 1926
             'jquery-ui-timepicker-addon',
1927
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1927
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery-ui-timepicker-addon.js',
1928 1928
             ['jquery-ui-datepicker', 'jquery-ui-slider'],
1929 1929
             EVENT_ESPRESSO_VERSION,
1930 1930
             true
@@ -1936,7 +1936,7 @@  discard block
 block discarded – undo
1936 1936
         // script for sorting tables
1937 1937
         wp_register_script(
1938 1938
             'espresso_ajax_table_sorting',
1939
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1939
+            EE_ADMIN_URL.'assets/espresso_ajax_table_sorting.js',
1940 1940
             ['ee_admin_js', 'jquery-ui-sortable'],
1941 1941
             EVENT_ESPRESSO_VERSION,
1942 1942
             true
@@ -1944,7 +1944,7 @@  discard block
 block discarded – undo
1944 1944
         // script for parsing uri's
1945 1945
         wp_register_script(
1946 1946
             'ee-parse-uri',
1947
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1947
+            EE_GLOBAL_ASSETS_URL.'scripts/parseuri.js',
1948 1948
             [],
1949 1949
             EVENT_ESPRESSO_VERSION,
1950 1950
             true
@@ -1952,7 +1952,7 @@  discard block
 block discarded – undo
1952 1952
         // and parsing associative serialized form elements
1953 1953
         wp_register_script(
1954 1954
             'ee-serialize-full-array',
1955
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1955
+            EE_GLOBAL_ASSETS_URL.'scripts/jquery.serializefullarray.js',
1956 1956
             ['jquery'],
1957 1957
             EVENT_ESPRESSO_VERSION,
1958 1958
             true
@@ -1960,28 +1960,28 @@  discard block
 block discarded – undo
1960 1960
         // helpers scripts
1961 1961
         wp_register_script(
1962 1962
             'ee-text-links',
1963
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1963
+            EE_PLUGIN_DIR_URL.'core/helpers/assets/ee_text_list_helper.js',
1964 1964
             ['jquery'],
1965 1965
             EVENT_ESPRESSO_VERSION,
1966 1966
             true
1967 1967
         );
1968 1968
         wp_register_script(
1969 1969
             'ee-moment-core',
1970
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1970
+            EE_THIRD_PARTY_URL.'moment/moment-with-locales.min.js',
1971 1971
             [],
1972 1972
             EVENT_ESPRESSO_VERSION,
1973 1973
             true
1974 1974
         );
1975 1975
         wp_register_script(
1976 1976
             'ee-moment',
1977
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1977
+            EE_THIRD_PARTY_URL.'moment/moment-timezone-with-data.min.js',
1978 1978
             ['ee-moment-core'],
1979 1979
             EVENT_ESPRESSO_VERSION,
1980 1980
             true
1981 1981
         );
1982 1982
         wp_register_script(
1983 1983
             'ee-datepicker',
1984
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1984
+            EE_ADMIN_URL.'assets/ee-datepicker.js',
1985 1985
             ['jquery-ui-timepicker-addon', 'ee-moment'],
1986 1986
             EVENT_ESPRESSO_VERSION,
1987 1987
             true
@@ -2042,7 +2042,7 @@  discard block
 block discarded – undo
2042 2042
 
2043 2043
         add_filter(
2044 2044
             'admin_body_class',
2045
-            function ($classes) {
2045
+            function($classes) {
2046 2046
                 if (strpos($classes, 'espresso-admin') === false) {
2047 2047
                     $classes .= ' espresso-admin';
2048 2048
                 }
@@ -2130,12 +2130,12 @@  discard block
 block discarded – undo
2130 2130
     protected function _set_list_table()
2131 2131
     {
2132 2132
         // first is this a list_table view?
2133
-        if (! isset($this->_route_config['list_table'])) {
2133
+        if ( ! isset($this->_route_config['list_table'])) {
2134 2134
             return;
2135 2135
         } //not a list_table view so get out.
2136 2136
         // list table functions are per view specific (because some admin pages might have more than one list table!)
2137
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2138
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2137
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
2138
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2139 2139
             // user error msg
2140 2140
             $error_msg = esc_html__(
2141 2141
                 'An error occurred. The requested list table views could not be found.',
@@ -2155,10 +2155,10 @@  discard block
 block discarded – undo
2155 2155
         }
2156 2156
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2157 2157
         $this->_views = apply_filters(
2158
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2158
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2159 2159
             $this->_views
2160 2160
         );
2161
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2161
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2162 2162
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2163 2163
         $this->_set_list_table_view();
2164 2164
         $this->_set_list_table_object();
@@ -2193,7 +2193,7 @@  discard block
 block discarded – undo
2193 2193
     protected function _set_list_table_object()
2194 2194
     {
2195 2195
         if (isset($this->_route_config['list_table'])) {
2196
-            if (! class_exists($this->_route_config['list_table'])) {
2196
+            if ( ! class_exists($this->_route_config['list_table'])) {
2197 2197
                 throw new EE_Error(
2198 2198
                     sprintf(
2199 2199
                         esc_html__(
@@ -2231,15 +2231,15 @@  discard block
 block discarded – undo
2231 2231
         foreach ($this->_views as $key => $view) {
2232 2232
             $query_args = [];
2233 2233
             // check for current view
2234
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2234
+            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2235 2235
             $query_args['action']                        = $this->_req_action;
2236
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2236
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2237 2237
             $query_args['status']                        = $view['slug'];
2238 2238
             // merge any other arguments sent in.
2239
-            if (isset($extra_query_args[ $view['slug'] ])) {
2240
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2239
+            if (isset($extra_query_args[$view['slug']])) {
2240
+                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2241 2241
             }
2242
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2242
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2243 2243
         }
2244 2244
         return $this->_views;
2245 2245
     }
@@ -2270,14 +2270,14 @@  discard block
 block discarded – undo
2270 2270
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2271 2271
         foreach ($values as $value) {
2272 2272
             if ($value < $max_entries) {
2273
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2273
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2274 2274
                 $entries_per_page_dropdown .= '
2275
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2275
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2276 2276
             }
2277 2277
         }
2278
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2278
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2279 2279
         $entries_per_page_dropdown .= '
2280
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2280
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2281 2281
         $entries_per_page_dropdown .= '
2282 2282
 					</select>
2283 2283
 					entries
@@ -2301,7 +2301,7 @@  discard block
 block discarded – undo
2301 2301
             empty($this->_search_btn_label) ? $this->page_label
2302 2302
                 : $this->_search_btn_label
2303 2303
         );
2304
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2304
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2305 2305
     }
2306 2306
 
2307 2307
 
@@ -2389,7 +2389,7 @@  discard block
 block discarded – undo
2389 2389
             $total_columns                                       = ! empty($screen_columns)
2390 2390
                 ? $screen_columns
2391 2391
                 : $this->_route_config['columns'][1];
2392
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2392
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2393 2393
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2394 2394
             $this->_template_args['screen']                      = $this->_current_screen;
2395 2395
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2434,7 +2434,7 @@  discard block
 block discarded – undo
2434 2434
      */
2435 2435
     protected function _espresso_ratings_request()
2436 2436
     {
2437
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2437
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2438 2438
             return;
2439 2439
         }
2440 2440
         $ratings_box_title = apply_filters(
@@ -2462,7 +2462,7 @@  discard block
 block discarded – undo
2462 2462
     public function espresso_ratings_request()
2463 2463
     {
2464 2464
         EEH_Template::display_template(
2465
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2465
+            EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php',
2466 2466
             []
2467 2467
         );
2468 2468
     }
@@ -2470,22 +2470,22 @@  discard block
 block discarded – undo
2470 2470
 
2471 2471
     public static function cached_rss_display($rss_id, $url)
2472 2472
     {
2473
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2473
+        $loading = '<p class="widget-loading hide-if-no-js">'
2474 2474
                      . esc_html__('Loading&#8230;', 'event_espresso')
2475 2475
                      . '</p><p class="hide-if-js">'
2476 2476
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2477 2477
                      . '</p>';
2478
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2479
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2480
-        $post      = '</div>' . "\n";
2481
-        $cache_key = 'ee_rss_' . md5($rss_id);
2478
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2479
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2480
+        $post      = '</div>'."\n";
2481
+        $cache_key = 'ee_rss_'.md5($rss_id);
2482 2482
         $output    = get_transient($cache_key);
2483 2483
         if ($output !== false) {
2484
-            echo $pre . $output . $post; // already escaped
2484
+            echo $pre.$output.$post; // already escaped
2485 2485
             return true;
2486 2486
         }
2487
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2488
-            echo $pre . $loading . $post; // already escaped
2487
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2488
+            echo $pre.$loading.$post; // already escaped
2489 2489
             return false;
2490 2490
         }
2491 2491
         ob_start();
@@ -2552,19 +2552,19 @@  discard block
 block discarded – undo
2552 2552
     public function espresso_sponsors_post_box()
2553 2553
     {
2554 2554
         EEH_Template::display_template(
2555
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2555
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2556 2556
         );
2557 2557
     }
2558 2558
 
2559 2559
 
2560 2560
     private function _publish_post_box()
2561 2561
     {
2562
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2562
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2563 2563
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2564 2564
         // then we'll use that for the metabox label.
2565 2565
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2566
-        if (! empty($this->_labels['publishbox'])) {
2567
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2566
+        if ( ! empty($this->_labels['publishbox'])) {
2567
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2568 2568
                 : $this->_labels['publishbox'];
2569 2569
         } else {
2570 2570
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2593,7 +2593,7 @@  discard block
 block discarded – undo
2593 2593
             ? $this->_template_args['publish_box_extra_content']
2594 2594
             : '';
2595 2595
         echo EEH_Template::display_template(
2596
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2596
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2597 2597
             $this->_template_args,
2598 2598
             true
2599 2599
         );
@@ -2685,18 +2685,18 @@  discard block
 block discarded – undo
2685 2685
             );
2686 2686
         }
2687 2687
         $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2688
-        if (! empty($name) && ! empty($id)) {
2689
-            $hidden_field_arr[ $name ] = [
2688
+        if ( ! empty($name) && ! empty($id)) {
2689
+            $hidden_field_arr[$name] = [
2690 2690
                 'type'  => 'hidden',
2691 2691
                 'value' => $id,
2692 2692
             ];
2693
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2693
+            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2694 2694
         } else {
2695 2695
             $hf = '';
2696 2696
         }
2697 2697
         // add hidden field
2698 2698
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2699
-            ? $hf[ $name ]['field']
2699
+            ? $hf[$name]['field']
2700 2700
             : $hf;
2701 2701
     }
2702 2702
 
@@ -2798,7 +2798,7 @@  discard block
 block discarded – undo
2798 2798
         }
2799 2799
         // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2800 2800
         $call_back_func = $create_func
2801
-            ? function ($post, $metabox) {
2801
+            ? function($post, $metabox) {
2802 2802
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2803 2803
                 echo EEH_Template::display_template(
2804 2804
                     $metabox['args']['template_path'],
@@ -2808,7 +2808,7 @@  discard block
 block discarded – undo
2808 2808
             }
2809 2809
             : $callback;
2810 2810
         add_meta_box(
2811
-            str_replace('_', '-', $action) . '-mbox',
2811
+            str_replace('_', '-', $action).'-mbox',
2812 2812
             $title,
2813 2813
             $call_back_func,
2814 2814
             $this->_wp_page_slug,
@@ -2900,9 +2900,9 @@  discard block
 block discarded – undo
2900 2900
             : 'espresso-default-admin';
2901 2901
         $template_path                                     = $sidebar
2902 2902
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2903
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2903
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2904 2904
         if ($this->request->isAjax()) {
2905
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2905
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2906 2906
         }
2907 2907
         $template_path                                     = ! empty($this->_column_template_path)
2908 2908
             ? $this->_column_template_path : $template_path;
@@ -2942,11 +2942,11 @@  discard block
 block discarded – undo
2942 2942
     public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2943 2943
     {
2944 2944
         // let's generate a default preview action button if there isn't one already present.
2945
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2945
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2946 2946
             'Upgrade to Event Espresso 4 Right Now',
2947 2947
             'event_espresso'
2948 2948
         );
2949
-        $buy_now_url                                   = add_query_arg(
2949
+        $buy_now_url = add_query_arg(
2950 2950
             [
2951 2951
                 'ee_ver'       => 'ee4',
2952 2952
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2966,8 +2966,8 @@  discard block
 block discarded – undo
2966 2966
                 true
2967 2967
             )
2968 2968
             : $this->_template_args['preview_action_button'];
2969
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2970
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2969
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2970
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2971 2971
             $this->_template_args,
2972 2972
             true
2973 2973
         );
@@ -3016,7 +3016,7 @@  discard block
 block discarded – undo
3016 3016
         // setup search attributes
3017 3017
         $this->_set_search_attributes();
3018 3018
         $this->_template_args['current_page']     = $this->_wp_page_slug;
3019
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3019
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
3020 3020
         $this->_template_args['table_url']        = $this->request->isAjax()
3021 3021
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
3022 3022
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -3024,10 +3024,10 @@  discard block
 block discarded – undo
3024 3024
         $this->_template_args['current_route']    = $this->_req_action;
3025 3025
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3026 3026
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3027
-        if (! empty($ajax_sorting_callback)) {
3027
+        if ( ! empty($ajax_sorting_callback)) {
3028 3028
             $sortable_list_table_form_fields = wp_nonce_field(
3029
-                $ajax_sorting_callback . '_nonce',
3030
-                $ajax_sorting_callback . '_nonce',
3029
+                $ajax_sorting_callback.'_nonce',
3030
+                $ajax_sorting_callback.'_nonce',
3031 3031
                 false,
3032 3032
                 false
3033 3033
             );
@@ -3045,20 +3045,20 @@  discard block
 block discarded – undo
3045 3045
             isset($this->_template_args['list_table_hidden_fields'])
3046 3046
                 ? $this->_template_args['list_table_hidden_fields']
3047 3047
                 : '';
3048
-        $nonce_ref                                               = $this->_req_action . '_nonce';
3049
-        $hidden_form_fields                                      .= '<input type="hidden" name="'
3048
+        $nonce_ref = $this->_req_action.'_nonce';
3049
+        $hidden_form_fields .= '<input type="hidden" name="'
3050 3050
                                                                     . $nonce_ref
3051 3051
                                                                     . '" value="'
3052 3052
                                                                     . wp_create_nonce($nonce_ref)
3053 3053
                                                                     . '">';
3054
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3054
+        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
3055 3055
         // display message about search results?
3056 3056
         $search = $this->request->getRequestParam('s');
3057 3057
         $this->_template_args['before_list_table'] .= ! empty($search)
3058
-            ? '<p class="ee-search-results">' . sprintf(
3058
+            ? '<p class="ee-search-results">'.sprintf(
3059 3059
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3060 3060
                 trim($search, '%')
3061
-            ) . '</p>'
3061
+            ).'</p>'
3062 3062
             : '';
3063 3063
         // filter before_list_table template arg
3064 3064
         $this->_template_args['before_list_table'] = apply_filters(
@@ -3092,7 +3092,7 @@  discard block
 block discarded – undo
3092 3092
         // convert to array and filter again
3093 3093
         // arrays are easier to inject new items in a specific location,
3094 3094
         // but would not be backwards compatible, so we have to add a new filter
3095
-        $this->_template_args['after_list_table']   = implode(
3095
+        $this->_template_args['after_list_table'] = implode(
3096 3096
             " \n",
3097 3097
             (array) apply_filters(
3098 3098
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3139,7 +3139,7 @@  discard block
 block discarded – undo
3139 3139
             $this
3140 3140
         );
3141 3141
         return EEH_Template::display_template(
3142
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3142
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3143 3143
             $this->_template_args,
3144 3144
             true
3145 3145
         );
@@ -3246,17 +3246,17 @@  discard block
 block discarded – undo
3246 3246
                 ? $this->_template_args['before_admin_page_content']
3247 3247
                 : ''
3248 3248
         );
3249
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3249
+        $this->_template_args['after_admin_page_content'] = apply_filters(
3250 3250
             "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3251 3251
             isset($this->_template_args['after_admin_page_content'])
3252 3252
                 ? $this->_template_args['after_admin_page_content']
3253 3253
                 : ''
3254 3254
         );
3255
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3255
+        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3256 3256
         // load settings page wrapper template
3257 3257
         $template_path = ! $this->request->isAjax()
3258 3258
             ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3259
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
3259
+            : EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php';
3260 3260
         // about page?
3261 3261
         $template_path = $about
3262 3262
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
@@ -3350,7 +3350,7 @@  discard block
 block discarded – undo
3350 3350
             : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3351 3351
               . $referrer
3352 3352
               . '" />';
3353
-        $button_text   = ! empty($text)
3353
+        $button_text = ! empty($text)
3354 3354
             ? $text
3355 3355
             : [
3356 3356
                 esc_html__('Save', 'event_espresso'),
@@ -3360,17 +3360,17 @@  discard block
 block discarded – undo
3360 3360
         // add in a hidden index for the current page (so save and close redirects properly)
3361 3361
         $this->_template_args['save_buttons'] = $referrer_url;
3362 3362
         foreach ($button_text as $key => $button) {
3363
-            $ref                                  = $default_names[ $key ];
3363
+            $ref = $default_names[$key];
3364 3364
             $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3365 3365
                                                      . $ref
3366 3366
                                                      . '" value="'
3367 3367
                                                      . $button
3368 3368
                                                      . '" name="'
3369
-                                                     . (! empty($actions) ? $actions[ $key ] : $ref)
3369
+                                                     . ( ! empty($actions) ? $actions[$key] : $ref)
3370 3370
                                                      . '" id="'
3371
-                                                     . $this->_current_view . '_' . $ref
3371
+                                                     . $this->_current_view.'_'.$ref
3372 3372
                                                      . '" />';
3373
-            if (! $both) {
3373
+            if ( ! $both) {
3374 3374
                 break;
3375 3375
             }
3376 3376
         }
@@ -3405,13 +3405,13 @@  discard block
 block discarded – undo
3405 3405
                 'An error occurred. No action was set for this page\'s form.',
3406 3406
                 'event_espresso'
3407 3407
             );
3408
-            $dev_msg  = $user_msg . "\n"
3408
+            $dev_msg = $user_msg."\n"
3409 3409
                         . sprintf(
3410 3410
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3411 3411
                             __FUNCTION__,
3412 3412
                             __CLASS__
3413 3413
                         );
3414
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3414
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3415 3415
         }
3416 3416
         // open form
3417 3417
         $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
@@ -3420,9 +3420,9 @@  discard block
 block discarded – undo
3420 3420
                                                              . $route
3421 3421
                                                              . '_event_form" >';
3422 3422
         // add nonce
3423
-        $nonce                                             =
3424
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3425
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3423
+        $nonce =
3424
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3425
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3426 3426
         // add REQUIRED form action
3427 3427
         $hidden_fields = [
3428 3428
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3435,7 +3435,7 @@  discard block
 block discarded – undo
3435 3435
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3436 3436
         // add fields to form
3437 3437
         foreach ((array) $form_fields as $field_name => $form_field) {
3438
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3438
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3439 3439
         }
3440 3440
         // close form
3441 3441
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3526,10 +3526,10 @@  discard block
 block discarded – undo
3526 3526
         $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3527 3527
         $notices      = EE_Error::get_notices(false);
3528 3528
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3529
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3529
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3530 3530
             EE_Error::overwrite_success();
3531 3531
         }
3532
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3532
+        if ( ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3533 3533
             // how many records affected ? more than one record ? or just one ?
3534 3534
             if ($success > 1) {
3535 3535
                 // set plural msg
@@ -3558,7 +3558,7 @@  discard block
 block discarded – undo
3558 3558
             }
3559 3559
         }
3560 3560
         // check that $query_args isn't something crazy
3561
-        if (! is_array($query_args)) {
3561
+        if ( ! is_array($query_args)) {
3562 3562
             $query_args = [];
3563 3563
         }
3564 3564
         /**
@@ -3587,7 +3587,7 @@  discard block
 block discarded – undo
3587 3587
             $redirect_url = admin_url('admin.php');
3588 3588
         }
3589 3589
         // merge any default query_args set in _default_route_query_args property
3590
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3590
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3591 3591
             $args_to_merge = [];
3592 3592
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3593 3593
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3599,15 +3599,15 @@  discard block
 block discarded – undo
3599 3599
                         }
3600 3600
                         // finally we will override any arguments in the referer with
3601 3601
                         // what might be set on the _default_route_query_args array.
3602
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3603
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3602
+                        if (isset($this->_default_route_query_args[$reference])) {
3603
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3604 3604
                         } else {
3605
-                            $args_to_merge[ $reference ] = urlencode($value);
3605
+                            $args_to_merge[$reference] = urlencode($value);
3606 3606
                         }
3607 3607
                     }
3608 3608
                     continue;
3609 3609
                 }
3610
-                $args_to_merge[ $query_param ] = $query_value;
3610
+                $args_to_merge[$query_param] = $query_value;
3611 3611
             }
3612 3612
             // now let's merge these arguments but override with what was specifically sent in to the
3613 3613
             // redirect.
@@ -3619,19 +3619,19 @@  discard block
 block discarded – undo
3619 3619
         if (isset($query_args['action'])) {
3620 3620
             // manually generate wp_nonce and merge that with the query vars
3621 3621
             // becuz the wp_nonce_url function wrecks havoc on some vars
3622
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3622
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3623 3623
         }
3624 3624
         // we're adding some hooks and filters in here for processing any things just before redirects
3625 3625
         // (example: an admin page has done an insert or update and we want to run something after that).
3626
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3626
+        do_action('AHEE_redirect_'.$classname.$this->_req_action, $query_args);
3627 3627
         $redirect_url = apply_filters(
3628
-            'FHEE_redirect_' . $classname . $this->_req_action,
3628
+            'FHEE_redirect_'.$classname.$this->_req_action,
3629 3629
             self::add_query_args_and_nonce($query_args, $redirect_url),
3630 3630
             $query_args
3631 3631
         );
3632 3632
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3633 3633
         if ($this->request->isAjax()) {
3634
-            $default_data                    = [
3634
+            $default_data = [
3635 3635
                 'close'        => true,
3636 3636
                 'redirect_url' => $redirect_url,
3637 3637
                 'where'        => 'main',
@@ -3678,7 +3678,7 @@  discard block
 block discarded – undo
3678 3678
         }
3679 3679
         $this->_template_args['notices'] = EE_Error::get_notices();
3680 3680
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3681
-        if (! $this->request->isAjax() || $sticky_notices) {
3681
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3682 3682
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3683 3683
             $this->_add_transient(
3684 3684
                 $route,
@@ -3718,7 +3718,7 @@  discard block
 block discarded – undo
3718 3718
         $exclude_nonce = false
3719 3719
     ) {
3720 3720
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3721
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3721
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3722 3722
             throw new EE_Error(
3723 3723
                 sprintf(
3724 3724
                     esc_html__(
@@ -3729,7 +3729,7 @@  discard block
 block discarded – undo
3729 3729
                 )
3730 3730
             );
3731 3731
         }
3732
-        if (! isset($this->_labels['buttons'][ $type ])) {
3732
+        if ( ! isset($this->_labels['buttons'][$type])) {
3733 3733
             throw new EE_Error(
3734 3734
                 sprintf(
3735 3735
                     esc_html__(
@@ -3742,7 +3742,7 @@  discard block
 block discarded – undo
3742 3742
         }
3743 3743
         // finally check user access for this button.
3744 3744
         $has_access = $this->check_user_access($action, true);
3745
-        if (! $has_access) {
3745
+        if ( ! $has_access) {
3746 3746
             return '';
3747 3747
         }
3748 3748
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3750,11 +3750,11 @@  discard block
 block discarded – undo
3750 3750
             'action' => $action,
3751 3751
         ];
3752 3752
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3753
-        if (! empty($extra_request)) {
3753
+        if ( ! empty($extra_request)) {
3754 3754
             $query_args = array_merge($extra_request, $query_args);
3755 3755
         }
3756 3756
         $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3757
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3757
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3758 3758
     }
3759 3759
 
3760 3760
 
@@ -3780,7 +3780,7 @@  discard block
 block discarded – undo
3780 3780
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3781 3781
                 20
3782 3782
             ),
3783
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3783
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3784 3784
         ];
3785 3785
         // ONLY add the screen option if the user has access to it.
3786 3786
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3801,18 +3801,18 @@  discard block
 block discarded – undo
3801 3801
     {
3802 3802
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3803 3803
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3804
-            if (! $user = wp_get_current_user()) {
3804
+            if ( ! $user = wp_get_current_user()) {
3805 3805
                 return;
3806 3806
             }
3807 3807
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3808
-            if (! $option) {
3808
+            if ( ! $option) {
3809 3809
                 return;
3810 3810
             }
3811
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3811
+            $value = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3812 3812
             $map_option = $option;
3813 3813
             $option     = str_replace('-', '_', $option);
3814 3814
             switch ($map_option) {
3815
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3815
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3816 3816
                     $max_value = apply_filters(
3817 3817
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3818 3818
                         999,
@@ -3869,13 +3869,13 @@  discard block
 block discarded – undo
3869 3869
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3870 3870
     {
3871 3871
         $user_id = get_current_user_id();
3872
-        if (! $skip_route_verify) {
3872
+        if ( ! $skip_route_verify) {
3873 3873
             $this->_verify_route($route);
3874 3874
         }
3875 3875
         // now let's set the string for what kind of transient we're setting
3876 3876
         $transient = $notices
3877
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3878
-            : 'rte_tx_' . $route . '_' . $user_id;
3877
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3878
+            : 'rte_tx_'.$route.'_'.$user_id;
3879 3879
         $data      = $notices ? ['notices' => $data] : $data;
3880 3880
         // is there already a transient for this route?  If there is then let's ADD to that transient
3881 3881
         $existing = is_multisite() && is_network_admin()
@@ -3904,8 +3904,8 @@  discard block
 block discarded – undo
3904 3904
         $user_id   = get_current_user_id();
3905 3905
         $route     = ! $route ? $this->_req_action : $route;
3906 3906
         $transient = $notices
3907
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3908
-            : 'rte_tx_' . $route . '_' . $user_id;
3907
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3908
+            : 'rte_tx_'.$route.'_'.$user_id;
3909 3909
         $data      = is_multisite() && is_network_admin()
3910 3910
             ? get_site_transient($transient)
3911 3911
             : get_transient($transient);
@@ -4136,7 +4136,7 @@  discard block
 block discarded – undo
4136 4136
      */
4137 4137
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4138 4138
     {
4139
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4139
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4140 4140
     }
4141 4141
 
4142 4142
 
@@ -4149,7 +4149,7 @@  discard block
 block discarded – undo
4149 4149
      */
4150 4150
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4151 4151
     {
4152
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4152
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4153 4153
     }
4154 4154
 
4155 4155
 
Please login to merge, or discard this patch.
Indentation   +4111 added lines, -4111 removed lines patch added patch discarded remove patch
@@ -18,4187 +18,4187 @@
 block discarded – undo
18 18
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
19 19
 {
20 20
 
21
-    /**
22
-     * @var LoaderInterface
23
-     */
24
-    protected $loader;
21
+	/**
22
+	 * @var LoaderInterface
23
+	 */
24
+	protected $loader;
25 25
 
26
-    /**
27
-     * @var RequestInterface
28
-     */
29
-    protected $request;
26
+	/**
27
+	 * @var RequestInterface
28
+	 */
29
+	protected $request;
30 30
 
31
-    // set in _init_page_props()
32
-    public $page_slug;
31
+	// set in _init_page_props()
32
+	public $page_slug;
33 33
 
34
-    public $page_label;
34
+	public $page_label;
35 35
 
36
-    public $page_folder;
36
+	public $page_folder;
37 37
 
38
-    // set in define_page_props()
39
-    protected $_admin_base_url;
38
+	// set in define_page_props()
39
+	protected $_admin_base_url;
40 40
 
41
-    protected $_admin_base_path;
41
+	protected $_admin_base_path;
42 42
 
43
-    protected $_admin_page_title;
43
+	protected $_admin_page_title;
44 44
 
45
-    protected $_labels;
45
+	protected $_labels;
46 46
 
47 47
 
48
-    // set early within EE_Admin_Init
49
-    protected $_wp_page_slug;
48
+	// set early within EE_Admin_Init
49
+	protected $_wp_page_slug;
50 50
 
51
-    // navtabs
52
-    protected $_nav_tabs;
51
+	// navtabs
52
+	protected $_nav_tabs;
53 53
 
54
-    protected $_default_nav_tab_name;
54
+	protected $_default_nav_tab_name;
55 55
 
56
-    /**
57
-     * @var array $_help_tour
58
-     */
59
-    protected $_help_tour = [];
56
+	/**
57
+	 * @var array $_help_tour
58
+	 */
59
+	protected $_help_tour = [];
60 60
 
61 61
 
62
-    // template variables (used by templates)
63
-    protected $_template_path;
62
+	// template variables (used by templates)
63
+	protected $_template_path;
64 64
 
65
-    protected $_column_template_path;
65
+	protected $_column_template_path;
66 66
 
67
-    /**
68
-     * @var array $_template_args
69
-     */
70
-    protected $_template_args = [];
67
+	/**
68
+	 * @var array $_template_args
69
+	 */
70
+	protected $_template_args = [];
71 71
 
72
-    /**
73
-     * this will hold the list table object for a given view.
74
-     *
75
-     * @var EE_Admin_List_Table $_list_table_object
76
-     */
77
-    protected $_list_table_object;
72
+	/**
73
+	 * this will hold the list table object for a given view.
74
+	 *
75
+	 * @var EE_Admin_List_Table $_list_table_object
76
+	 */
77
+	protected $_list_table_object;
78 78
 
79
-    // bools
80
-    protected $_is_UI_request = null; // this starts at null so we can have no header routes progress through two states.
79
+	// bools
80
+	protected $_is_UI_request = null; // this starts at null so we can have no header routes progress through two states.
81 81
 
82
-    protected $_routing;
82
+	protected $_routing;
83 83
 
84
-    // list table args
85
-    protected $_view;
84
+	// list table args
85
+	protected $_view;
86 86
 
87
-    protected $_views;
87
+	protected $_views;
88 88
 
89 89
 
90
-    // action => method pairs used for routing incoming requests
91
-    protected $_page_routes;
90
+	// action => method pairs used for routing incoming requests
91
+	protected $_page_routes;
92 92
 
93
-    /**
94
-     * @var array $_page_config
95
-     */
96
-    protected $_page_config;
93
+	/**
94
+	 * @var array $_page_config
95
+	 */
96
+	protected $_page_config;
97 97
 
98
-    /**
99
-     * the current page route and route config
100
-     *
101
-     * @var string $_route
102
-     */
103
-    protected $_route;
98
+	/**
99
+	 * the current page route and route config
100
+	 *
101
+	 * @var string $_route
102
+	 */
103
+	protected $_route;
104 104
 
105
-    /**
106
-     * @var string $_cpt_route
107
-     */
108
-    protected $_cpt_route;
105
+	/**
106
+	 * @var string $_cpt_route
107
+	 */
108
+	protected $_cpt_route;
109 109
 
110
-    /**
111
-     * @var array $_route_config
112
-     */
113
-    protected $_route_config;
110
+	/**
111
+	 * @var array $_route_config
112
+	 */
113
+	protected $_route_config;
114 114
 
115
-    /**
116
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
117
-     * actions.
118
-     *
119
-     * @since 4.6.x
120
-     * @var array.
121
-     */
122
-    protected $_default_route_query_args;
123
-
124
-    // set via request page and action args.
125
-    protected $_current_page;
126
-
127
-    protected $_current_view;
128
-
129
-    protected $_current_page_view_url;
130
-
131
-    /**
132
-     * unprocessed value for the 'action' request param (default '')
133
-     *
134
-     * @var string
135
-     */
136
-    protected $raw_req_action = '';
137
-
138
-    /**
139
-     * unprocessed value for the 'page' request param (default '')
140
-     *
141
-     * @var string
142
-     */
143
-    protected $raw_req_page = '';
144
-
145
-    /**
146
-     * sanitized request action (and nonce)
147
-     *
148
-     * @var string
149
-     */
150
-    protected $_req_action = '';
151
-
152
-    /**
153
-     * sanitized request action nonce
154
-     *
155
-     * @var string
156
-     */
157
-    protected $_req_nonce = '';
158
-
159
-    /**
160
-     * @var string
161
-     */
162
-    protected $_search_btn_label = '';
163
-
164
-    /**
165
-     * @var string
166
-     */
167
-    protected $_search_box_callback = '';
168
-
169
-    /**
170
-     * @var WP_Screen
171
-     */
172
-    protected $_current_screen;
173
-
174
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
175
-    protected $_hook_obj;
176
-
177
-    // for holding incoming request data
178
-    protected $_req_data = [];
179
-
180
-    // yes / no array for admin form fields
181
-    protected $_yes_no_values = [];
182
-
183
-    // some default things shared by all child classes
184
-    protected $_default_espresso_metaboxes;
185
-
186
-    /**
187
-     * @var EE_Registry
188
-     */
189
-    protected $EE = null;
190
-
191
-
192
-    /**
193
-     * This is just a property that flags whether the given route is a caffeinated route or not.
194
-     *
195
-     * @var boolean
196
-     */
197
-    protected $_is_caf = false;
198
-
199
-
200
-    /**
201
-     * @Constructor
202
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
203
-     * @throws EE_Error
204
-     * @throws InvalidArgumentException
205
-     * @throws ReflectionException
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     */
209
-    public function __construct($routing = true)
210
-    {
211
-        $this->loader  = LoaderFactory::getLoader();
212
-        $this->request = $this->loader->getShared(RequestInterface::class);
213
-        $this->_routing = $routing;
214
-
215
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
216
-            $this->_is_caf = true;
217
-        }
218
-        $this->_yes_no_values = [
219
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
220
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
221
-        ];
222
-        // set the _req_data property.
223
-        $this->_req_data = $this->request->requestParams();
224
-        // set initial page props (child method)
225
-        $this->_init_page_props();
226
-        // set global defaults
227
-        $this->_set_defaults();
228
-        // set early because incoming requests could be ajax related and we need to register those hooks.
229
-        $this->_global_ajax_hooks();
230
-        $this->_ajax_hooks();
231
-        // other_page_hooks have to be early too.
232
-        $this->_do_other_page_hooks();
233
-        // set up page dependencies
234
-        $this->_before_page_setup();
235
-        $this->_page_setup();
236
-        // die();
237
-    }
238
-
239
-
240
-    /**
241
-     * _init_page_props
242
-     * Child classes use to set at least the following properties:
243
-     * $page_slug.
244
-     * $page_label.
245
-     *
246
-     * @abstract
247
-     * @return void
248
-     */
249
-    abstract protected function _init_page_props();
250
-
251
-
252
-    /**
253
-     * _ajax_hooks
254
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
255
-     * Note: within the ajax callback methods.
256
-     *
257
-     * @abstract
258
-     * @return void
259
-     */
260
-    abstract protected function _ajax_hooks();
261
-
262
-
263
-    /**
264
-     * _define_page_props
265
-     * child classes define page properties in here.  Must include at least:
266
-     * $_admin_base_url = base_url for all admin pages
267
-     * $_admin_page_title = default admin_page_title for admin pages
268
-     * $_labels = array of default labels for various automatically generated elements:
269
-     *    array(
270
-     *        'buttons' => array(
271
-     *            'add' => esc_html__('label for add new button'),
272
-     *            'edit' => esc_html__('label for edit button'),
273
-     *            'delete' => esc_html__('label for delete button')
274
-     *            )
275
-     *        )
276
-     *
277
-     * @abstract
278
-     * @return void
279
-     */
280
-    abstract protected function _define_page_props();
281
-
282
-
283
-    /**
284
-     * _set_page_routes
285
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
286
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
287
-     * have a 'default' route. Here's the format
288
-     * $this->_page_routes = array(
289
-     *        'default' => array(
290
-     *            'func' => '_default_method_handling_route',
291
-     *            'args' => array('array','of','args'),
292
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
293
-     *            ajax request, backend processing)
294
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
295
-     *            headers route after.  The string you enter here should match the defined route reference for a
296
-     *            headers sent route.
297
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
298
-     *            this route.
299
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
300
-     *            checks).
301
-     *        ),
302
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
303
-     *        handling method.
304
-     *        )
305
-     * )
306
-     *
307
-     * @abstract
308
-     * @return void
309
-     */
310
-    abstract protected function _set_page_routes();
311
-
312
-
313
-    /**
314
-     * _set_page_config
315
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
316
-     * array corresponds to the page_route for the loaded page. Format:
317
-     * $this->_page_config = array(
318
-     *        'default' => array(
319
-     *            'labels' => array(
320
-     *                'buttons' => array(
321
-     *                    'add' => esc_html__('label for adding item'),
322
-     *                    'edit' => esc_html__('label for editing item'),
323
-     *                    'delete' => esc_html__('label for deleting item')
324
-     *                ),
325
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
326
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
327
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
328
-     *            _define_page_props() method
329
-     *            'nav' => array(
330
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
331
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
332
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
333
-     *                'order' => 10, //required to indicate tab position.
334
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
335
-     *                displayed then add this parameter.
336
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
337
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
338
-     *            metaboxes set for eventespresso admin pages.
339
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
340
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
341
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
342
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
343
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
344
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
345
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
346
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
347
-     *            want to display.
348
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
349
-     *                'tab_id' => array(
350
-     *                    'title' => 'tab_title',
351
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
352
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
353
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
354
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
355
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
356
-     *                    attempt to use the callback which should match the name of a method in the class
357
-     *                    ),
358
-     *                'tab2_id' => array(
359
-     *                    'title' => 'tab2 title',
360
-     *                    'filename' => 'file_name_2'
361
-     *                    'callback' => 'callback_method_for_content',
362
-     *                 ),
363
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
364
-     *            help tab area on an admin page. @return void
365
-     *
366
-     * @link
367
-     *                http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
368
-     *                'help_tour' => array(
369
-     *                'name_of_help_tour_class', //all help tours should be a child class of EE_Help_Tour and located
370
-     *                in a folder for this admin page named "help_tours", a file name matching the key given here
371
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
372
-     *                ),
373
-     *                'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default
374
-     *                is true if it isn't present).  To remove the requirement for a nonce check when this route is
375
-     *                visited just set
376
-     *                'require_nonce' to FALSE
377
-     *                )
378
-     *                )
379
-     *
380
-     * @abstract
381
-     */
382
-    abstract protected function _set_page_config();
383
-
384
-
385
-
386
-
387
-
388
-    /** end sample help_tour methods **/
389
-    /**
390
-     * _add_screen_options
391
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
392
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
393
-     * to a particular view.
394
-     *
395
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
396
-     *         see also WP_Screen object documents...
397
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
398
-     * @abstract
399
-     * @return void
400
-     */
401
-    abstract protected function _add_screen_options();
402
-
403
-
404
-    /**
405
-     * _add_feature_pointers
406
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
407
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
408
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
409
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
410
-     * extended) also see:
411
-     *
412
-     * @link   http://eamann.com/tech/wordpress-portland/
413
-     * @abstract
414
-     * @return void
415
-     */
416
-    abstract protected function _add_feature_pointers();
417
-
418
-
419
-    /**
420
-     * load_scripts_styles
421
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
422
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
423
-     * scripts/styles per view by putting them in a dynamic function in this format
424
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
425
-     *
426
-     * @abstract
427
-     * @return void
428
-     */
429
-    abstract public function load_scripts_styles();
430
-
431
-
432
-    /**
433
-     * admin_init
434
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
435
-     * all pages/views loaded by child class.
436
-     *
437
-     * @abstract
438
-     * @return void
439
-     */
440
-    abstract public function admin_init();
441
-
442
-
443
-    /**
444
-     * admin_notices
445
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
446
-     * all pages/views loaded by child class.
447
-     *
448
-     * @abstract
449
-     * @return void
450
-     */
451
-    abstract public function admin_notices();
452
-
453
-
454
-    /**
455
-     * admin_footer_scripts
456
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
457
-     * will apply to all pages/views loaded by child class.
458
-     *
459
-     * @return void
460
-     */
461
-    abstract public function admin_footer_scripts();
462
-
463
-
464
-    /**
465
-     * admin_footer
466
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
467
-     * apply to all pages/views loaded by child class.
468
-     *
469
-     * @return void
470
-     */
471
-    public function admin_footer()
472
-    {
473
-    }
474
-
475
-
476
-    /**
477
-     * _global_ajax_hooks
478
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
479
-     * Note: within the ajax callback methods.
480
-     *
481
-     * @abstract
482
-     * @return void
483
-     */
484
-    protected function _global_ajax_hooks()
485
-    {
486
-        // for lazy loading of metabox content
487
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
488
-    }
489
-
490
-
491
-    public function ajax_metabox_content()
492
-    {
493
-        $content_id  = $this->request->getRequestParam('contentid', '');
494
-        $content_url = $this->request->getRequestParam('contenturl', '', 'url');
495
-        self::cached_rss_display($content_id, $content_url);
496
-        wp_die();
497
-    }
498
-
499
-
500
-    /**
501
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
502
-     *
503
-     * @return void
504
-     */
505
-    protected function _before_page_setup()
506
-    {
507
-        // default is to do nothing
508
-    }
509
-
510
-
511
-    /**
512
-     * Makes sure any things that need to be loaded early get handled.
513
-     * We also escape early here if the page requested doesn't match the object.
514
-     *
515
-     * @final
516
-     * @return void
517
-     * @throws EE_Error
518
-     * @throws InvalidArgumentException
519
-     * @throws ReflectionException
520
-     * @throws InvalidDataTypeException
521
-     * @throws InvalidInterfaceException
522
-     */
523
-    final protected function _page_setup()
524
-    {
525
-        // requires?
526
-        // admin_init stuff - global - we're setting this REALLY early
527
-        // so if EE_Admin pages have to hook into other WP pages they can.
528
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
529
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
530
-        // next verify if we need to load anything...
531
-        $this->_current_page = $this->request->getRequestParam('page', '', 'key');
532
-        $this->page_folder   = strtolower(
533
-            str_replace(['_Admin_Page', 'Extend_'], '', get_class($this))
534
-        );
535
-        global $ee_menu_slugs;
536
-        $ee_menu_slugs = (array) $ee_menu_slugs;
537
-        if (
538
-            ! $this->request->isAjax()
539
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
540
-        ) {
541
-            return;
542
-        }
543
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
544
-        // we need to copy the action from the second to the first
545
-        $action     = $this->request->getRequestParam('action', '-1', 'key');
546
-        $action2    = $this->request->getRequestParam('action2', '-1', 'key');
547
-        $action     = $action !== '-1' ? $action : $action2;
548
-        $req_action = $action !== '-1' ? $action : 'default';
549
-
550
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
551
-        // then let's use the route as the action.
552
-        // This covers cases where we're coming in from a list table that isn't on the default route.
553
-        $route = $this->request->getRequestParam('route');
554
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
555
-            ? $route
556
-            : $req_action;
557
-
558
-        $this->_current_view = $this->_req_action;
559
-        $this->_req_nonce    = $this->_req_action . '_nonce';
560
-        $this->_define_page_props();
561
-        $this->_current_page_view_url = add_query_arg(
562
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
563
-            $this->_admin_base_url
564
-        );
565
-        // default things
566
-        $this->_default_espresso_metaboxes = [
567
-            '_espresso_news_post_box',
568
-            '_espresso_links_post_box',
569
-            '_espresso_ratings_request',
570
-            '_espresso_sponsors_post_box',
571
-        ];
572
-        // set page configs
573
-        $this->_set_page_routes();
574
-        $this->_set_page_config();
575
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
576
-        if ($this->request->requestParamIsSet('wp_referer')) {
577
-            $wp_referer = $this->request->getRequestParam('wp_referer');
578
-            if ($wp_referer) {
579
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
580
-            }
581
-        }
582
-        // for caffeinated and other extended functionality.
583
-        //  If there is a _extend_page_config method
584
-        // then let's run that to modify the all the various page configuration arrays
585
-        if (method_exists($this, '_extend_page_config')) {
586
-            $this->_extend_page_config();
587
-        }
588
-        // for CPT and other extended functionality.
589
-        // If there is an _extend_page_config_for_cpt
590
-        // then let's run that to modify all the various page configuration arrays.
591
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
592
-            $this->_extend_page_config_for_cpt();
593
-        }
594
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
595
-        $this->_page_routes = apply_filters(
596
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
597
-            $this->_page_routes,
598
-            $this
599
-        );
600
-        $this->_page_config = apply_filters(
601
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
602
-            $this->_page_config,
603
-            $this
604
-        );
605
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
606
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
607
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
608
-            add_action(
609
-                'AHEE__EE_Admin_Page__route_admin_request',
610
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
611
-                10,
612
-                2
613
-            );
614
-        }
615
-        // next route only if routing enabled
616
-        if ($this->_routing && ! $this->request->isAjax()) {
617
-            $this->_verify_routes();
618
-            // next let's just check user_access and kill if no access
619
-            $this->check_user_access();
620
-            if ($this->_is_UI_request) {
621
-                // admin_init stuff - global, all views for this page class, specific view
622
-                add_action('admin_init', [$this, 'admin_init'], 10);
623
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
624
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
625
-                }
626
-            } else {
627
-                // hijack regular WP loading and route admin request immediately
628
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
629
-                $this->route_admin_request();
630
-            }
631
-        }
632
-    }
633
-
634
-
635
-    /**
636
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
637
-     *
638
-     * @return void
639
-     * @throws EE_Error
640
-     */
641
-    private function _do_other_page_hooks()
642
-    {
643
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
644
-        foreach ($registered_pages as $page) {
645
-            // now let's setup the file name and class that should be present
646
-            $classname = str_replace('.class.php', '', $page);
647
-            // autoloaders should take care of loading file
648
-            if (! class_exists($classname)) {
649
-                $error_msg[] = sprintf(
650
-                    esc_html__(
651
-                        'Something went wrong with loading the %s admin hooks page.',
652
-                        'event_espresso'
653
-                    ),
654
-                    $page
655
-                );
656
-                $error_msg[] = $error_msg[0]
657
-                               . "\r\n"
658
-                               . sprintf(
659
-                                   esc_html__(
660
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
661
-                                       'event_espresso'
662
-                                   ),
663
-                                   $page,
664
-                                   '<br />',
665
-                                   '<strong>' . $classname . '</strong>'
666
-                               );
667
-                throw new EE_Error(implode('||', $error_msg));
668
-            }
669
-            // notice we are passing the instance of this class to the hook object.
670
-            $this->loader->getShared($classname, [$this]);
671
-        }
672
-    }
673
-
674
-
675
-    /**
676
-     * @throws ReflectionException
677
-     * @throws EE_Error
678
-     */
679
-    public function load_page_dependencies()
680
-    {
681
-        try {
682
-            $this->_load_page_dependencies();
683
-        } catch (EE_Error $e) {
684
-            $e->get_error();
685
-        }
686
-    }
687
-
688
-
689
-    /**
690
-     * load_page_dependencies
691
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
692
-     *
693
-     * @return void
694
-     * @throws DomainException
695
-     * @throws EE_Error
696
-     * @throws InvalidArgumentException
697
-     * @throws InvalidDataTypeException
698
-     * @throws InvalidInterfaceException
699
-     */
700
-    protected function _load_page_dependencies()
701
-    {
702
-        // let's set the current_screen and screen options to override what WP set
703
-        $this->_current_screen = get_current_screen();
704
-        // load admin_notices - global, page class, and view specific
705
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
706
-        add_action('admin_notices', [$this, 'admin_notices'], 10);
707
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
708
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
709
-        }
710
-        // load network admin_notices - global, page class, and view specific
711
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
712
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
713
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
714
-        }
715
-        // this will save any per_page screen options if they are present
716
-        $this->_set_per_page_screen_options();
717
-        // setup list table properties
718
-        $this->_set_list_table();
719
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
720
-        // However in some cases the metaboxes will need to be added within a route handling callback.
721
-        $this->_add_registered_meta_boxes();
722
-        $this->_add_screen_columns();
723
-        // add screen options - global, page child class, and view specific
724
-        $this->_add_global_screen_options();
725
-        $this->_add_screen_options();
726
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
727
-        if (method_exists($this, $add_screen_options)) {
728
-            $this->{$add_screen_options}();
729
-        }
730
-        // add help tab(s) and tours- set via page_config and qtips.
731
-        // $this->_add_help_tour();
732
-        $this->_add_help_tabs();
733
-        $this->_add_qtips();
734
-        // add feature_pointers - global, page child class, and view specific
735
-        $this->_add_feature_pointers();
736
-        $this->_add_global_feature_pointers();
737
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
738
-        if (method_exists($this, $add_feature_pointer)) {
739
-            $this->{$add_feature_pointer}();
740
-        }
741
-        // enqueue scripts/styles - global, page class, and view specific
742
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
743
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
744
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
745
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
746
-        }
747
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
748
-        // admin_print_footer_scripts - global, page child class, and view specific.
749
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
750
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
751
-        // is a good use case. Notice the late priority we're giving these
752
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
753
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
754
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
755
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
756
-        }
757
-        // admin footer scripts
758
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
759
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
760
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
761
-            add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
762
-        }
763
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
764
-        // targeted hook
765
-        do_action(
766
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
767
-        );
768
-    }
769
-
770
-
771
-    /**
772
-     * _set_defaults
773
-     * This sets some global defaults for class properties.
774
-     */
775
-    private function _set_defaults()
776
-    {
777
-        $this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
778
-        $this->_event                = $this->_template_path = $this->_column_template_path = null;
779
-        $this->_nav_tabs             = $this->_views = $this->_page_routes = [];
780
-        $this->_page_config          = $this->_default_route_query_args = [];
781
-        $this->_default_nav_tab_name = 'overview';
782
-        // init template args
783
-        $this->_template_args = [
784
-            'admin_page_header'  => '',
785
-            'admin_page_content' => '',
786
-            'post_body_content'  => '',
787
-            'before_list_table'  => '',
788
-            'after_list_table'   => '',
789
-        ];
790
-    }
791
-
792
-
793
-    /**
794
-     * route_admin_request
795
-     *
796
-     * @return void
797
-     * @throws InvalidArgumentException
798
-     * @throws InvalidInterfaceException
799
-     * @throws InvalidDataTypeException
800
-     * @throws EE_Error
801
-     * @throws ReflectionException
802
-     * @see    _route_admin_request()
803
-     */
804
-    public function route_admin_request()
805
-    {
806
-        try {
807
-            $this->_route_admin_request();
808
-        } catch (EE_Error $e) {
809
-            $e->get_error();
810
-        }
811
-    }
812
-
813
-
814
-    public function set_wp_page_slug($wp_page_slug)
815
-    {
816
-        $this->_wp_page_slug = $wp_page_slug;
817
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
818
-        if (is_network_admin()) {
819
-            $this->_wp_page_slug .= '-network';
820
-        }
821
-    }
822
-
823
-
824
-    /**
825
-     * _verify_routes
826
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
827
-     * we know if we need to drop out.
828
-     *
829
-     * @return bool
830
-     * @throws EE_Error
831
-     */
832
-    protected function _verify_routes()
833
-    {
834
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
835
-        if (! $this->_current_page && ! $this->request->isAjax()) {
836
-            return false;
837
-        }
838
-        $this->_route = false;
839
-        // check that the page_routes array is not empty
840
-        if (empty($this->_page_routes)) {
841
-            // user error msg
842
-            $error_msg = sprintf(
843
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
844
-                $this->_admin_page_title
845
-            );
846
-            // developer error msg
847
-            $error_msg .= '||' . $error_msg
848
-                          . esc_html__(
849
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
850
-                              'event_espresso'
851
-                          );
852
-            throw new EE_Error($error_msg);
853
-        }
854
-        // and that the requested page route exists
855
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
856
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
857
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
858
-                ? $this->_page_config[ $this->_req_action ]
859
-                : [];
860
-        } else {
861
-            // user error msg
862
-            $error_msg = sprintf(
863
-                esc_html__(
864
-                    'The requested page route does not exist for the %s admin page.',
865
-                    'event_espresso'
866
-                ),
867
-                $this->_admin_page_title
868
-            );
869
-            // developer error msg
870
-            $error_msg .= '||' . $error_msg
871
-                          . sprintf(
872
-                              esc_html__(
873
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
874
-                                  'event_espresso'
875
-                              ),
876
-                              $this->_req_action
877
-                          );
878
-            throw new EE_Error($error_msg);
879
-        }
880
-        // and that a default route exists
881
-        if (! array_key_exists('default', $this->_page_routes)) {
882
-            // user error msg
883
-            $error_msg = sprintf(
884
-                esc_html__(
885
-                    'A default page route has not been set for the % admin page.',
886
-                    'event_espresso'
887
-                ),
888
-                $this->_admin_page_title
889
-            );
890
-            // developer error msg
891
-            $error_msg .= '||' . $error_msg
892
-                          . esc_html__(
893
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
894
-                              'event_espresso'
895
-                          );
896
-            throw new EE_Error($error_msg);
897
-        }
898
-        // first lets' catch if the UI request has EVER been set.
899
-        if ($this->_is_UI_request === null) {
900
-            // lets set if this is a UI request or not.
901
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
902
-            // wait a minute... we might have a noheader in the route array
903
-            $this->_is_UI_request = ! (
904
-                is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
905
-            )
906
-                ? $this->_is_UI_request
907
-                : false;
908
-        }
909
-        $this->_set_current_labels();
910
-        return true;
911
-    }
912
-
913
-
914
-    /**
915
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
916
-     *
917
-     * @param string $route the route name we're verifying
918
-     * @return bool we'll throw an exception if this isn't a valid route.
919
-     * @throws EE_Error
920
-     */
921
-    protected function _verify_route($route)
922
-    {
923
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
924
-            return true;
925
-        }
926
-        // user error msg
927
-        $error_msg = sprintf(
928
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
929
-            $this->_admin_page_title
930
-        );
931
-        // developer error msg
932
-        $error_msg .= '||' . $error_msg
933
-                      . sprintf(
934
-                          esc_html__(
935
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
936
-                              'event_espresso'
937
-                          ),
938
-                          $route
939
-                      );
940
-        throw new EE_Error($error_msg);
941
-    }
942
-
943
-
944
-    /**
945
-     * perform nonce verification
946
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
947
-     * using this method (and save retyping!)
948
-     *
949
-     * @param string $nonce     The nonce sent
950
-     * @param string $nonce_ref The nonce reference string (name0)
951
-     * @return void
952
-     * @throws EE_Error
953
-     */
954
-    protected function _verify_nonce($nonce, $nonce_ref)
955
-    {
956
-        // verify nonce against expected value
957
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
958
-            // these are not the droids you are looking for !!!
959
-            $msg = sprintf(
960
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
961
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
962
-                '</a>'
963
-            );
964
-            if (WP_DEBUG) {
965
-                $msg .= "\n  ";
966
-                $msg .= sprintf(
967
-                    esc_html__(
968
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
969
-                        'event_espresso'
970
-                    ),
971
-                    __CLASS__
972
-                );
973
-            }
974
-            if (! $this->request->isAjax()) {
975
-                wp_die($msg);
976
-            }
977
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
978
-            $this->_return_json();
979
-        }
980
-    }
981
-
982
-
983
-    /**
984
-     * _route_admin_request()
985
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
986
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
987
-     * in the page routes and then will try to load the corresponding method.
988
-     *
989
-     * @return void
990
-     * @throws EE_Error
991
-     * @throws InvalidArgumentException
992
-     * @throws InvalidDataTypeException
993
-     * @throws InvalidInterfaceException
994
-     * @throws ReflectionException
995
-     */
996
-    protected function _route_admin_request()
997
-    {
998
-        if (! $this->_is_UI_request) {
999
-            $this->_verify_routes();
1000
-        }
1001
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1002
-        if ($this->_req_action !== 'default' && $nonce_check) {
1003
-            // set nonce from post data
1004
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1005
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1006
-        }
1007
-        // set the nav_tabs array but ONLY if this is  UI_request
1008
-        if ($this->_is_UI_request) {
1009
-            $this->_set_nav_tabs();
1010
-        }
1011
-        // grab callback function
1012
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
1013
-        // check if callback has args
1014
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1015
-        $error_msg = '';
1016
-        // action right before calling route
1017
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1018
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1019
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1020
-        }
1021
-        // right before calling the route, let's clean the _wp_http_referer
1022
-        $this->request->setServerParam(
1023
-            'REQUEST_URI',
1024
-            remove_query_arg(
1025
-                '_wp_http_referer',
1026
-                wp_unslash($this->request->getServerParam('REQUEST_URI'))
1027
-            )
1028
-        );
1029
-        if (! empty($func)) {
1030
-            if (is_array($func)) {
1031
-                list($class, $method) = $func;
1032
-            } elseif (strpos($func, '::') !== false) {
1033
-                list($class, $method) = explode('::', $func);
1034
-            } else {
1035
-                $class  = $this;
1036
-                $method = $func;
1037
-            }
1038
-            if (! (is_object($class) && $class === $this)) {
1039
-                // send along this admin page object for access by addons.
1040
-                $args['admin_page_object'] = $this;
1041
-            }
1042
-            if (
115
+	/**
116
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
117
+	 * actions.
118
+	 *
119
+	 * @since 4.6.x
120
+	 * @var array.
121
+	 */
122
+	protected $_default_route_query_args;
123
+
124
+	// set via request page and action args.
125
+	protected $_current_page;
126
+
127
+	protected $_current_view;
128
+
129
+	protected $_current_page_view_url;
130
+
131
+	/**
132
+	 * unprocessed value for the 'action' request param (default '')
133
+	 *
134
+	 * @var string
135
+	 */
136
+	protected $raw_req_action = '';
137
+
138
+	/**
139
+	 * unprocessed value for the 'page' request param (default '')
140
+	 *
141
+	 * @var string
142
+	 */
143
+	protected $raw_req_page = '';
144
+
145
+	/**
146
+	 * sanitized request action (and nonce)
147
+	 *
148
+	 * @var string
149
+	 */
150
+	protected $_req_action = '';
151
+
152
+	/**
153
+	 * sanitized request action nonce
154
+	 *
155
+	 * @var string
156
+	 */
157
+	protected $_req_nonce = '';
158
+
159
+	/**
160
+	 * @var string
161
+	 */
162
+	protected $_search_btn_label = '';
163
+
164
+	/**
165
+	 * @var string
166
+	 */
167
+	protected $_search_box_callback = '';
168
+
169
+	/**
170
+	 * @var WP_Screen
171
+	 */
172
+	protected $_current_screen;
173
+
174
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
175
+	protected $_hook_obj;
176
+
177
+	// for holding incoming request data
178
+	protected $_req_data = [];
179
+
180
+	// yes / no array for admin form fields
181
+	protected $_yes_no_values = [];
182
+
183
+	// some default things shared by all child classes
184
+	protected $_default_espresso_metaboxes;
185
+
186
+	/**
187
+	 * @var EE_Registry
188
+	 */
189
+	protected $EE = null;
190
+
191
+
192
+	/**
193
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
194
+	 *
195
+	 * @var boolean
196
+	 */
197
+	protected $_is_caf = false;
198
+
199
+
200
+	/**
201
+	 * @Constructor
202
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
203
+	 * @throws EE_Error
204
+	 * @throws InvalidArgumentException
205
+	 * @throws ReflectionException
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 */
209
+	public function __construct($routing = true)
210
+	{
211
+		$this->loader  = LoaderFactory::getLoader();
212
+		$this->request = $this->loader->getShared(RequestInterface::class);
213
+		$this->_routing = $routing;
214
+
215
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
216
+			$this->_is_caf = true;
217
+		}
218
+		$this->_yes_no_values = [
219
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
220
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
221
+		];
222
+		// set the _req_data property.
223
+		$this->_req_data = $this->request->requestParams();
224
+		// set initial page props (child method)
225
+		$this->_init_page_props();
226
+		// set global defaults
227
+		$this->_set_defaults();
228
+		// set early because incoming requests could be ajax related and we need to register those hooks.
229
+		$this->_global_ajax_hooks();
230
+		$this->_ajax_hooks();
231
+		// other_page_hooks have to be early too.
232
+		$this->_do_other_page_hooks();
233
+		// set up page dependencies
234
+		$this->_before_page_setup();
235
+		$this->_page_setup();
236
+		// die();
237
+	}
238
+
239
+
240
+	/**
241
+	 * _init_page_props
242
+	 * Child classes use to set at least the following properties:
243
+	 * $page_slug.
244
+	 * $page_label.
245
+	 *
246
+	 * @abstract
247
+	 * @return void
248
+	 */
249
+	abstract protected function _init_page_props();
250
+
251
+
252
+	/**
253
+	 * _ajax_hooks
254
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
255
+	 * Note: within the ajax callback methods.
256
+	 *
257
+	 * @abstract
258
+	 * @return void
259
+	 */
260
+	abstract protected function _ajax_hooks();
261
+
262
+
263
+	/**
264
+	 * _define_page_props
265
+	 * child classes define page properties in here.  Must include at least:
266
+	 * $_admin_base_url = base_url for all admin pages
267
+	 * $_admin_page_title = default admin_page_title for admin pages
268
+	 * $_labels = array of default labels for various automatically generated elements:
269
+	 *    array(
270
+	 *        'buttons' => array(
271
+	 *            'add' => esc_html__('label for add new button'),
272
+	 *            'edit' => esc_html__('label for edit button'),
273
+	 *            'delete' => esc_html__('label for delete button')
274
+	 *            )
275
+	 *        )
276
+	 *
277
+	 * @abstract
278
+	 * @return void
279
+	 */
280
+	abstract protected function _define_page_props();
281
+
282
+
283
+	/**
284
+	 * _set_page_routes
285
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
286
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
287
+	 * have a 'default' route. Here's the format
288
+	 * $this->_page_routes = array(
289
+	 *        'default' => array(
290
+	 *            'func' => '_default_method_handling_route',
291
+	 *            'args' => array('array','of','args'),
292
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
293
+	 *            ajax request, backend processing)
294
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
295
+	 *            headers route after.  The string you enter here should match the defined route reference for a
296
+	 *            headers sent route.
297
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
298
+	 *            this route.
299
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
300
+	 *            checks).
301
+	 *        ),
302
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
303
+	 *        handling method.
304
+	 *        )
305
+	 * )
306
+	 *
307
+	 * @abstract
308
+	 * @return void
309
+	 */
310
+	abstract protected function _set_page_routes();
311
+
312
+
313
+	/**
314
+	 * _set_page_config
315
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
316
+	 * array corresponds to the page_route for the loaded page. Format:
317
+	 * $this->_page_config = array(
318
+	 *        'default' => array(
319
+	 *            'labels' => array(
320
+	 *                'buttons' => array(
321
+	 *                    'add' => esc_html__('label for adding item'),
322
+	 *                    'edit' => esc_html__('label for editing item'),
323
+	 *                    'delete' => esc_html__('label for deleting item')
324
+	 *                ),
325
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
326
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
327
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
328
+	 *            _define_page_props() method
329
+	 *            'nav' => array(
330
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
331
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
332
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
333
+	 *                'order' => 10, //required to indicate tab position.
334
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
335
+	 *                displayed then add this parameter.
336
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
337
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
338
+	 *            metaboxes set for eventespresso admin pages.
339
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
340
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
341
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
342
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
343
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
344
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
345
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
346
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
347
+	 *            want to display.
348
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
349
+	 *                'tab_id' => array(
350
+	 *                    'title' => 'tab_title',
351
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
352
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
353
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
354
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
355
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
356
+	 *                    attempt to use the callback which should match the name of a method in the class
357
+	 *                    ),
358
+	 *                'tab2_id' => array(
359
+	 *                    'title' => 'tab2 title',
360
+	 *                    'filename' => 'file_name_2'
361
+	 *                    'callback' => 'callback_method_for_content',
362
+	 *                 ),
363
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
364
+	 *            help tab area on an admin page. @return void
365
+	 *
366
+	 * @link
367
+	 *                http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
368
+	 *                'help_tour' => array(
369
+	 *                'name_of_help_tour_class', //all help tours should be a child class of EE_Help_Tour and located
370
+	 *                in a folder for this admin page named "help_tours", a file name matching the key given here
371
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
372
+	 *                ),
373
+	 *                'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default
374
+	 *                is true if it isn't present).  To remove the requirement for a nonce check when this route is
375
+	 *                visited just set
376
+	 *                'require_nonce' to FALSE
377
+	 *                )
378
+	 *                )
379
+	 *
380
+	 * @abstract
381
+	 */
382
+	abstract protected function _set_page_config();
383
+
384
+
385
+
386
+
387
+
388
+	/** end sample help_tour methods **/
389
+	/**
390
+	 * _add_screen_options
391
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
392
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
393
+	 * to a particular view.
394
+	 *
395
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
396
+	 *         see also WP_Screen object documents...
397
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
398
+	 * @abstract
399
+	 * @return void
400
+	 */
401
+	abstract protected function _add_screen_options();
402
+
403
+
404
+	/**
405
+	 * _add_feature_pointers
406
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
407
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
408
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
409
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
410
+	 * extended) also see:
411
+	 *
412
+	 * @link   http://eamann.com/tech/wordpress-portland/
413
+	 * @abstract
414
+	 * @return void
415
+	 */
416
+	abstract protected function _add_feature_pointers();
417
+
418
+
419
+	/**
420
+	 * load_scripts_styles
421
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
422
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
423
+	 * scripts/styles per view by putting them in a dynamic function in this format
424
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
425
+	 *
426
+	 * @abstract
427
+	 * @return void
428
+	 */
429
+	abstract public function load_scripts_styles();
430
+
431
+
432
+	/**
433
+	 * admin_init
434
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
435
+	 * all pages/views loaded by child class.
436
+	 *
437
+	 * @abstract
438
+	 * @return void
439
+	 */
440
+	abstract public function admin_init();
441
+
442
+
443
+	/**
444
+	 * admin_notices
445
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
446
+	 * all pages/views loaded by child class.
447
+	 *
448
+	 * @abstract
449
+	 * @return void
450
+	 */
451
+	abstract public function admin_notices();
452
+
453
+
454
+	/**
455
+	 * admin_footer_scripts
456
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
457
+	 * will apply to all pages/views loaded by child class.
458
+	 *
459
+	 * @return void
460
+	 */
461
+	abstract public function admin_footer_scripts();
462
+
463
+
464
+	/**
465
+	 * admin_footer
466
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
467
+	 * apply to all pages/views loaded by child class.
468
+	 *
469
+	 * @return void
470
+	 */
471
+	public function admin_footer()
472
+	{
473
+	}
474
+
475
+
476
+	/**
477
+	 * _global_ajax_hooks
478
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
479
+	 * Note: within the ajax callback methods.
480
+	 *
481
+	 * @abstract
482
+	 * @return void
483
+	 */
484
+	protected function _global_ajax_hooks()
485
+	{
486
+		// for lazy loading of metabox content
487
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
488
+	}
489
+
490
+
491
+	public function ajax_metabox_content()
492
+	{
493
+		$content_id  = $this->request->getRequestParam('contentid', '');
494
+		$content_url = $this->request->getRequestParam('contenturl', '', 'url');
495
+		self::cached_rss_display($content_id, $content_url);
496
+		wp_die();
497
+	}
498
+
499
+
500
+	/**
501
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
502
+	 *
503
+	 * @return void
504
+	 */
505
+	protected function _before_page_setup()
506
+	{
507
+		// default is to do nothing
508
+	}
509
+
510
+
511
+	/**
512
+	 * Makes sure any things that need to be loaded early get handled.
513
+	 * We also escape early here if the page requested doesn't match the object.
514
+	 *
515
+	 * @final
516
+	 * @return void
517
+	 * @throws EE_Error
518
+	 * @throws InvalidArgumentException
519
+	 * @throws ReflectionException
520
+	 * @throws InvalidDataTypeException
521
+	 * @throws InvalidInterfaceException
522
+	 */
523
+	final protected function _page_setup()
524
+	{
525
+		// requires?
526
+		// admin_init stuff - global - we're setting this REALLY early
527
+		// so if EE_Admin pages have to hook into other WP pages they can.
528
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
529
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
530
+		// next verify if we need to load anything...
531
+		$this->_current_page = $this->request->getRequestParam('page', '', 'key');
532
+		$this->page_folder   = strtolower(
533
+			str_replace(['_Admin_Page', 'Extend_'], '', get_class($this))
534
+		);
535
+		global $ee_menu_slugs;
536
+		$ee_menu_slugs = (array) $ee_menu_slugs;
537
+		if (
538
+			! $this->request->isAjax()
539
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
540
+		) {
541
+			return;
542
+		}
543
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
544
+		// we need to copy the action from the second to the first
545
+		$action     = $this->request->getRequestParam('action', '-1', 'key');
546
+		$action2    = $this->request->getRequestParam('action2', '-1', 'key');
547
+		$action     = $action !== '-1' ? $action : $action2;
548
+		$req_action = $action !== '-1' ? $action : 'default';
549
+
550
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
551
+		// then let's use the route as the action.
552
+		// This covers cases where we're coming in from a list table that isn't on the default route.
553
+		$route = $this->request->getRequestParam('route');
554
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
555
+			? $route
556
+			: $req_action;
557
+
558
+		$this->_current_view = $this->_req_action;
559
+		$this->_req_nonce    = $this->_req_action . '_nonce';
560
+		$this->_define_page_props();
561
+		$this->_current_page_view_url = add_query_arg(
562
+			['page' => $this->_current_page, 'action' => $this->_current_view],
563
+			$this->_admin_base_url
564
+		);
565
+		// default things
566
+		$this->_default_espresso_metaboxes = [
567
+			'_espresso_news_post_box',
568
+			'_espresso_links_post_box',
569
+			'_espresso_ratings_request',
570
+			'_espresso_sponsors_post_box',
571
+		];
572
+		// set page configs
573
+		$this->_set_page_routes();
574
+		$this->_set_page_config();
575
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
576
+		if ($this->request->requestParamIsSet('wp_referer')) {
577
+			$wp_referer = $this->request->getRequestParam('wp_referer');
578
+			if ($wp_referer) {
579
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
580
+			}
581
+		}
582
+		// for caffeinated and other extended functionality.
583
+		//  If there is a _extend_page_config method
584
+		// then let's run that to modify the all the various page configuration arrays
585
+		if (method_exists($this, '_extend_page_config')) {
586
+			$this->_extend_page_config();
587
+		}
588
+		// for CPT and other extended functionality.
589
+		// If there is an _extend_page_config_for_cpt
590
+		// then let's run that to modify all the various page configuration arrays.
591
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
592
+			$this->_extend_page_config_for_cpt();
593
+		}
594
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
595
+		$this->_page_routes = apply_filters(
596
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
597
+			$this->_page_routes,
598
+			$this
599
+		);
600
+		$this->_page_config = apply_filters(
601
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
602
+			$this->_page_config,
603
+			$this
604
+		);
605
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
606
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
607
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
608
+			add_action(
609
+				'AHEE__EE_Admin_Page__route_admin_request',
610
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
611
+				10,
612
+				2
613
+			);
614
+		}
615
+		// next route only if routing enabled
616
+		if ($this->_routing && ! $this->request->isAjax()) {
617
+			$this->_verify_routes();
618
+			// next let's just check user_access and kill if no access
619
+			$this->check_user_access();
620
+			if ($this->_is_UI_request) {
621
+				// admin_init stuff - global, all views for this page class, specific view
622
+				add_action('admin_init', [$this, 'admin_init'], 10);
623
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
624
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
625
+				}
626
+			} else {
627
+				// hijack regular WP loading and route admin request immediately
628
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
629
+				$this->route_admin_request();
630
+			}
631
+		}
632
+	}
633
+
634
+
635
+	/**
636
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
637
+	 *
638
+	 * @return void
639
+	 * @throws EE_Error
640
+	 */
641
+	private function _do_other_page_hooks()
642
+	{
643
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
644
+		foreach ($registered_pages as $page) {
645
+			// now let's setup the file name and class that should be present
646
+			$classname = str_replace('.class.php', '', $page);
647
+			// autoloaders should take care of loading file
648
+			if (! class_exists($classname)) {
649
+				$error_msg[] = sprintf(
650
+					esc_html__(
651
+						'Something went wrong with loading the %s admin hooks page.',
652
+						'event_espresso'
653
+					),
654
+					$page
655
+				);
656
+				$error_msg[] = $error_msg[0]
657
+							   . "\r\n"
658
+							   . sprintf(
659
+								   esc_html__(
660
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
661
+									   'event_espresso'
662
+								   ),
663
+								   $page,
664
+								   '<br />',
665
+								   '<strong>' . $classname . '</strong>'
666
+							   );
667
+				throw new EE_Error(implode('||', $error_msg));
668
+			}
669
+			// notice we are passing the instance of this class to the hook object.
670
+			$this->loader->getShared($classname, [$this]);
671
+		}
672
+	}
673
+
674
+
675
+	/**
676
+	 * @throws ReflectionException
677
+	 * @throws EE_Error
678
+	 */
679
+	public function load_page_dependencies()
680
+	{
681
+		try {
682
+			$this->_load_page_dependencies();
683
+		} catch (EE_Error $e) {
684
+			$e->get_error();
685
+		}
686
+	}
687
+
688
+
689
+	/**
690
+	 * load_page_dependencies
691
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
692
+	 *
693
+	 * @return void
694
+	 * @throws DomainException
695
+	 * @throws EE_Error
696
+	 * @throws InvalidArgumentException
697
+	 * @throws InvalidDataTypeException
698
+	 * @throws InvalidInterfaceException
699
+	 */
700
+	protected function _load_page_dependencies()
701
+	{
702
+		// let's set the current_screen and screen options to override what WP set
703
+		$this->_current_screen = get_current_screen();
704
+		// load admin_notices - global, page class, and view specific
705
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
706
+		add_action('admin_notices', [$this, 'admin_notices'], 10);
707
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
708
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
709
+		}
710
+		// load network admin_notices - global, page class, and view specific
711
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
712
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
713
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
714
+		}
715
+		// this will save any per_page screen options if they are present
716
+		$this->_set_per_page_screen_options();
717
+		// setup list table properties
718
+		$this->_set_list_table();
719
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
720
+		// However in some cases the metaboxes will need to be added within a route handling callback.
721
+		$this->_add_registered_meta_boxes();
722
+		$this->_add_screen_columns();
723
+		// add screen options - global, page child class, and view specific
724
+		$this->_add_global_screen_options();
725
+		$this->_add_screen_options();
726
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
727
+		if (method_exists($this, $add_screen_options)) {
728
+			$this->{$add_screen_options}();
729
+		}
730
+		// add help tab(s) and tours- set via page_config and qtips.
731
+		// $this->_add_help_tour();
732
+		$this->_add_help_tabs();
733
+		$this->_add_qtips();
734
+		// add feature_pointers - global, page child class, and view specific
735
+		$this->_add_feature_pointers();
736
+		$this->_add_global_feature_pointers();
737
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
738
+		if (method_exists($this, $add_feature_pointer)) {
739
+			$this->{$add_feature_pointer}();
740
+		}
741
+		// enqueue scripts/styles - global, page class, and view specific
742
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
743
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
744
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
745
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
746
+		}
747
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
748
+		// admin_print_footer_scripts - global, page child class, and view specific.
749
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
750
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
751
+		// is a good use case. Notice the late priority we're giving these
752
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
753
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
754
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
755
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
756
+		}
757
+		// admin footer scripts
758
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
759
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
760
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
761
+			add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
762
+		}
763
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
764
+		// targeted hook
765
+		do_action(
766
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
767
+		);
768
+	}
769
+
770
+
771
+	/**
772
+	 * _set_defaults
773
+	 * This sets some global defaults for class properties.
774
+	 */
775
+	private function _set_defaults()
776
+	{
777
+		$this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
778
+		$this->_event                = $this->_template_path = $this->_column_template_path = null;
779
+		$this->_nav_tabs             = $this->_views = $this->_page_routes = [];
780
+		$this->_page_config          = $this->_default_route_query_args = [];
781
+		$this->_default_nav_tab_name = 'overview';
782
+		// init template args
783
+		$this->_template_args = [
784
+			'admin_page_header'  => '',
785
+			'admin_page_content' => '',
786
+			'post_body_content'  => '',
787
+			'before_list_table'  => '',
788
+			'after_list_table'   => '',
789
+		];
790
+	}
791
+
792
+
793
+	/**
794
+	 * route_admin_request
795
+	 *
796
+	 * @return void
797
+	 * @throws InvalidArgumentException
798
+	 * @throws InvalidInterfaceException
799
+	 * @throws InvalidDataTypeException
800
+	 * @throws EE_Error
801
+	 * @throws ReflectionException
802
+	 * @see    _route_admin_request()
803
+	 */
804
+	public function route_admin_request()
805
+	{
806
+		try {
807
+			$this->_route_admin_request();
808
+		} catch (EE_Error $e) {
809
+			$e->get_error();
810
+		}
811
+	}
812
+
813
+
814
+	public function set_wp_page_slug($wp_page_slug)
815
+	{
816
+		$this->_wp_page_slug = $wp_page_slug;
817
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
818
+		if (is_network_admin()) {
819
+			$this->_wp_page_slug .= '-network';
820
+		}
821
+	}
822
+
823
+
824
+	/**
825
+	 * _verify_routes
826
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
827
+	 * we know if we need to drop out.
828
+	 *
829
+	 * @return bool
830
+	 * @throws EE_Error
831
+	 */
832
+	protected function _verify_routes()
833
+	{
834
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
835
+		if (! $this->_current_page && ! $this->request->isAjax()) {
836
+			return false;
837
+		}
838
+		$this->_route = false;
839
+		// check that the page_routes array is not empty
840
+		if (empty($this->_page_routes)) {
841
+			// user error msg
842
+			$error_msg = sprintf(
843
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
844
+				$this->_admin_page_title
845
+			);
846
+			// developer error msg
847
+			$error_msg .= '||' . $error_msg
848
+						  . esc_html__(
849
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
850
+							  'event_espresso'
851
+						  );
852
+			throw new EE_Error($error_msg);
853
+		}
854
+		// and that the requested page route exists
855
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
856
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
857
+			$this->_route_config = isset($this->_page_config[ $this->_req_action ])
858
+				? $this->_page_config[ $this->_req_action ]
859
+				: [];
860
+		} else {
861
+			// user error msg
862
+			$error_msg = sprintf(
863
+				esc_html__(
864
+					'The requested page route does not exist for the %s admin page.',
865
+					'event_espresso'
866
+				),
867
+				$this->_admin_page_title
868
+			);
869
+			// developer error msg
870
+			$error_msg .= '||' . $error_msg
871
+						  . sprintf(
872
+							  esc_html__(
873
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
874
+								  'event_espresso'
875
+							  ),
876
+							  $this->_req_action
877
+						  );
878
+			throw new EE_Error($error_msg);
879
+		}
880
+		// and that a default route exists
881
+		if (! array_key_exists('default', $this->_page_routes)) {
882
+			// user error msg
883
+			$error_msg = sprintf(
884
+				esc_html__(
885
+					'A default page route has not been set for the % admin page.',
886
+					'event_espresso'
887
+				),
888
+				$this->_admin_page_title
889
+			);
890
+			// developer error msg
891
+			$error_msg .= '||' . $error_msg
892
+						  . esc_html__(
893
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
894
+							  'event_espresso'
895
+						  );
896
+			throw new EE_Error($error_msg);
897
+		}
898
+		// first lets' catch if the UI request has EVER been set.
899
+		if ($this->_is_UI_request === null) {
900
+			// lets set if this is a UI request or not.
901
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
902
+			// wait a minute... we might have a noheader in the route array
903
+			$this->_is_UI_request = ! (
904
+				is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
905
+			)
906
+				? $this->_is_UI_request
907
+				: false;
908
+		}
909
+		$this->_set_current_labels();
910
+		return true;
911
+	}
912
+
913
+
914
+	/**
915
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
916
+	 *
917
+	 * @param string $route the route name we're verifying
918
+	 * @return bool we'll throw an exception if this isn't a valid route.
919
+	 * @throws EE_Error
920
+	 */
921
+	protected function _verify_route($route)
922
+	{
923
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
924
+			return true;
925
+		}
926
+		// user error msg
927
+		$error_msg = sprintf(
928
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
929
+			$this->_admin_page_title
930
+		);
931
+		// developer error msg
932
+		$error_msg .= '||' . $error_msg
933
+					  . sprintf(
934
+						  esc_html__(
935
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
936
+							  'event_espresso'
937
+						  ),
938
+						  $route
939
+					  );
940
+		throw new EE_Error($error_msg);
941
+	}
942
+
943
+
944
+	/**
945
+	 * perform nonce verification
946
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
947
+	 * using this method (and save retyping!)
948
+	 *
949
+	 * @param string $nonce     The nonce sent
950
+	 * @param string $nonce_ref The nonce reference string (name0)
951
+	 * @return void
952
+	 * @throws EE_Error
953
+	 */
954
+	protected function _verify_nonce($nonce, $nonce_ref)
955
+	{
956
+		// verify nonce against expected value
957
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
958
+			// these are not the droids you are looking for !!!
959
+			$msg = sprintf(
960
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
961
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
962
+				'</a>'
963
+			);
964
+			if (WP_DEBUG) {
965
+				$msg .= "\n  ";
966
+				$msg .= sprintf(
967
+					esc_html__(
968
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
969
+						'event_espresso'
970
+					),
971
+					__CLASS__
972
+				);
973
+			}
974
+			if (! $this->request->isAjax()) {
975
+				wp_die($msg);
976
+			}
977
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
978
+			$this->_return_json();
979
+		}
980
+	}
981
+
982
+
983
+	/**
984
+	 * _route_admin_request()
985
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
986
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
987
+	 * in the page routes and then will try to load the corresponding method.
988
+	 *
989
+	 * @return void
990
+	 * @throws EE_Error
991
+	 * @throws InvalidArgumentException
992
+	 * @throws InvalidDataTypeException
993
+	 * @throws InvalidInterfaceException
994
+	 * @throws ReflectionException
995
+	 */
996
+	protected function _route_admin_request()
997
+	{
998
+		if (! $this->_is_UI_request) {
999
+			$this->_verify_routes();
1000
+		}
1001
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1002
+		if ($this->_req_action !== 'default' && $nonce_check) {
1003
+			// set nonce from post data
1004
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1005
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1006
+		}
1007
+		// set the nav_tabs array but ONLY if this is  UI_request
1008
+		if ($this->_is_UI_request) {
1009
+			$this->_set_nav_tabs();
1010
+		}
1011
+		// grab callback function
1012
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
1013
+		// check if callback has args
1014
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1015
+		$error_msg = '';
1016
+		// action right before calling route
1017
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1018
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1019
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1020
+		}
1021
+		// right before calling the route, let's clean the _wp_http_referer
1022
+		$this->request->setServerParam(
1023
+			'REQUEST_URI',
1024
+			remove_query_arg(
1025
+				'_wp_http_referer',
1026
+				wp_unslash($this->request->getServerParam('REQUEST_URI'))
1027
+			)
1028
+		);
1029
+		if (! empty($func)) {
1030
+			if (is_array($func)) {
1031
+				list($class, $method) = $func;
1032
+			} elseif (strpos($func, '::') !== false) {
1033
+				list($class, $method) = explode('::', $func);
1034
+			} else {
1035
+				$class  = $this;
1036
+				$method = $func;
1037
+			}
1038
+			if (! (is_object($class) && $class === $this)) {
1039
+				// send along this admin page object for access by addons.
1040
+				$args['admin_page_object'] = $this;
1041
+			}
1042
+			if (
1043 1043
 // is it a method on a class that doesn't work?
1044
-                (
1045
-                    (
1046
-                        method_exists($class, $method)
1047
-                        && call_user_func_array([$class, $method], $args) === false
1048
-                    )
1049
-                    && (
1050
-                        // is it a standalone function that doesn't work?
1051
-                        function_exists($method)
1052
-                        && call_user_func_array(
1053
-                            $func,
1054
-                            array_merge(['admin_page_object' => $this], $args)
1055
-                        ) === false
1056
-                    )
1057
-                )
1058
-                || (
1059
-                    // is it neither a class method NOR a standalone function?
1060
-                    ! method_exists($class, $method)
1061
-                    && ! function_exists($method)
1062
-                )
1063
-            ) {
1064
-                // user error msg
1065
-                $error_msg = esc_html__(
1066
-                    'An error occurred. The  requested page route could not be found.',
1067
-                    'event_espresso'
1068
-                );
1069
-                // developer error msg
1070
-                $error_msg .= '||';
1071
-                $error_msg .= sprintf(
1072
-                    esc_html__(
1073
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1074
-                        'event_espresso'
1075
-                    ),
1076
-                    $method
1077
-                );
1078
-            }
1079
-            if (! empty($error_msg)) {
1080
-                throw new EE_Error($error_msg);
1081
-            }
1082
-        }
1083
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1084
-        // then we need to reset the routing properties to the new route.
1085
-        // now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1086
-        if (
1087
-            $this->_is_UI_request === false
1088
-            && is_array($this->_route)
1089
-            && ! empty($this->_route['headers_sent_route'])
1090
-        ) {
1091
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1092
-        }
1093
-    }
1094
-
1095
-
1096
-    /**
1097
-     * This method just allows the resetting of page properties in the case where a no headers
1098
-     * route redirects to a headers route in its route config.
1099
-     *
1100
-     * @param string $new_route New (non header) route to redirect to.
1101
-     * @return   void
1102
-     * @throws ReflectionException
1103
-     * @throws InvalidArgumentException
1104
-     * @throws InvalidInterfaceException
1105
-     * @throws InvalidDataTypeException
1106
-     * @throws EE_Error
1107
-     * @since   4.3.0
1108
-     */
1109
-    protected function _reset_routing_properties($new_route)
1110
-    {
1111
-        $this->_is_UI_request = true;
1112
-        // now we set the current route to whatever the headers_sent_route is set at
1113
-        $this->request->setRequestParam('action', $new_route);
1114
-        // rerun page setup
1115
-        $this->_page_setup();
1116
-    }
1117
-
1118
-
1119
-    /**
1120
-     * _add_query_arg
1121
-     * adds nonce to array of arguments then calls WP add_query_arg function
1122
-     *(internally just uses EEH_URL's function with the same name)
1123
-     *
1124
-     * @param array  $args
1125
-     * @param string $url
1126
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1127
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1128
-     *                                        Example usage: If the current page is:
1129
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1130
-     *                                        &action=default&event_id=20&month_range=March%202015
1131
-     *                                        &_wpnonce=5467821
1132
-     *                                        and you call:
1133
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1134
-     *                                        array(
1135
-     *                                        'action' => 'resend_something',
1136
-     *                                        'page=>espresso_registrations'
1137
-     *                                        ),
1138
-     *                                        $some_url,
1139
-     *                                        true
1140
-     *                                        );
1141
-     *                                        It will produce a url in this structure:
1142
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1143
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1144
-     *                                        month_range]=March%202015
1145
-     * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1146
-     * @return string
1147
-     */
1148
-    public static function add_query_args_and_nonce(
1149
-        $args = [],
1150
-        $url = false,
1151
-        $sticky = false,
1152
-        $exclude_nonce = false
1153
-    ) {
1154
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1155
-        if ($sticky) {
1156
-            /** @var RequestInterface $request */
1157
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1158
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer']);
1159
-            foreach ($request->requestParams() as $key => $value) {
1160
-                // do not add nonces
1161
-                if (strpos($key, 'nonce') !== false) {
1162
-                    continue;
1163
-                }
1164
-                $args[ 'wp_referer[' . $key . ']' ] = $value;
1165
-            }
1166
-        }
1167
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1168
-    }
1169
-
1170
-
1171
-    /**
1172
-     * This returns a generated link that will load the related help tab.
1173
-     *
1174
-     * @param string $help_tab_id the id for the connected help tab
1175
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1176
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1177
-     * @return string              generated link
1178
-     * @uses EEH_Template::get_help_tab_link()
1179
-     */
1180
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1181
-    {
1182
-        return EEH_Template::get_help_tab_link(
1183
-            $help_tab_id,
1184
-            $this->page_slug,
1185
-            $this->_req_action,
1186
-            $icon_style,
1187
-            $help_text
1188
-        );
1189
-    }
1190
-
1191
-
1192
-    /**
1193
-     * _add_help_tabs
1194
-     * Note child classes define their help tabs within the page_config array.
1195
-     *
1196
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1197
-     * @return void
1198
-     * @throws DomainException
1199
-     * @throws EE_Error
1200
-     */
1201
-    protected function _add_help_tabs()
1202
-    {
1203
-        $tour_buttons = '';
1204
-        if (isset($this->_page_config[ $this->_req_action ])) {
1205
-            $config = $this->_page_config[ $this->_req_action ];
1206
-            // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1207
-            // is there a help tour for the current route?  if there is let's setup the tour buttons
1208
-            // if (isset($this->_help_tour[ $this->_req_action ])) {
1209
-            //     $tb = array();
1210
-            //     $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1211
-            //     foreach ($this->_help_tour['tours'] as $tour) {
1212
-            //         // if this is the end tour then we don't need to setup a button
1213
-            //         if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1214
-            //             continue;
1215
-            //         }
1216
-            //         $tb[] = '<button id="trigger-tour-'
1217
-            //                 . $tour->get_slug()
1218
-            //                 . '" class="button-primary trigger-ee-help-tour">'
1219
-            //                 . $tour->get_label()
1220
-            //                 . '</button>';
1221
-            //     }
1222
-            //     $tour_buttons .= implode('<br />', $tb);
1223
-            //     $tour_buttons .= '</div></div>';
1224
-            // }
1225
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1226
-            if (is_array($config) && isset($config['help_sidebar'])) {
1227
-                // check that the callback given is valid
1228
-                if (! method_exists($this, $config['help_sidebar'])) {
1229
-                    throw new EE_Error(
1230
-                        sprintf(
1231
-                            esc_html__(
1232
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1233
-                                'event_espresso'
1234
-                            ),
1235
-                            $config['help_sidebar'],
1236
-                            get_class($this)
1237
-                        )
1238
-                    );
1239
-                }
1240
-                $content = apply_filters(
1241
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1242
-                    $this->{$config['help_sidebar']}()
1243
-                );
1244
-                $content .= $tour_buttons; // add help tour buttons.
1245
-                // do we have any help tours setup?  Cause if we do we want to add the buttons
1246
-                $this->_current_screen->set_help_sidebar($content);
1247
-            }
1248
-            // if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1249
-            if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1250
-                $this->_current_screen->set_help_sidebar($tour_buttons);
1251
-            }
1252
-            // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1253
-            if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1254
-                $_ht['id']      = $this->page_slug;
1255
-                $_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1256
-                $_ht['content'] = '<p>'
1257
-                                  . esc_html__(
1258
-                                      'The buttons to the right allow you to start/restart any help tours available for this page',
1259
-                                      'event_espresso'
1260
-                                  ) . '</p>';
1261
-                $this->_current_screen->add_help_tab($_ht);
1262
-            }
1263
-            if (! isset($config['help_tabs'])) {
1264
-                return;
1265
-            } //no help tabs for this route
1266
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1267
-                // we're here so there ARE help tabs!
1268
-                // make sure we've got what we need
1269
-                if (! isset($cfg['title'])) {
1270
-                    throw new EE_Error(
1271
-                        esc_html__(
1272
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1273
-                            'event_espresso'
1274
-                        )
1275
-                    );
1276
-                }
1277
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1278
-                    throw new EE_Error(
1279
-                        esc_html__(
1280
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1281
-                            'event_espresso'
1282
-                        )
1283
-                    );
1284
-                }
1285
-                // first priority goes to content.
1286
-                if (! empty($cfg['content'])) {
1287
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1288
-                    // second priority goes to filename
1289
-                } elseif (! empty($cfg['filename'])) {
1290
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1291
-                    // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1292
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1293
-                                                             . basename($this->_get_dir())
1294
-                                                             . '/help_tabs/'
1295
-                                                             . $cfg['filename']
1296
-                                                             . '.help_tab.php' : $file_path;
1297
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1298
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1299
-                        EE_Error::add_error(
1300
-                            sprintf(
1301
-                                esc_html__(
1302
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1303
-                                    'event_espresso'
1304
-                                ),
1305
-                                $tab_id,
1306
-                                key($config),
1307
-                                $file_path
1308
-                            ),
1309
-                            __FILE__,
1310
-                            __FUNCTION__,
1311
-                            __LINE__
1312
-                        );
1313
-                        return;
1314
-                    }
1315
-                    $template_args['admin_page_obj'] = $this;
1316
-                    $content                         = EEH_Template::display_template(
1317
-                        $file_path,
1318
-                        $template_args,
1319
-                        true
1320
-                    );
1321
-                } else {
1322
-                    $content = '';
1323
-                }
1324
-                // check if callback is valid
1325
-                if (
1326
-                    empty($content)
1327
-                    && (
1328
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1329
-                    )
1330
-                ) {
1331
-                    EE_Error::add_error(
1332
-                        sprintf(
1333
-                            esc_html__(
1334
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1335
-                                'event_espresso'
1336
-                            ),
1337
-                            $cfg['title']
1338
-                        ),
1339
-                        __FILE__,
1340
-                        __FUNCTION__,
1341
-                        __LINE__
1342
-                    );
1343
-                    return;
1344
-                }
1345
-                // setup config array for help tab method
1346
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1347
-                $_ht = [
1348
-                    'id'       => $id,
1349
-                    'title'    => $cfg['title'],
1350
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1351
-                    'content'  => $content,
1352
-                ];
1353
-                $this->_current_screen->add_help_tab($_ht);
1354
-            }
1355
-        }
1356
-    }
1357
-
1358
-
1359
-    /**
1360
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1361
-     * an array with properties for setting up usage of the joyride plugin
1362
-     *
1363
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1364
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1365
-     *         _set_page_config() comments
1366
-     * @return void
1367
-     * @throws InvalidArgumentException
1368
-     * @throws InvalidDataTypeException
1369
-     * @throws InvalidInterfaceException
1370
-     */
1371
-    protected function _add_help_tour()
1372
-    {
1373
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1374
-        // $tours = array();
1375
-        // $this->_help_tour = array();
1376
-        // // exit early if help tours are turned off globally
1377
-        // if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1378
-        //     || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1379
-        // ) {
1380
-        //     return;
1381
-        // }
1382
-        // // loop through _page_config to find any help_tour defined
1383
-        // foreach ($this->_page_config as $route => $config) {
1384
-        //     // we're only going to set things up for this route
1385
-        //     if ($route !== $this->_req_action) {
1386
-        //         continue;
1387
-        //     }
1388
-        //     if (isset($config['help_tour'])) {
1389
-        //         foreach ($config['help_tour'] as $tour) {
1390
-        //             $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1391
-        //             // let's see if we can get that file...
1392
-        //             // if not its possible this is a decaf route not set in caffeinated
1393
-        //             // so lets try and get the caffeinated equivalent
1394
-        //             $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1395
-        //                                                      . basename($this->_get_dir())
1396
-        //                                                      . '/help_tours/'
1397
-        //                                                      . $tour
1398
-        //                                                      . '.class.php' : $file_path;
1399
-        //             // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1400
-        //             if (! is_readable($file_path)) {
1401
-        //                 EE_Error::add_error(
1402
-        //                     sprintf(
1403
-        //                         esc_html__(
1404
-        //                             'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1405
-        //                             'event_espresso'
1406
-        //                         ),
1407
-        //                         $file_path,
1408
-        //                         $tour
1409
-        //                     ),
1410
-        //                     __FILE__,
1411
-        //                     __FUNCTION__,
1412
-        //                     __LINE__
1413
-        //                 );
1414
-        //                 return;
1415
-        //             }
1416
-        //             require_once $file_path;
1417
-        //             if (! class_exists($tour)) {
1418
-        //                 $error_msg[] = sprintf(
1419
-        //                     esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1420
-        //                     $tour
1421
-        //                 );
1422
-        //                 $error_msg[] = $error_msg[0] . "\r\n"
1423
-        //                                . sprintf(
1424
-        //                                    esc_html__(
1425
-        //                                        'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1426
-        //                                        'event_espresso'
1427
-        //                                    ),
1428
-        //                                    $tour,
1429
-        //                                    '<br />',
1430
-        //                                    $tour,
1431
-        //                                    $this->_req_action,
1432
-        //                                    get_class($this)
1433
-        //                                );
1434
-        //                 throw new EE_Error(implode('||', $error_msg));
1435
-        //             }
1436
-        //             $tour_obj = new $tour($this->_is_caf);
1437
-        //             $tours[] = $tour_obj;
1438
-        //             $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1439
-        //         }
1440
-        //         // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1441
-        //         $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1442
-        //         $tours[] = $end_stop_tour;
1443
-        //         $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1444
-        //     }
1445
-        // }
1446
-        //
1447
-        // if (! empty($tours)) {
1448
-        //     $this->_help_tour['tours'] = $tours;
1449
-        // }
1450
-        // // that's it!  Now that the $_help_tours property is set (or not)
1451
-        // // the scripts and html should be taken care of automatically.
1452
-        //
1453
-        // /**
1454
-        //  * Allow extending the help tours variable.
1455
-        //  *
1456
-        //  * @param Array $_help_tour The array containing all help tour information to be displayed.
1457
-        //  */
1458
-        // $this->_help_tour = apply_filters('FHEE__EE_Admin_Page___add_help_tour___help_tour', $this->_help_tour);
1459
-    }
1460
-
1461
-
1462
-    /**
1463
-     * This simply sets up any qtips that have been defined in the page config
1464
-     *
1465
-     * @return void
1466
-     */
1467
-    protected function _add_qtips()
1468
-    {
1469
-        if (isset($this->_route_config['qtips'])) {
1470
-            $qtips = (array) $this->_route_config['qtips'];
1471
-            // load qtip loader
1472
-            $path = [
1473
-                $this->_get_dir() . '/qtips/',
1474
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1475
-            ];
1476
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1477
-        }
1478
-    }
1479
-
1480
-
1481
-    /**
1482
-     * _set_nav_tabs
1483
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1484
-     * wish to add additional tabs or modify accordingly.
1485
-     *
1486
-     * @return void
1487
-     * @throws InvalidArgumentException
1488
-     * @throws InvalidInterfaceException
1489
-     * @throws InvalidDataTypeException
1490
-     */
1491
-    protected function _set_nav_tabs()
1492
-    {
1493
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1494
-        $i = 0;
1495
-        foreach ($this->_page_config as $slug => $config) {
1496
-            if (! is_array($config) || empty($config['nav'])) {
1497
-                continue;
1498
-            }
1499
-            // no nav tab for this config
1500
-            // check for persistent flag
1501
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1502
-                // nav tab is only to appear when route requested.
1503
-                continue;
1504
-            }
1505
-            if (! $this->check_user_access($slug, true)) {
1506
-                // no nav tab because current user does not have access.
1507
-                continue;
1508
-            }
1509
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1510
-            $this->_nav_tabs[ $slug ] = [
1511
-                'url'       => isset($config['nav']['url'])
1512
-                    ? $config['nav']['url']
1513
-                    : self::add_query_args_and_nonce(
1514
-                        ['action' => $slug],
1515
-                        $this->_admin_base_url
1516
-                    ),
1517
-                'link_text' => isset($config['nav']['label'])
1518
-                    ? $config['nav']['label']
1519
-                    : ucwords(
1520
-                        str_replace('_', ' ', $slug)
1521
-                    ),
1522
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1523
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1524
-            ];
1525
-            $i++;
1526
-        }
1527
-        // if $this->_nav_tabs is empty then lets set the default
1528
-        if (empty($this->_nav_tabs)) {
1529
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1530
-                'url'       => $this->_admin_base_url,
1531
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1532
-                'css_class' => 'nav-tab-active',
1533
-                'order'     => 10,
1534
-            ];
1535
-        }
1536
-        // now let's sort the tabs according to order
1537
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1538
-    }
1539
-
1540
-
1541
-    /**
1542
-     * _set_current_labels
1543
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1544
-     * property array
1545
-     *
1546
-     * @return void
1547
-     */
1548
-    private function _set_current_labels()
1549
-    {
1550
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1551
-            foreach ($this->_route_config['labels'] as $label => $text) {
1552
-                if (is_array($text)) {
1553
-                    foreach ($text as $sublabel => $subtext) {
1554
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1555
-                    }
1556
-                } else {
1557
-                    $this->_labels[ $label ] = $text;
1558
-                }
1559
-            }
1560
-        }
1561
-    }
1562
-
1563
-
1564
-    /**
1565
-     *        verifies user access for this admin page
1566
-     *
1567
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1568
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1569
-     *                               return false if verify fail.
1570
-     * @return bool
1571
-     * @throws InvalidArgumentException
1572
-     * @throws InvalidDataTypeException
1573
-     * @throws InvalidInterfaceException
1574
-     */
1575
-    public function check_user_access($route_to_check = '', $verify_only = false)
1576
-    {
1577
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1578
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1579
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1580
-                          && is_array(
1581
-                              $this->_page_routes[ $route_to_check ]
1582
-                          )
1583
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1584
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1585
-        if (empty($capability) && empty($route_to_check)) {
1586
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1587
-                : $this->_route['capability'];
1588
-        } else {
1589
-            $capability = empty($capability) ? 'manage_options' : $capability;
1590
-        }
1591
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1592
-        if (
1593
-            ! $this->request->isAjax()
1594
-            && (
1595
-                ! function_exists('is_admin')
1596
-                || ! EE_Registry::instance()->CAP->current_user_can(
1597
-                    $capability,
1598
-                    $this->page_slug
1599
-                    . '_'
1600
-                    . $route_to_check,
1601
-                    $id
1602
-                )
1603
-            )
1604
-        ) {
1605
-            if ($verify_only) {
1606
-                return false;
1607
-            }
1608
-            if (is_user_logged_in()) {
1609
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1610
-            } else {
1611
-                return false;
1612
-            }
1613
-        }
1614
-        return true;
1615
-    }
1616
-
1617
-
1618
-    /**
1619
-     * admin_init_global
1620
-     * This runs all the code that we want executed within the WP admin_init hook.
1621
-     * This method executes for ALL EE Admin pages.
1622
-     *
1623
-     * @return void
1624
-     */
1625
-    public function admin_init_global()
1626
-    {
1627
-    }
1628
-
1629
-
1630
-    /**
1631
-     * wp_loaded_global
1632
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1633
-     * EE_Admin page and will execute on every EE Admin Page load
1634
-     *
1635
-     * @return void
1636
-     */
1637
-    public function wp_loaded()
1638
-    {
1639
-    }
1640
-
1641
-
1642
-    /**
1643
-     * admin_notices
1644
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1645
-     * ALL EE_Admin pages.
1646
-     *
1647
-     * @return void
1648
-     */
1649
-    public function admin_notices_global()
1650
-    {
1651
-        $this->_display_no_javascript_warning();
1652
-        $this->_display_espresso_notices();
1653
-    }
1654
-
1655
-
1656
-    public function network_admin_notices_global()
1657
-    {
1658
-        $this->_display_no_javascript_warning();
1659
-        $this->_display_espresso_notices();
1660
-    }
1661
-
1662
-
1663
-    /**
1664
-     * admin_footer_scripts_global
1665
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1666
-     * will apply on ALL EE_Admin pages.
1667
-     *
1668
-     * @return void
1669
-     */
1670
-    public function admin_footer_scripts_global()
1671
-    {
1672
-        $this->_add_admin_page_ajax_loading_img();
1673
-        $this->_add_admin_page_overlay();
1674
-        // if metaboxes are present we need to add the nonce field
1675
-        if (
1676
-            isset($this->_route_config['metaboxes'])
1677
-            || isset($this->_route_config['list_table'])
1678
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1679
-        ) {
1680
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1681
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1682
-        }
1683
-    }
1684
-
1685
-
1686
-    /**
1687
-     * admin_footer_global
1688
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1689
-     * ALL EE_Admin Pages.
1690
-     *
1691
-     * @return void
1692
-     */
1693
-    public function admin_footer_global()
1694
-    {
1695
-        // dialog container for dialog helper
1696
-        echo '
1044
+				(
1045
+					(
1046
+						method_exists($class, $method)
1047
+						&& call_user_func_array([$class, $method], $args) === false
1048
+					)
1049
+					&& (
1050
+						// is it a standalone function that doesn't work?
1051
+						function_exists($method)
1052
+						&& call_user_func_array(
1053
+							$func,
1054
+							array_merge(['admin_page_object' => $this], $args)
1055
+						) === false
1056
+					)
1057
+				)
1058
+				|| (
1059
+					// is it neither a class method NOR a standalone function?
1060
+					! method_exists($class, $method)
1061
+					&& ! function_exists($method)
1062
+				)
1063
+			) {
1064
+				// user error msg
1065
+				$error_msg = esc_html__(
1066
+					'An error occurred. The  requested page route could not be found.',
1067
+					'event_espresso'
1068
+				);
1069
+				// developer error msg
1070
+				$error_msg .= '||';
1071
+				$error_msg .= sprintf(
1072
+					esc_html__(
1073
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1074
+						'event_espresso'
1075
+					),
1076
+					$method
1077
+				);
1078
+			}
1079
+			if (! empty($error_msg)) {
1080
+				throw new EE_Error($error_msg);
1081
+			}
1082
+		}
1083
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1084
+		// then we need to reset the routing properties to the new route.
1085
+		// now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1086
+		if (
1087
+			$this->_is_UI_request === false
1088
+			&& is_array($this->_route)
1089
+			&& ! empty($this->_route['headers_sent_route'])
1090
+		) {
1091
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1092
+		}
1093
+	}
1094
+
1095
+
1096
+	/**
1097
+	 * This method just allows the resetting of page properties in the case where a no headers
1098
+	 * route redirects to a headers route in its route config.
1099
+	 *
1100
+	 * @param string $new_route New (non header) route to redirect to.
1101
+	 * @return   void
1102
+	 * @throws ReflectionException
1103
+	 * @throws InvalidArgumentException
1104
+	 * @throws InvalidInterfaceException
1105
+	 * @throws InvalidDataTypeException
1106
+	 * @throws EE_Error
1107
+	 * @since   4.3.0
1108
+	 */
1109
+	protected function _reset_routing_properties($new_route)
1110
+	{
1111
+		$this->_is_UI_request = true;
1112
+		// now we set the current route to whatever the headers_sent_route is set at
1113
+		$this->request->setRequestParam('action', $new_route);
1114
+		// rerun page setup
1115
+		$this->_page_setup();
1116
+	}
1117
+
1118
+
1119
+	/**
1120
+	 * _add_query_arg
1121
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1122
+	 *(internally just uses EEH_URL's function with the same name)
1123
+	 *
1124
+	 * @param array  $args
1125
+	 * @param string $url
1126
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1127
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1128
+	 *                                        Example usage: If the current page is:
1129
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1130
+	 *                                        &action=default&event_id=20&month_range=March%202015
1131
+	 *                                        &_wpnonce=5467821
1132
+	 *                                        and you call:
1133
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1134
+	 *                                        array(
1135
+	 *                                        'action' => 'resend_something',
1136
+	 *                                        'page=>espresso_registrations'
1137
+	 *                                        ),
1138
+	 *                                        $some_url,
1139
+	 *                                        true
1140
+	 *                                        );
1141
+	 *                                        It will produce a url in this structure:
1142
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1143
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1144
+	 *                                        month_range]=March%202015
1145
+	 * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1146
+	 * @return string
1147
+	 */
1148
+	public static function add_query_args_and_nonce(
1149
+		$args = [],
1150
+		$url = false,
1151
+		$sticky = false,
1152
+		$exclude_nonce = false
1153
+	) {
1154
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1155
+		if ($sticky) {
1156
+			/** @var RequestInterface $request */
1157
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1158
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer']);
1159
+			foreach ($request->requestParams() as $key => $value) {
1160
+				// do not add nonces
1161
+				if (strpos($key, 'nonce') !== false) {
1162
+					continue;
1163
+				}
1164
+				$args[ 'wp_referer[' . $key . ']' ] = $value;
1165
+			}
1166
+		}
1167
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1168
+	}
1169
+
1170
+
1171
+	/**
1172
+	 * This returns a generated link that will load the related help tab.
1173
+	 *
1174
+	 * @param string $help_tab_id the id for the connected help tab
1175
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1176
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1177
+	 * @return string              generated link
1178
+	 * @uses EEH_Template::get_help_tab_link()
1179
+	 */
1180
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1181
+	{
1182
+		return EEH_Template::get_help_tab_link(
1183
+			$help_tab_id,
1184
+			$this->page_slug,
1185
+			$this->_req_action,
1186
+			$icon_style,
1187
+			$help_text
1188
+		);
1189
+	}
1190
+
1191
+
1192
+	/**
1193
+	 * _add_help_tabs
1194
+	 * Note child classes define their help tabs within the page_config array.
1195
+	 *
1196
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1197
+	 * @return void
1198
+	 * @throws DomainException
1199
+	 * @throws EE_Error
1200
+	 */
1201
+	protected function _add_help_tabs()
1202
+	{
1203
+		$tour_buttons = '';
1204
+		if (isset($this->_page_config[ $this->_req_action ])) {
1205
+			$config = $this->_page_config[ $this->_req_action ];
1206
+			// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1207
+			// is there a help tour for the current route?  if there is let's setup the tour buttons
1208
+			// if (isset($this->_help_tour[ $this->_req_action ])) {
1209
+			//     $tb = array();
1210
+			//     $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1211
+			//     foreach ($this->_help_tour['tours'] as $tour) {
1212
+			//         // if this is the end tour then we don't need to setup a button
1213
+			//         if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1214
+			//             continue;
1215
+			//         }
1216
+			//         $tb[] = '<button id="trigger-tour-'
1217
+			//                 . $tour->get_slug()
1218
+			//                 . '" class="button-primary trigger-ee-help-tour">'
1219
+			//                 . $tour->get_label()
1220
+			//                 . '</button>';
1221
+			//     }
1222
+			//     $tour_buttons .= implode('<br />', $tb);
1223
+			//     $tour_buttons .= '</div></div>';
1224
+			// }
1225
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1226
+			if (is_array($config) && isset($config['help_sidebar'])) {
1227
+				// check that the callback given is valid
1228
+				if (! method_exists($this, $config['help_sidebar'])) {
1229
+					throw new EE_Error(
1230
+						sprintf(
1231
+							esc_html__(
1232
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1233
+								'event_espresso'
1234
+							),
1235
+							$config['help_sidebar'],
1236
+							get_class($this)
1237
+						)
1238
+					);
1239
+				}
1240
+				$content = apply_filters(
1241
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1242
+					$this->{$config['help_sidebar']}()
1243
+				);
1244
+				$content .= $tour_buttons; // add help tour buttons.
1245
+				// do we have any help tours setup?  Cause if we do we want to add the buttons
1246
+				$this->_current_screen->set_help_sidebar($content);
1247
+			}
1248
+			// if we DON'T have config help sidebar and there ARE tour buttons then we'll just add the tour buttons to the sidebar.
1249
+			if (! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1250
+				$this->_current_screen->set_help_sidebar($tour_buttons);
1251
+			}
1252
+			// handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1253
+			if (! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1254
+				$_ht['id']      = $this->page_slug;
1255
+				$_ht['title']   = esc_html__('Help Tours', 'event_espresso');
1256
+				$_ht['content'] = '<p>'
1257
+								  . esc_html__(
1258
+									  'The buttons to the right allow you to start/restart any help tours available for this page',
1259
+									  'event_espresso'
1260
+								  ) . '</p>';
1261
+				$this->_current_screen->add_help_tab($_ht);
1262
+			}
1263
+			if (! isset($config['help_tabs'])) {
1264
+				return;
1265
+			} //no help tabs for this route
1266
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1267
+				// we're here so there ARE help tabs!
1268
+				// make sure we've got what we need
1269
+				if (! isset($cfg['title'])) {
1270
+					throw new EE_Error(
1271
+						esc_html__(
1272
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1273
+							'event_espresso'
1274
+						)
1275
+					);
1276
+				}
1277
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1278
+					throw new EE_Error(
1279
+						esc_html__(
1280
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1281
+							'event_espresso'
1282
+						)
1283
+					);
1284
+				}
1285
+				// first priority goes to content.
1286
+				if (! empty($cfg['content'])) {
1287
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1288
+					// second priority goes to filename
1289
+				} elseif (! empty($cfg['filename'])) {
1290
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1291
+					// it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1292
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1293
+															 . basename($this->_get_dir())
1294
+															 . '/help_tabs/'
1295
+															 . $cfg['filename']
1296
+															 . '.help_tab.php' : $file_path;
1297
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1298
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1299
+						EE_Error::add_error(
1300
+							sprintf(
1301
+								esc_html__(
1302
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1303
+									'event_espresso'
1304
+								),
1305
+								$tab_id,
1306
+								key($config),
1307
+								$file_path
1308
+							),
1309
+							__FILE__,
1310
+							__FUNCTION__,
1311
+							__LINE__
1312
+						);
1313
+						return;
1314
+					}
1315
+					$template_args['admin_page_obj'] = $this;
1316
+					$content                         = EEH_Template::display_template(
1317
+						$file_path,
1318
+						$template_args,
1319
+						true
1320
+					);
1321
+				} else {
1322
+					$content = '';
1323
+				}
1324
+				// check if callback is valid
1325
+				if (
1326
+					empty($content)
1327
+					&& (
1328
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1329
+					)
1330
+				) {
1331
+					EE_Error::add_error(
1332
+						sprintf(
1333
+							esc_html__(
1334
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1335
+								'event_espresso'
1336
+							),
1337
+							$cfg['title']
1338
+						),
1339
+						__FILE__,
1340
+						__FUNCTION__,
1341
+						__LINE__
1342
+					);
1343
+					return;
1344
+				}
1345
+				// setup config array for help tab method
1346
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1347
+				$_ht = [
1348
+					'id'       => $id,
1349
+					'title'    => $cfg['title'],
1350
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1351
+					'content'  => $content,
1352
+				];
1353
+				$this->_current_screen->add_help_tab($_ht);
1354
+			}
1355
+		}
1356
+	}
1357
+
1358
+
1359
+	/**
1360
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1361
+	 * an array with properties for setting up usage of the joyride plugin
1362
+	 *
1363
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1364
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1365
+	 *         _set_page_config() comments
1366
+	 * @return void
1367
+	 * @throws InvalidArgumentException
1368
+	 * @throws InvalidDataTypeException
1369
+	 * @throws InvalidInterfaceException
1370
+	 */
1371
+	protected function _add_help_tour()
1372
+	{
1373
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1374
+		// $tours = array();
1375
+		// $this->_help_tour = array();
1376
+		// // exit early if help tours are turned off globally
1377
+		// if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1378
+		//     || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1379
+		// ) {
1380
+		//     return;
1381
+		// }
1382
+		// // loop through _page_config to find any help_tour defined
1383
+		// foreach ($this->_page_config as $route => $config) {
1384
+		//     // we're only going to set things up for this route
1385
+		//     if ($route !== $this->_req_action) {
1386
+		//         continue;
1387
+		//     }
1388
+		//     if (isset($config['help_tour'])) {
1389
+		//         foreach ($config['help_tour'] as $tour) {
1390
+		//             $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1391
+		//             // let's see if we can get that file...
1392
+		//             // if not its possible this is a decaf route not set in caffeinated
1393
+		//             // so lets try and get the caffeinated equivalent
1394
+		//             $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1395
+		//                                                      . basename($this->_get_dir())
1396
+		//                                                      . '/help_tours/'
1397
+		//                                                      . $tour
1398
+		//                                                      . '.class.php' : $file_path;
1399
+		//             // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1400
+		//             if (! is_readable($file_path)) {
1401
+		//                 EE_Error::add_error(
1402
+		//                     sprintf(
1403
+		//                         esc_html__(
1404
+		//                             'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1405
+		//                             'event_espresso'
1406
+		//                         ),
1407
+		//                         $file_path,
1408
+		//                         $tour
1409
+		//                     ),
1410
+		//                     __FILE__,
1411
+		//                     __FUNCTION__,
1412
+		//                     __LINE__
1413
+		//                 );
1414
+		//                 return;
1415
+		//             }
1416
+		//             require_once $file_path;
1417
+		//             if (! class_exists($tour)) {
1418
+		//                 $error_msg[] = sprintf(
1419
+		//                     esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1420
+		//                     $tour
1421
+		//                 );
1422
+		//                 $error_msg[] = $error_msg[0] . "\r\n"
1423
+		//                                . sprintf(
1424
+		//                                    esc_html__(
1425
+		//                                        'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1426
+		//                                        'event_espresso'
1427
+		//                                    ),
1428
+		//                                    $tour,
1429
+		//                                    '<br />',
1430
+		//                                    $tour,
1431
+		//                                    $this->_req_action,
1432
+		//                                    get_class($this)
1433
+		//                                );
1434
+		//                 throw new EE_Error(implode('||', $error_msg));
1435
+		//             }
1436
+		//             $tour_obj = new $tour($this->_is_caf);
1437
+		//             $tours[] = $tour_obj;
1438
+		//             $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1439
+		//         }
1440
+		//         // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1441
+		//         $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1442
+		//         $tours[] = $end_stop_tour;
1443
+		//         $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1444
+		//     }
1445
+		// }
1446
+		//
1447
+		// if (! empty($tours)) {
1448
+		//     $this->_help_tour['tours'] = $tours;
1449
+		// }
1450
+		// // that's it!  Now that the $_help_tours property is set (or not)
1451
+		// // the scripts and html should be taken care of automatically.
1452
+		//
1453
+		// /**
1454
+		//  * Allow extending the help tours variable.
1455
+		//  *
1456
+		//  * @param Array $_help_tour The array containing all help tour information to be displayed.
1457
+		//  */
1458
+		// $this->_help_tour = apply_filters('FHEE__EE_Admin_Page___add_help_tour___help_tour', $this->_help_tour);
1459
+	}
1460
+
1461
+
1462
+	/**
1463
+	 * This simply sets up any qtips that have been defined in the page config
1464
+	 *
1465
+	 * @return void
1466
+	 */
1467
+	protected function _add_qtips()
1468
+	{
1469
+		if (isset($this->_route_config['qtips'])) {
1470
+			$qtips = (array) $this->_route_config['qtips'];
1471
+			// load qtip loader
1472
+			$path = [
1473
+				$this->_get_dir() . '/qtips/',
1474
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1475
+			];
1476
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1477
+		}
1478
+	}
1479
+
1480
+
1481
+	/**
1482
+	 * _set_nav_tabs
1483
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1484
+	 * wish to add additional tabs or modify accordingly.
1485
+	 *
1486
+	 * @return void
1487
+	 * @throws InvalidArgumentException
1488
+	 * @throws InvalidInterfaceException
1489
+	 * @throws InvalidDataTypeException
1490
+	 */
1491
+	protected function _set_nav_tabs()
1492
+	{
1493
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1494
+		$i = 0;
1495
+		foreach ($this->_page_config as $slug => $config) {
1496
+			if (! is_array($config) || empty($config['nav'])) {
1497
+				continue;
1498
+			}
1499
+			// no nav tab for this config
1500
+			// check for persistent flag
1501
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1502
+				// nav tab is only to appear when route requested.
1503
+				continue;
1504
+			}
1505
+			if (! $this->check_user_access($slug, true)) {
1506
+				// no nav tab because current user does not have access.
1507
+				continue;
1508
+			}
1509
+			$css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1510
+			$this->_nav_tabs[ $slug ] = [
1511
+				'url'       => isset($config['nav']['url'])
1512
+					? $config['nav']['url']
1513
+					: self::add_query_args_and_nonce(
1514
+						['action' => $slug],
1515
+						$this->_admin_base_url
1516
+					),
1517
+				'link_text' => isset($config['nav']['label'])
1518
+					? $config['nav']['label']
1519
+					: ucwords(
1520
+						str_replace('_', ' ', $slug)
1521
+					),
1522
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1523
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1524
+			];
1525
+			$i++;
1526
+		}
1527
+		// if $this->_nav_tabs is empty then lets set the default
1528
+		if (empty($this->_nav_tabs)) {
1529
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1530
+				'url'       => $this->_admin_base_url,
1531
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1532
+				'css_class' => 'nav-tab-active',
1533
+				'order'     => 10,
1534
+			];
1535
+		}
1536
+		// now let's sort the tabs according to order
1537
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1538
+	}
1539
+
1540
+
1541
+	/**
1542
+	 * _set_current_labels
1543
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1544
+	 * property array
1545
+	 *
1546
+	 * @return void
1547
+	 */
1548
+	private function _set_current_labels()
1549
+	{
1550
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1551
+			foreach ($this->_route_config['labels'] as $label => $text) {
1552
+				if (is_array($text)) {
1553
+					foreach ($text as $sublabel => $subtext) {
1554
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1555
+					}
1556
+				} else {
1557
+					$this->_labels[ $label ] = $text;
1558
+				}
1559
+			}
1560
+		}
1561
+	}
1562
+
1563
+
1564
+	/**
1565
+	 *        verifies user access for this admin page
1566
+	 *
1567
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1568
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1569
+	 *                               return false if verify fail.
1570
+	 * @return bool
1571
+	 * @throws InvalidArgumentException
1572
+	 * @throws InvalidDataTypeException
1573
+	 * @throws InvalidInterfaceException
1574
+	 */
1575
+	public function check_user_access($route_to_check = '', $verify_only = false)
1576
+	{
1577
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1578
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1579
+		$capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1580
+						  && is_array(
1581
+							  $this->_page_routes[ $route_to_check ]
1582
+						  )
1583
+						  && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1584
+			? $this->_page_routes[ $route_to_check ]['capability'] : null;
1585
+		if (empty($capability) && empty($route_to_check)) {
1586
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1587
+				: $this->_route['capability'];
1588
+		} else {
1589
+			$capability = empty($capability) ? 'manage_options' : $capability;
1590
+		}
1591
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1592
+		if (
1593
+			! $this->request->isAjax()
1594
+			&& (
1595
+				! function_exists('is_admin')
1596
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1597
+					$capability,
1598
+					$this->page_slug
1599
+					. '_'
1600
+					. $route_to_check,
1601
+					$id
1602
+				)
1603
+			)
1604
+		) {
1605
+			if ($verify_only) {
1606
+				return false;
1607
+			}
1608
+			if (is_user_logged_in()) {
1609
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1610
+			} else {
1611
+				return false;
1612
+			}
1613
+		}
1614
+		return true;
1615
+	}
1616
+
1617
+
1618
+	/**
1619
+	 * admin_init_global
1620
+	 * This runs all the code that we want executed within the WP admin_init hook.
1621
+	 * This method executes for ALL EE Admin pages.
1622
+	 *
1623
+	 * @return void
1624
+	 */
1625
+	public function admin_init_global()
1626
+	{
1627
+	}
1628
+
1629
+
1630
+	/**
1631
+	 * wp_loaded_global
1632
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1633
+	 * EE_Admin page and will execute on every EE Admin Page load
1634
+	 *
1635
+	 * @return void
1636
+	 */
1637
+	public function wp_loaded()
1638
+	{
1639
+	}
1640
+
1641
+
1642
+	/**
1643
+	 * admin_notices
1644
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1645
+	 * ALL EE_Admin pages.
1646
+	 *
1647
+	 * @return void
1648
+	 */
1649
+	public function admin_notices_global()
1650
+	{
1651
+		$this->_display_no_javascript_warning();
1652
+		$this->_display_espresso_notices();
1653
+	}
1654
+
1655
+
1656
+	public function network_admin_notices_global()
1657
+	{
1658
+		$this->_display_no_javascript_warning();
1659
+		$this->_display_espresso_notices();
1660
+	}
1661
+
1662
+
1663
+	/**
1664
+	 * admin_footer_scripts_global
1665
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1666
+	 * will apply on ALL EE_Admin pages.
1667
+	 *
1668
+	 * @return void
1669
+	 */
1670
+	public function admin_footer_scripts_global()
1671
+	{
1672
+		$this->_add_admin_page_ajax_loading_img();
1673
+		$this->_add_admin_page_overlay();
1674
+		// if metaboxes are present we need to add the nonce field
1675
+		if (
1676
+			isset($this->_route_config['metaboxes'])
1677
+			|| isset($this->_route_config['list_table'])
1678
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1679
+		) {
1680
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1681
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1682
+		}
1683
+	}
1684
+
1685
+
1686
+	/**
1687
+	 * admin_footer_global
1688
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particular method will apply on
1689
+	 * ALL EE_Admin Pages.
1690
+	 *
1691
+	 * @return void
1692
+	 */
1693
+	public function admin_footer_global()
1694
+	{
1695
+		// dialog container for dialog helper
1696
+		echo '
1697 1697
         <div class="ee-admin-dialog-container auto-hide hidden">
1698 1698
             <div class="ee-notices"></div>
1699 1699
             <div class="ee-admin-dialog-container-inner-content"></div>
1700 1700
         </div>
1701 1701
         ';
1702 1702
 
1703
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1704
-        // help tour stuff?
1705
-        // if (isset($this->_help_tour[ $this->_req_action ])) {
1706
-        //     echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1707
-        // }
1708
-        // current set timezone for timezone js
1709
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1710
-    }
1711
-
1712
-
1713
-    /**
1714
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1715
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1716
-     * help popups then in your templates or your content you set "triggers" for the content using the
1717
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1718
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1719
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1720
-     * for the
1721
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1722
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1723
-     *    'help_trigger_id' => array(
1724
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1725
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1726
-     *    )
1727
-     * );
1728
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1729
-     *
1730
-     * @param array $help_array
1731
-     * @param bool  $display
1732
-     * @return string content
1733
-     * @throws DomainException
1734
-     * @throws EE_Error
1735
-     */
1736
-    protected function _set_help_popup_content($help_array = [], $display = false)
1737
-    {
1738
-        $content    = '';
1739
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1740
-        // loop through the array and setup content
1741
-        foreach ($help_array as $trigger => $help) {
1742
-            // make sure the array is setup properly
1743
-            if (! isset($help['title']) || ! isset($help['content'])) {
1744
-                throw new EE_Error(
1745
-                    esc_html__(
1746
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1747
-                        'event_espresso'
1748
-                    )
1749
-                );
1750
-            }
1751
-            // we're good so let'd setup the template vars and then assign parsed template content to our content.
1752
-            $template_args = [
1753
-                'help_popup_id'      => $trigger,
1754
-                'help_popup_title'   => $help['title'],
1755
-                'help_popup_content' => $help['content'],
1756
-            ];
1757
-            $content       .= EEH_Template::display_template(
1758
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1759
-                $template_args,
1760
-                true
1761
-            );
1762
-        }
1763
-        if ($display) {
1764
-            echo $content; // already escaped
1765
-            return '';
1766
-        }
1767
-        return $content;
1768
-    }
1769
-
1770
-
1771
-    /**
1772
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1773
-     *
1774
-     * @return array properly formatted array for help popup content
1775
-     * @throws EE_Error
1776
-     */
1777
-    private function _get_help_content()
1778
-    {
1779
-        // what is the method we're looking for?
1780
-        $method_name = '_help_popup_content_' . $this->_req_action;
1781
-        // if method doesn't exist let's get out.
1782
-        if (! method_exists($this, $method_name)) {
1783
-            return [];
1784
-        }
1785
-        // k we're good to go let's retrieve the help array
1786
-        $help_array = call_user_func([$this, $method_name]);
1787
-        // make sure we've got an array!
1788
-        if (! is_array($help_array)) {
1789
-            throw new EE_Error(
1790
-                esc_html__(
1791
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1792
-                    'event_espresso'
1793
-                )
1794
-            );
1795
-        }
1796
-        return $help_array;
1797
-    }
1798
-
1799
-
1800
-    /**
1801
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1802
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1803
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1804
-     *
1805
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1806
-     * @param boolean $display    if false then we return the trigger string
1807
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1808
-     * @return string
1809
-     * @throws DomainException
1810
-     * @throws EE_Error
1811
-     */
1812
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1813
-    {
1814
-        if ($this->request->isAjax()) {
1815
-            return '';
1816
-        }
1817
-        // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1818
-        $help_array   = $this->_get_help_content();
1819
-        $help_content = '';
1820
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1821
-            $help_array[ $trigger_id ] = [
1822
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1823
-                'content' => esc_html__(
1824
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1825
-                    'event_espresso'
1826
-                ),
1827
-            ];
1828
-            $help_content              = $this->_set_help_popup_content($help_array, false);
1829
-        }
1830
-        // let's setup the trigger
1831
-        $content = '<a class="ee-dialog" href="?height='
1832
-                   . esc_attr($dimensions[0])
1833
-                   . '&width='
1834
-                   . esc_attr($dimensions[1])
1835
-                   . '&inlineId='
1836
-                   . esc_attr($trigger_id)
1837
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1838
-        $content .= $help_content;
1839
-        if ($display) {
1840
-            echo $content; // already escaped
1841
-            return '';
1842
-        }
1843
-        return $content;
1844
-    }
1845
-
1846
-
1847
-    /**
1848
-     * _add_global_screen_options
1849
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1850
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1851
-     *
1852
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1853
-     *         see also WP_Screen object documents...
1854
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1855
-     * @abstract
1856
-     * @return void
1857
-     */
1858
-    private function _add_global_screen_options()
1859
-    {
1860
-    }
1861
-
1862
-
1863
-    /**
1864
-     * _add_global_feature_pointers
1865
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1866
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1867
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1868
-     *
1869
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1870
-     *         extended) also see:
1871
-     * @link   http://eamann.com/tech/wordpress-portland/
1872
-     * @abstract
1873
-     * @return void
1874
-     */
1875
-    private function _add_global_feature_pointers()
1876
-    {
1877
-    }
1878
-
1879
-
1880
-    /**
1881
-     * load_global_scripts_styles
1882
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1883
-     *
1884
-     * @return void
1885
-     */
1886
-    public function load_global_scripts_styles()
1887
-    {
1888
-        /** STYLES **/
1889
-        // add debugging styles
1890
-        if (WP_DEBUG) {
1891
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1892
-        }
1893
-        // register all styles
1894
-        wp_register_style(
1895
-            'espresso-ui-theme',
1896
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1897
-            [],
1898
-            EVENT_ESPRESSO_VERSION
1899
-        );
1900
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1901
-        // helpers styles
1902
-        wp_register_style(
1903
-            'ee-text-links',
1904
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1905
-            [],
1906
-            EVENT_ESPRESSO_VERSION
1907
-        );
1908
-        /** SCRIPTS **/
1909
-        // register all scripts
1910
-        wp_register_script(
1911
-            'ee-dialog',
1912
-            EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1913
-            ['jquery', 'jquery-ui-draggable'],
1914
-            EVENT_ESPRESSO_VERSION,
1915
-            true
1916
-        );
1917
-        wp_register_script(
1918
-            'ee_admin_js',
1919
-            EE_ADMIN_URL . 'assets/ee-admin-page.js',
1920
-            ['espresso_core', 'ee-parse-uri', 'ee-dialog'],
1921
-            EVENT_ESPRESSO_VERSION,
1922
-            true
1923
-        );
1924
-        wp_register_script(
1925
-            'jquery-ui-timepicker-addon',
1926
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1927
-            ['jquery-ui-datepicker', 'jquery-ui-slider'],
1928
-            EVENT_ESPRESSO_VERSION,
1929
-            true
1930
-        );
1931
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1932
-        // if (EE_Registry::instance()->CFG->admin->help_tour_activation) {
1933
-        //     add_filter('FHEE_load_joyride', '__return_true');
1934
-        // }
1935
-        // script for sorting tables
1936
-        wp_register_script(
1937
-            'espresso_ajax_table_sorting',
1938
-            EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1939
-            ['ee_admin_js', 'jquery-ui-sortable'],
1940
-            EVENT_ESPRESSO_VERSION,
1941
-            true
1942
-        );
1943
-        // script for parsing uri's
1944
-        wp_register_script(
1945
-            'ee-parse-uri',
1946
-            EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1947
-            [],
1948
-            EVENT_ESPRESSO_VERSION,
1949
-            true
1950
-        );
1951
-        // and parsing associative serialized form elements
1952
-        wp_register_script(
1953
-            'ee-serialize-full-array',
1954
-            EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1955
-            ['jquery'],
1956
-            EVENT_ESPRESSO_VERSION,
1957
-            true
1958
-        );
1959
-        // helpers scripts
1960
-        wp_register_script(
1961
-            'ee-text-links',
1962
-            EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1963
-            ['jquery'],
1964
-            EVENT_ESPRESSO_VERSION,
1965
-            true
1966
-        );
1967
-        wp_register_script(
1968
-            'ee-moment-core',
1969
-            EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1970
-            [],
1971
-            EVENT_ESPRESSO_VERSION,
1972
-            true
1973
-        );
1974
-        wp_register_script(
1975
-            'ee-moment',
1976
-            EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1977
-            ['ee-moment-core'],
1978
-            EVENT_ESPRESSO_VERSION,
1979
-            true
1980
-        );
1981
-        wp_register_script(
1982
-            'ee-datepicker',
1983
-            EE_ADMIN_URL . 'assets/ee-datepicker.js',
1984
-            ['jquery-ui-timepicker-addon', 'ee-moment'],
1985
-            EVENT_ESPRESSO_VERSION,
1986
-            true
1987
-        );
1988
-        // google charts
1989
-        wp_register_script(
1990
-            'google-charts',
1991
-            'https://www.gstatic.com/charts/loader.js',
1992
-            [],
1993
-            EVENT_ESPRESSO_VERSION,
1994
-            false
1995
-        );
1996
-        // ENQUEUE ALL BASICS BY DEFAULT
1997
-        wp_enqueue_style('ee-admin-css');
1998
-        wp_enqueue_script('ee_admin_js');
1999
-        wp_enqueue_script('ee-accounting');
2000
-        wp_enqueue_script('jquery-validate');
2001
-        // taking care of metaboxes
2002
-        if (
2003
-            empty($this->_cpt_route)
2004
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
2005
-        ) {
2006
-            wp_enqueue_script('dashboard');
2007
-        }
2008
-        // LOCALIZED DATA
2009
-        // localize script for ajax lazy loading
2010
-        $lazy_loader_container_ids = apply_filters(
2011
-            'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2012
-            ['espresso_news_post_box_content']
2013
-        );
2014
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
2015
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
2016
-        // /**
2017
-        //  * help tour stuff
2018
-        //  */
2019
-        // if (! empty($this->_help_tour)) {
2020
-        //     // register the js for kicking things off
2021
-        //     wp_enqueue_script(
2022
-        //         'ee-help-tour',
2023
-        //         EE_ADMIN_URL . 'assets/ee-help-tour.js',
2024
-        //         array('jquery-joyride'),
2025
-        //         EVENT_ESPRESSO_VERSION,
2026
-        //         true
2027
-        //     );
2028
-        //     $tours = array();
2029
-        //     // setup tours for the js tour object
2030
-        //     foreach ($this->_help_tour['tours'] as $tour) {
2031
-        //         if ($tour instanceof EE_Help_Tour) {
2032
-        //             $tours[] = array(
2033
-        //                 'id'      => $tour->get_slug(),
2034
-        //                 'options' => $tour->get_options(),
2035
-        //             );
2036
-        //         }
2037
-        //     }
2038
-        //     wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2039
-        //     // admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2040
-        // }
2041
-
2042
-        add_filter(
2043
-            'admin_body_class',
2044
-            function ($classes) {
2045
-                if (strpos($classes, 'espresso-admin') === false) {
2046
-                    $classes .= ' espresso-admin';
2047
-                }
2048
-                return $classes;
2049
-            }
2050
-        );
2051
-    }
2052
-
2053
-
2054
-    /**
2055
-     *        admin_footer_scripts_eei18n_js_strings
2056
-     *
2057
-     * @return        void
2058
-     */
2059
-    public function admin_footer_scripts_eei18n_js_strings()
2060
-    {
2061
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2062
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
2063
-            __(
2064
-                'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2065
-                'event_espresso'
2066
-            )
2067
-        );
2068
-        EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
2069
-        EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
2070
-        EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
2071
-        EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
2072
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2073
-        EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
2074
-        EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
2075
-        EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
2076
-        EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
2077
-        EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
2078
-        EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
2079
-        EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
2080
-        EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
2081
-        EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
2082
-        EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
2083
-        EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
2084
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2085
-        EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
2086
-        EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
2087
-        EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
2088
-        EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
2089
-        EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
2090
-        EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
2091
-        EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
2092
-        EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
2093
-        EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
2094
-        EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
2095
-        EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
2096
-        EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
2097
-        EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
2098
-        EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
2099
-        EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
2100
-        EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
2101
-        EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
2102
-        EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
2103
-        EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
2104
-        EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
2105
-        EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
2106
-    }
2107
-
2108
-
2109
-    /**
2110
-     *        load enhanced xdebug styles for ppl with failing eyesight
2111
-     *
2112
-     * @return        void
2113
-     */
2114
-    public function add_xdebug_style()
2115
-    {
2116
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2117
-    }
2118
-
2119
-
2120
-    /************************/
2121
-    /** LIST TABLE METHODS **/
2122
-    /************************/
2123
-    /**
2124
-     * this sets up the list table if the current view requires it.
2125
-     *
2126
-     * @return void
2127
-     * @throws EE_Error
2128
-     */
2129
-    protected function _set_list_table()
2130
-    {
2131
-        // first is this a list_table view?
2132
-        if (! isset($this->_route_config['list_table'])) {
2133
-            return;
2134
-        } //not a list_table view so get out.
2135
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2136
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2137
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2138
-            // user error msg
2139
-            $error_msg = esc_html__(
2140
-                'An error occurred. The requested list table views could not be found.',
2141
-                'event_espresso'
2142
-            );
2143
-            // developer error msg
2144
-            $error_msg .= '||'
2145
-                          . sprintf(
2146
-                              esc_html__(
2147
-                                  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2148
-                                  'event_espresso'
2149
-                              ),
2150
-                              $this->_req_action,
2151
-                              $list_table_view
2152
-                          );
2153
-            throw new EE_Error($error_msg);
2154
-        }
2155
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2156
-        $this->_views = apply_filters(
2157
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2158
-            $this->_views
2159
-        );
2160
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2161
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2162
-        $this->_set_list_table_view();
2163
-        $this->_set_list_table_object();
2164
-    }
2165
-
2166
-
2167
-    /**
2168
-     * set current view for List Table
2169
-     *
2170
-     * @return void
2171
-     */
2172
-    protected function _set_list_table_view()
2173
-    {
2174
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2175
-        $status = $this->request->getRequestParam('status', null, 'key');
2176
-        $this->_view = $status && array_key_exists($status, $this->_views)
2177
-            ? $status
2178
-            : $this->_view;
2179
-    }
2180
-
2181
-
2182
-    /**
2183
-     * _set_list_table_object
2184
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2185
-     *
2186
-     * @throws InvalidInterfaceException
2187
-     * @throws InvalidArgumentException
2188
-     * @throws InvalidDataTypeException
2189
-     * @throws EE_Error
2190
-     * @throws InvalidInterfaceException
2191
-     */
2192
-    protected function _set_list_table_object()
2193
-    {
2194
-        if (isset($this->_route_config['list_table'])) {
2195
-            if (! class_exists($this->_route_config['list_table'])) {
2196
-                throw new EE_Error(
2197
-                    sprintf(
2198
-                        esc_html__(
2199
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2200
-                            'event_espresso'
2201
-                        ),
2202
-                        $this->_route_config['list_table'],
2203
-                        get_class($this)
2204
-                    )
2205
-                );
2206
-            }
2207
-            $this->_list_table_object = $this->loader->getShared(
2208
-                $this->_route_config['list_table'],
2209
-                [$this]
2210
-            );
2211
-        }
2212
-    }
2213
-
2214
-
2215
-    /**
2216
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2217
-     *
2218
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2219
-     *                                                    urls.  The array should be indexed by the view it is being
2220
-     *                                                    added to.
2221
-     * @return array
2222
-     */
2223
-    public function get_list_table_view_RLs($extra_query_args = [])
2224
-    {
2225
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2226
-        if (empty($this->_views)) {
2227
-            $this->_views = [];
2228
-        }
2229
-        // cycle thru views
2230
-        foreach ($this->_views as $key => $view) {
2231
-            $query_args = [];
2232
-            // check for current view
2233
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2234
-            $query_args['action']                        = $this->_req_action;
2235
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2236
-            $query_args['status']                        = $view['slug'];
2237
-            // merge any other arguments sent in.
2238
-            if (isset($extra_query_args[ $view['slug'] ])) {
2239
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2240
-            }
2241
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2242
-        }
2243
-        return $this->_views;
2244
-    }
2245
-
2246
-
2247
-    /**
2248
-     * _entries_per_page_dropdown
2249
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2250
-     *
2251
-     * @param int $max_entries total number of rows in the table
2252
-     * @return string
2253
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2254
-     *         WP does it.
2255
-     */
2256
-    protected function _entries_per_page_dropdown($max_entries = 0)
2257
-    {
2258
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2259
-        $values   = [10, 25, 50, 100];
2260
-        $per_page = $this->request->getRequestParam('per_page', 10, 'int');
2261
-        if ($max_entries) {
2262
-            $values[] = $max_entries;
2263
-            sort($values);
2264
-        }
2265
-        $entries_per_page_dropdown = '
1703
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1704
+		// help tour stuff?
1705
+		// if (isset($this->_help_tour[ $this->_req_action ])) {
1706
+		//     echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1707
+		// }
1708
+		// current set timezone for timezone js
1709
+		echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1710
+	}
1711
+
1712
+
1713
+	/**
1714
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1715
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1716
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1717
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1718
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1719
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1720
+	 * for the
1721
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1722
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1723
+	 *    'help_trigger_id' => array(
1724
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1725
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1726
+	 *    )
1727
+	 * );
1728
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1729
+	 *
1730
+	 * @param array $help_array
1731
+	 * @param bool  $display
1732
+	 * @return string content
1733
+	 * @throws DomainException
1734
+	 * @throws EE_Error
1735
+	 */
1736
+	protected function _set_help_popup_content($help_array = [], $display = false)
1737
+	{
1738
+		$content    = '';
1739
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1740
+		// loop through the array and setup content
1741
+		foreach ($help_array as $trigger => $help) {
1742
+			// make sure the array is setup properly
1743
+			if (! isset($help['title']) || ! isset($help['content'])) {
1744
+				throw new EE_Error(
1745
+					esc_html__(
1746
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1747
+						'event_espresso'
1748
+					)
1749
+				);
1750
+			}
1751
+			// we're good so let'd setup the template vars and then assign parsed template content to our content.
1752
+			$template_args = [
1753
+				'help_popup_id'      => $trigger,
1754
+				'help_popup_title'   => $help['title'],
1755
+				'help_popup_content' => $help['content'],
1756
+			];
1757
+			$content       .= EEH_Template::display_template(
1758
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1759
+				$template_args,
1760
+				true
1761
+			);
1762
+		}
1763
+		if ($display) {
1764
+			echo $content; // already escaped
1765
+			return '';
1766
+		}
1767
+		return $content;
1768
+	}
1769
+
1770
+
1771
+	/**
1772
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1773
+	 *
1774
+	 * @return array properly formatted array for help popup content
1775
+	 * @throws EE_Error
1776
+	 */
1777
+	private function _get_help_content()
1778
+	{
1779
+		// what is the method we're looking for?
1780
+		$method_name = '_help_popup_content_' . $this->_req_action;
1781
+		// if method doesn't exist let's get out.
1782
+		if (! method_exists($this, $method_name)) {
1783
+			return [];
1784
+		}
1785
+		// k we're good to go let's retrieve the help array
1786
+		$help_array = call_user_func([$this, $method_name]);
1787
+		// make sure we've got an array!
1788
+		if (! is_array($help_array)) {
1789
+			throw new EE_Error(
1790
+				esc_html__(
1791
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1792
+					'event_espresso'
1793
+				)
1794
+			);
1795
+		}
1796
+		return $help_array;
1797
+	}
1798
+
1799
+
1800
+	/**
1801
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1802
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1803
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1804
+	 *
1805
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1806
+	 * @param boolean $display    if false then we return the trigger string
1807
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1808
+	 * @return string
1809
+	 * @throws DomainException
1810
+	 * @throws EE_Error
1811
+	 */
1812
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1813
+	{
1814
+		if ($this->request->isAjax()) {
1815
+			return '';
1816
+		}
1817
+		// let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1818
+		$help_array   = $this->_get_help_content();
1819
+		$help_content = '';
1820
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1821
+			$help_array[ $trigger_id ] = [
1822
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1823
+				'content' => esc_html__(
1824
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1825
+					'event_espresso'
1826
+				),
1827
+			];
1828
+			$help_content              = $this->_set_help_popup_content($help_array, false);
1829
+		}
1830
+		// let's setup the trigger
1831
+		$content = '<a class="ee-dialog" href="?height='
1832
+				   . esc_attr($dimensions[0])
1833
+				   . '&width='
1834
+				   . esc_attr($dimensions[1])
1835
+				   . '&inlineId='
1836
+				   . esc_attr($trigger_id)
1837
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1838
+		$content .= $help_content;
1839
+		if ($display) {
1840
+			echo $content; // already escaped
1841
+			return '';
1842
+		}
1843
+		return $content;
1844
+	}
1845
+
1846
+
1847
+	/**
1848
+	 * _add_global_screen_options
1849
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1850
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1851
+	 *
1852
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1853
+	 *         see also WP_Screen object documents...
1854
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1855
+	 * @abstract
1856
+	 * @return void
1857
+	 */
1858
+	private function _add_global_screen_options()
1859
+	{
1860
+	}
1861
+
1862
+
1863
+	/**
1864
+	 * _add_global_feature_pointers
1865
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1866
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1867
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1868
+	 *
1869
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1870
+	 *         extended) also see:
1871
+	 * @link   http://eamann.com/tech/wordpress-portland/
1872
+	 * @abstract
1873
+	 * @return void
1874
+	 */
1875
+	private function _add_global_feature_pointers()
1876
+	{
1877
+	}
1878
+
1879
+
1880
+	/**
1881
+	 * load_global_scripts_styles
1882
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1883
+	 *
1884
+	 * @return void
1885
+	 */
1886
+	public function load_global_scripts_styles()
1887
+	{
1888
+		/** STYLES **/
1889
+		// add debugging styles
1890
+		if (WP_DEBUG) {
1891
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1892
+		}
1893
+		// register all styles
1894
+		wp_register_style(
1895
+			'espresso-ui-theme',
1896
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
1897
+			[],
1898
+			EVENT_ESPRESSO_VERSION
1899
+		);
1900
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', [], EVENT_ESPRESSO_VERSION);
1901
+		// helpers styles
1902
+		wp_register_style(
1903
+			'ee-text-links',
1904
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css',
1905
+			[],
1906
+			EVENT_ESPRESSO_VERSION
1907
+		);
1908
+		/** SCRIPTS **/
1909
+		// register all scripts
1910
+		wp_register_script(
1911
+			'ee-dialog',
1912
+			EE_ADMIN_URL . 'assets/ee-dialog-helper.js',
1913
+			['jquery', 'jquery-ui-draggable'],
1914
+			EVENT_ESPRESSO_VERSION,
1915
+			true
1916
+		);
1917
+		wp_register_script(
1918
+			'ee_admin_js',
1919
+			EE_ADMIN_URL . 'assets/ee-admin-page.js',
1920
+			['espresso_core', 'ee-parse-uri', 'ee-dialog'],
1921
+			EVENT_ESPRESSO_VERSION,
1922
+			true
1923
+		);
1924
+		wp_register_script(
1925
+			'jquery-ui-timepicker-addon',
1926
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js',
1927
+			['jquery-ui-datepicker', 'jquery-ui-slider'],
1928
+			EVENT_ESPRESSO_VERSION,
1929
+			true
1930
+		);
1931
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1932
+		// if (EE_Registry::instance()->CFG->admin->help_tour_activation) {
1933
+		//     add_filter('FHEE_load_joyride', '__return_true');
1934
+		// }
1935
+		// script for sorting tables
1936
+		wp_register_script(
1937
+			'espresso_ajax_table_sorting',
1938
+			EE_ADMIN_URL . 'assets/espresso_ajax_table_sorting.js',
1939
+			['ee_admin_js', 'jquery-ui-sortable'],
1940
+			EVENT_ESPRESSO_VERSION,
1941
+			true
1942
+		);
1943
+		// script for parsing uri's
1944
+		wp_register_script(
1945
+			'ee-parse-uri',
1946
+			EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js',
1947
+			[],
1948
+			EVENT_ESPRESSO_VERSION,
1949
+			true
1950
+		);
1951
+		// and parsing associative serialized form elements
1952
+		wp_register_script(
1953
+			'ee-serialize-full-array',
1954
+			EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js',
1955
+			['jquery'],
1956
+			EVENT_ESPRESSO_VERSION,
1957
+			true
1958
+		);
1959
+		// helpers scripts
1960
+		wp_register_script(
1961
+			'ee-text-links',
1962
+			EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js',
1963
+			['jquery'],
1964
+			EVENT_ESPRESSO_VERSION,
1965
+			true
1966
+		);
1967
+		wp_register_script(
1968
+			'ee-moment-core',
1969
+			EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js',
1970
+			[],
1971
+			EVENT_ESPRESSO_VERSION,
1972
+			true
1973
+		);
1974
+		wp_register_script(
1975
+			'ee-moment',
1976
+			EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js',
1977
+			['ee-moment-core'],
1978
+			EVENT_ESPRESSO_VERSION,
1979
+			true
1980
+		);
1981
+		wp_register_script(
1982
+			'ee-datepicker',
1983
+			EE_ADMIN_URL . 'assets/ee-datepicker.js',
1984
+			['jquery-ui-timepicker-addon', 'ee-moment'],
1985
+			EVENT_ESPRESSO_VERSION,
1986
+			true
1987
+		);
1988
+		// google charts
1989
+		wp_register_script(
1990
+			'google-charts',
1991
+			'https://www.gstatic.com/charts/loader.js',
1992
+			[],
1993
+			EVENT_ESPRESSO_VERSION,
1994
+			false
1995
+		);
1996
+		// ENQUEUE ALL BASICS BY DEFAULT
1997
+		wp_enqueue_style('ee-admin-css');
1998
+		wp_enqueue_script('ee_admin_js');
1999
+		wp_enqueue_script('ee-accounting');
2000
+		wp_enqueue_script('jquery-validate');
2001
+		// taking care of metaboxes
2002
+		if (
2003
+			empty($this->_cpt_route)
2004
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
2005
+		) {
2006
+			wp_enqueue_script('dashboard');
2007
+		}
2008
+		// LOCALIZED DATA
2009
+		// localize script for ajax lazy loading
2010
+		$lazy_loader_container_ids = apply_filters(
2011
+			'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2012
+			['espresso_news_post_box_content']
2013
+		);
2014
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
2015
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
2016
+		// /**
2017
+		//  * help tour stuff
2018
+		//  */
2019
+		// if (! empty($this->_help_tour)) {
2020
+		//     // register the js for kicking things off
2021
+		//     wp_enqueue_script(
2022
+		//         'ee-help-tour',
2023
+		//         EE_ADMIN_URL . 'assets/ee-help-tour.js',
2024
+		//         array('jquery-joyride'),
2025
+		//         EVENT_ESPRESSO_VERSION,
2026
+		//         true
2027
+		//     );
2028
+		//     $tours = array();
2029
+		//     // setup tours for the js tour object
2030
+		//     foreach ($this->_help_tour['tours'] as $tour) {
2031
+		//         if ($tour instanceof EE_Help_Tour) {
2032
+		//             $tours[] = array(
2033
+		//                 'id'      => $tour->get_slug(),
2034
+		//                 'options' => $tour->get_options(),
2035
+		//             );
2036
+		//         }
2037
+		//     }
2038
+		//     wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2039
+		//     // admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2040
+		// }
2041
+
2042
+		add_filter(
2043
+			'admin_body_class',
2044
+			function ($classes) {
2045
+				if (strpos($classes, 'espresso-admin') === false) {
2046
+					$classes .= ' espresso-admin';
2047
+				}
2048
+				return $classes;
2049
+			}
2050
+		);
2051
+	}
2052
+
2053
+
2054
+	/**
2055
+	 *        admin_footer_scripts_eei18n_js_strings
2056
+	 *
2057
+	 * @return        void
2058
+	 */
2059
+	public function admin_footer_scripts_eei18n_js_strings()
2060
+	{
2061
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2062
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
2063
+			__(
2064
+				'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2065
+				'event_espresso'
2066
+			)
2067
+		);
2068
+		EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
2069
+		EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
2070
+		EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
2071
+		EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
2072
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2073
+		EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
2074
+		EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
2075
+		EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
2076
+		EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
2077
+		EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
2078
+		EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
2079
+		EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
2080
+		EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
2081
+		EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
2082
+		EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
2083
+		EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
2084
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2085
+		EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
2086
+		EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
2087
+		EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
2088
+		EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
2089
+		EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
2090
+		EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
2091
+		EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
2092
+		EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
2093
+		EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
2094
+		EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
2095
+		EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
2096
+		EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
2097
+		EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
2098
+		EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
2099
+		EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
2100
+		EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
2101
+		EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
2102
+		EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
2103
+		EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
2104
+		EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
2105
+		EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
2106
+	}
2107
+
2108
+
2109
+	/**
2110
+	 *        load enhanced xdebug styles for ppl with failing eyesight
2111
+	 *
2112
+	 * @return        void
2113
+	 */
2114
+	public function add_xdebug_style()
2115
+	{
2116
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2117
+	}
2118
+
2119
+
2120
+	/************************/
2121
+	/** LIST TABLE METHODS **/
2122
+	/************************/
2123
+	/**
2124
+	 * this sets up the list table if the current view requires it.
2125
+	 *
2126
+	 * @return void
2127
+	 * @throws EE_Error
2128
+	 */
2129
+	protected function _set_list_table()
2130
+	{
2131
+		// first is this a list_table view?
2132
+		if (! isset($this->_route_config['list_table'])) {
2133
+			return;
2134
+		} //not a list_table view so get out.
2135
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2136
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2137
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2138
+			// user error msg
2139
+			$error_msg = esc_html__(
2140
+				'An error occurred. The requested list table views could not be found.',
2141
+				'event_espresso'
2142
+			);
2143
+			// developer error msg
2144
+			$error_msg .= '||'
2145
+						  . sprintf(
2146
+							  esc_html__(
2147
+								  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2148
+								  'event_espresso'
2149
+							  ),
2150
+							  $this->_req_action,
2151
+							  $list_table_view
2152
+						  );
2153
+			throw new EE_Error($error_msg);
2154
+		}
2155
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2156
+		$this->_views = apply_filters(
2157
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2158
+			$this->_views
2159
+		);
2160
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2161
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2162
+		$this->_set_list_table_view();
2163
+		$this->_set_list_table_object();
2164
+	}
2165
+
2166
+
2167
+	/**
2168
+	 * set current view for List Table
2169
+	 *
2170
+	 * @return void
2171
+	 */
2172
+	protected function _set_list_table_view()
2173
+	{
2174
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2175
+		$status = $this->request->getRequestParam('status', null, 'key');
2176
+		$this->_view = $status && array_key_exists($status, $this->_views)
2177
+			? $status
2178
+			: $this->_view;
2179
+	}
2180
+
2181
+
2182
+	/**
2183
+	 * _set_list_table_object
2184
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2185
+	 *
2186
+	 * @throws InvalidInterfaceException
2187
+	 * @throws InvalidArgumentException
2188
+	 * @throws InvalidDataTypeException
2189
+	 * @throws EE_Error
2190
+	 * @throws InvalidInterfaceException
2191
+	 */
2192
+	protected function _set_list_table_object()
2193
+	{
2194
+		if (isset($this->_route_config['list_table'])) {
2195
+			if (! class_exists($this->_route_config['list_table'])) {
2196
+				throw new EE_Error(
2197
+					sprintf(
2198
+						esc_html__(
2199
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2200
+							'event_espresso'
2201
+						),
2202
+						$this->_route_config['list_table'],
2203
+						get_class($this)
2204
+					)
2205
+				);
2206
+			}
2207
+			$this->_list_table_object = $this->loader->getShared(
2208
+				$this->_route_config['list_table'],
2209
+				[$this]
2210
+			);
2211
+		}
2212
+	}
2213
+
2214
+
2215
+	/**
2216
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2217
+	 *
2218
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2219
+	 *                                                    urls.  The array should be indexed by the view it is being
2220
+	 *                                                    added to.
2221
+	 * @return array
2222
+	 */
2223
+	public function get_list_table_view_RLs($extra_query_args = [])
2224
+	{
2225
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2226
+		if (empty($this->_views)) {
2227
+			$this->_views = [];
2228
+		}
2229
+		// cycle thru views
2230
+		foreach ($this->_views as $key => $view) {
2231
+			$query_args = [];
2232
+			// check for current view
2233
+			$this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2234
+			$query_args['action']                        = $this->_req_action;
2235
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2236
+			$query_args['status']                        = $view['slug'];
2237
+			// merge any other arguments sent in.
2238
+			if (isset($extra_query_args[ $view['slug'] ])) {
2239
+				$query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2240
+			}
2241
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2242
+		}
2243
+		return $this->_views;
2244
+	}
2245
+
2246
+
2247
+	/**
2248
+	 * _entries_per_page_dropdown
2249
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2250
+	 *
2251
+	 * @param int $max_entries total number of rows in the table
2252
+	 * @return string
2253
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2254
+	 *         WP does it.
2255
+	 */
2256
+	protected function _entries_per_page_dropdown($max_entries = 0)
2257
+	{
2258
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2259
+		$values   = [10, 25, 50, 100];
2260
+		$per_page = $this->request->getRequestParam('per_page', 10, 'int');
2261
+		if ($max_entries) {
2262
+			$values[] = $max_entries;
2263
+			sort($values);
2264
+		}
2265
+		$entries_per_page_dropdown = '
2266 2266
 			<div id="entries-per-page-dv" class="alignleft actions">
2267 2267
 				<label class="hide-if-no-js">
2268 2268
 					Show
2269 2269
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2270
-        foreach ($values as $value) {
2271
-            if ($value < $max_entries) {
2272
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2273
-                $entries_per_page_dropdown .= '
2270
+		foreach ($values as $value) {
2271
+			if ($value < $max_entries) {
2272
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2273
+				$entries_per_page_dropdown .= '
2274 2274
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2275
-            }
2276
-        }
2277
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2278
-        $entries_per_page_dropdown .= '
2275
+			}
2276
+		}
2277
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2278
+		$entries_per_page_dropdown .= '
2279 2279
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2280
-        $entries_per_page_dropdown .= '
2280
+		$entries_per_page_dropdown .= '
2281 2281
 					</select>
2282 2282
 					entries
2283 2283
 				</label>
2284 2284
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2285 2285
 			</div>
2286 2286
 		';
2287
-        return $entries_per_page_dropdown;
2288
-    }
2289
-
2290
-
2291
-    /**
2292
-     *        _set_search_attributes
2293
-     *
2294
-     * @return        void
2295
-     */
2296
-    public function _set_search_attributes()
2297
-    {
2298
-        $this->_template_args['search']['btn_label'] = sprintf(
2299
-            esc_html__('Search %s', 'event_espresso'),
2300
-            empty($this->_search_btn_label) ? $this->page_label
2301
-                : $this->_search_btn_label
2302
-        );
2303
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2304
-    }
2305
-
2306
-
2307
-
2308
-    /*** END LIST TABLE METHODS **/
2309
-
2310
-
2311
-    /**
2312
-     * _add_registered_metaboxes
2313
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2314
-     *
2315
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2316
-     * @return void
2317
-     * @throws EE_Error
2318
-     */
2319
-    private function _add_registered_meta_boxes()
2320
-    {
2321
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2322
-        // we only add meta boxes if the page_route calls for it
2323
-        if (
2324
-            is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2325
-            && is_array(
2326
-                $this->_route_config['metaboxes']
2327
-            )
2328
-        ) {
2329
-            // this simply loops through the callbacks provided
2330
-            // and checks if there is a corresponding callback registered by the child
2331
-            // if there is then we go ahead and process the metabox loader.
2332
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2333
-                // first check for Closures
2334
-                if ($metabox_callback instanceof Closure) {
2335
-                    $result = $metabox_callback();
2336
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2337
-                    $result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2338
-                } else {
2339
-                    $result = call_user_func([$this, &$metabox_callback]);
2340
-                }
2341
-                if ($result === false) {
2342
-                    // user error msg
2343
-                    $error_msg = esc_html__(
2344
-                        'An error occurred. The  requested metabox could not be found.',
2345
-                        'event_espresso'
2346
-                    );
2347
-                    // developer error msg
2348
-                    $error_msg .= '||'
2349
-                                  . sprintf(
2350
-                                      esc_html__(
2351
-                                          'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2352
-                                          'event_espresso'
2353
-                                      ),
2354
-                                      $metabox_callback
2355
-                                  );
2356
-                    throw new EE_Error($error_msg);
2357
-                }
2358
-            }
2359
-        }
2360
-    }
2361
-
2362
-
2363
-    /**
2364
-     * _add_screen_columns
2365
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2366
-     * the dynamic column template and we'll setup the column options for the page.
2367
-     *
2368
-     * @return void
2369
-     */
2370
-    private function _add_screen_columns()
2371
-    {
2372
-        if (
2373
-            is_array($this->_route_config)
2374
-            && isset($this->_route_config['columns'])
2375
-            && is_array($this->_route_config['columns'])
2376
-            && count($this->_route_config['columns']) === 2
2377
-        ) {
2378
-            add_screen_option(
2379
-                'layout_columns',
2380
-                [
2381
-                    'max'     => (int) $this->_route_config['columns'][0],
2382
-                    'default' => (int) $this->_route_config['columns'][1],
2383
-                ]
2384
-            );
2385
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2386
-            $screen_id                                           = $this->_current_screen->id;
2387
-            $screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2388
-            $total_columns                                       = ! empty($screen_columns)
2389
-                ? $screen_columns
2390
-                : $this->_route_config['columns'][1];
2391
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2392
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2393
-            $this->_template_args['screen']                      = $this->_current_screen;
2394
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2395
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2396
-            // finally if we don't have has_metaboxes set in the route config
2397
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2398
-            $this->_route_config['has_metaboxes'] = true;
2399
-        }
2400
-    }
2401
-
2402
-
2403
-
2404
-    /** GLOBALLY AVAILABLE METABOXES **/
2405
-
2406
-
2407
-    /**
2408
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2409
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2410
-     * these get loaded on.
2411
-     */
2412
-    private function _espresso_news_post_box()
2413
-    {
2414
-        $news_box_title = apply_filters(
2415
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2416
-            esc_html__('New @ Event Espresso', 'event_espresso')
2417
-        );
2418
-        add_meta_box(
2419
-            'espresso_news_post_box',
2420
-            $news_box_title,
2421
-            [
2422
-                $this,
2423
-                'espresso_news_post_box',
2424
-            ],
2425
-            $this->_wp_page_slug,
2426
-            'side'
2427
-        );
2428
-    }
2429
-
2430
-
2431
-    /**
2432
-     * Code for setting up espresso ratings request metabox.
2433
-     */
2434
-    protected function _espresso_ratings_request()
2435
-    {
2436
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2437
-            return;
2438
-        }
2439
-        $ratings_box_title = apply_filters(
2440
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2441
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2442
-        );
2443
-        add_meta_box(
2444
-            'espresso_ratings_request',
2445
-            $ratings_box_title,
2446
-            [
2447
-                $this,
2448
-                'espresso_ratings_request',
2449
-            ],
2450
-            $this->_wp_page_slug,
2451
-            'side'
2452
-        );
2453
-    }
2454
-
2455
-
2456
-    /**
2457
-     * Code for setting up espresso ratings request metabox content.
2458
-     *
2459
-     * @throws DomainException
2460
-     */
2461
-    public function espresso_ratings_request()
2462
-    {
2463
-        EEH_Template::display_template(
2464
-            EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2465
-            []
2466
-        );
2467
-    }
2468
-
2469
-
2470
-    public static function cached_rss_display($rss_id, $url)
2471
-    {
2472
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2473
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2474
-                     . '</p><p class="hide-if-js">'
2475
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2476
-                     . '</p>';
2477
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2478
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2479
-        $post      = '</div>' . "\n";
2480
-        $cache_key = 'ee_rss_' . md5($rss_id);
2481
-        $output    = get_transient($cache_key);
2482
-        if ($output !== false) {
2483
-            echo $pre . $output . $post; // already escaped
2484
-            return true;
2485
-        }
2486
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2487
-            echo $pre . $loading . $post; // already escaped
2488
-            return false;
2489
-        }
2490
-        ob_start();
2491
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2492
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2493
-        return true;
2494
-    }
2495
-
2496
-
2497
-    public function espresso_news_post_box()
2498
-    {
2499
-        ?>
2287
+		return $entries_per_page_dropdown;
2288
+	}
2289
+
2290
+
2291
+	/**
2292
+	 *        _set_search_attributes
2293
+	 *
2294
+	 * @return        void
2295
+	 */
2296
+	public function _set_search_attributes()
2297
+	{
2298
+		$this->_template_args['search']['btn_label'] = sprintf(
2299
+			esc_html__('Search %s', 'event_espresso'),
2300
+			empty($this->_search_btn_label) ? $this->page_label
2301
+				: $this->_search_btn_label
2302
+		);
2303
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2304
+	}
2305
+
2306
+
2307
+
2308
+	/*** END LIST TABLE METHODS **/
2309
+
2310
+
2311
+	/**
2312
+	 * _add_registered_metaboxes
2313
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2314
+	 *
2315
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2316
+	 * @return void
2317
+	 * @throws EE_Error
2318
+	 */
2319
+	private function _add_registered_meta_boxes()
2320
+	{
2321
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2322
+		// we only add meta boxes if the page_route calls for it
2323
+		if (
2324
+			is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2325
+			&& is_array(
2326
+				$this->_route_config['metaboxes']
2327
+			)
2328
+		) {
2329
+			// this simply loops through the callbacks provided
2330
+			// and checks if there is a corresponding callback registered by the child
2331
+			// if there is then we go ahead and process the metabox loader.
2332
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2333
+				// first check for Closures
2334
+				if ($metabox_callback instanceof Closure) {
2335
+					$result = $metabox_callback();
2336
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2337
+					$result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2338
+				} else {
2339
+					$result = call_user_func([$this, &$metabox_callback]);
2340
+				}
2341
+				if ($result === false) {
2342
+					// user error msg
2343
+					$error_msg = esc_html__(
2344
+						'An error occurred. The  requested metabox could not be found.',
2345
+						'event_espresso'
2346
+					);
2347
+					// developer error msg
2348
+					$error_msg .= '||'
2349
+								  . sprintf(
2350
+									  esc_html__(
2351
+										  'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2352
+										  'event_espresso'
2353
+									  ),
2354
+									  $metabox_callback
2355
+								  );
2356
+					throw new EE_Error($error_msg);
2357
+				}
2358
+			}
2359
+		}
2360
+	}
2361
+
2362
+
2363
+	/**
2364
+	 * _add_screen_columns
2365
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2366
+	 * the dynamic column template and we'll setup the column options for the page.
2367
+	 *
2368
+	 * @return void
2369
+	 */
2370
+	private function _add_screen_columns()
2371
+	{
2372
+		if (
2373
+			is_array($this->_route_config)
2374
+			&& isset($this->_route_config['columns'])
2375
+			&& is_array($this->_route_config['columns'])
2376
+			&& count($this->_route_config['columns']) === 2
2377
+		) {
2378
+			add_screen_option(
2379
+				'layout_columns',
2380
+				[
2381
+					'max'     => (int) $this->_route_config['columns'][0],
2382
+					'default' => (int) $this->_route_config['columns'][1],
2383
+				]
2384
+			);
2385
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2386
+			$screen_id                                           = $this->_current_screen->id;
2387
+			$screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2388
+			$total_columns                                       = ! empty($screen_columns)
2389
+				? $screen_columns
2390
+				: $this->_route_config['columns'][1];
2391
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2392
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2393
+			$this->_template_args['screen']                      = $this->_current_screen;
2394
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2395
+																   . 'admin_details_metabox_column_wrapper.template.php';
2396
+			// finally if we don't have has_metaboxes set in the route config
2397
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2398
+			$this->_route_config['has_metaboxes'] = true;
2399
+		}
2400
+	}
2401
+
2402
+
2403
+
2404
+	/** GLOBALLY AVAILABLE METABOXES **/
2405
+
2406
+
2407
+	/**
2408
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2409
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2410
+	 * these get loaded on.
2411
+	 */
2412
+	private function _espresso_news_post_box()
2413
+	{
2414
+		$news_box_title = apply_filters(
2415
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2416
+			esc_html__('New @ Event Espresso', 'event_espresso')
2417
+		);
2418
+		add_meta_box(
2419
+			'espresso_news_post_box',
2420
+			$news_box_title,
2421
+			[
2422
+				$this,
2423
+				'espresso_news_post_box',
2424
+			],
2425
+			$this->_wp_page_slug,
2426
+			'side'
2427
+		);
2428
+	}
2429
+
2430
+
2431
+	/**
2432
+	 * Code for setting up espresso ratings request metabox.
2433
+	 */
2434
+	protected function _espresso_ratings_request()
2435
+	{
2436
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2437
+			return;
2438
+		}
2439
+		$ratings_box_title = apply_filters(
2440
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2441
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2442
+		);
2443
+		add_meta_box(
2444
+			'espresso_ratings_request',
2445
+			$ratings_box_title,
2446
+			[
2447
+				$this,
2448
+				'espresso_ratings_request',
2449
+			],
2450
+			$this->_wp_page_slug,
2451
+			'side'
2452
+		);
2453
+	}
2454
+
2455
+
2456
+	/**
2457
+	 * Code for setting up espresso ratings request metabox content.
2458
+	 *
2459
+	 * @throws DomainException
2460
+	 */
2461
+	public function espresso_ratings_request()
2462
+	{
2463
+		EEH_Template::display_template(
2464
+			EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php',
2465
+			[]
2466
+		);
2467
+	}
2468
+
2469
+
2470
+	public static function cached_rss_display($rss_id, $url)
2471
+	{
2472
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2473
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2474
+					 . '</p><p class="hide-if-js">'
2475
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2476
+					 . '</p>';
2477
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2478
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2479
+		$post      = '</div>' . "\n";
2480
+		$cache_key = 'ee_rss_' . md5($rss_id);
2481
+		$output    = get_transient($cache_key);
2482
+		if ($output !== false) {
2483
+			echo $pre . $output . $post; // already escaped
2484
+			return true;
2485
+		}
2486
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2487
+			echo $pre . $loading . $post; // already escaped
2488
+			return false;
2489
+		}
2490
+		ob_start();
2491
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2492
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2493
+		return true;
2494
+	}
2495
+
2496
+
2497
+	public function espresso_news_post_box()
2498
+	{
2499
+		?>
2500 2500
         <div class="padding">
2501 2501
             <div id="espresso_news_post_box_content" class="infolinks">
2502 2502
                 <?php
2503
-                // Get RSS Feed(s)
2504
-                self::cached_rss_display(
2505
-                    'espresso_news_post_box_content',
2506
-                    urlencode(
2507
-                        apply_filters(
2508
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2509
-                            'https://eventespresso.com/feed/'
2510
-                        )
2511
-                    )
2512
-                );
2513
-                ?>
2503
+				// Get RSS Feed(s)
2504
+				self::cached_rss_display(
2505
+					'espresso_news_post_box_content',
2506
+					urlencode(
2507
+						apply_filters(
2508
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2509
+							'https://eventespresso.com/feed/'
2510
+						)
2511
+					)
2512
+				);
2513
+				?>
2514 2514
             </div>
2515 2515
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2516 2516
         </div>
2517 2517
         <?php
2518
-    }
2519
-
2520
-
2521
-    private function _espresso_links_post_box()
2522
-    {
2523
-        // Hiding until we actually have content to put in here...
2524
-        // add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2525
-    }
2526
-
2527
-
2528
-    public function espresso_links_post_box()
2529
-    {
2530
-        // Hiding until we actually have content to put in here...
2531
-        // EEH_Template::display_template(
2532
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2533
-        // );
2534
-    }
2535
-
2536
-
2537
-    protected function _espresso_sponsors_post_box()
2538
-    {
2539
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2540
-            add_meta_box(
2541
-                'espresso_sponsors_post_box',
2542
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2543
-                [$this, 'espresso_sponsors_post_box'],
2544
-                $this->_wp_page_slug,
2545
-                'side'
2546
-            );
2547
-        }
2548
-    }
2549
-
2550
-
2551
-    public function espresso_sponsors_post_box()
2552
-    {
2553
-        EEH_Template::display_template(
2554
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2555
-        );
2556
-    }
2557
-
2558
-
2559
-    private function _publish_post_box()
2560
-    {
2561
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2562
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2563
-        // then we'll use that for the metabox label.
2564
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2565
-        if (! empty($this->_labels['publishbox'])) {
2566
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2567
-                : $this->_labels['publishbox'];
2568
-        } else {
2569
-            $box_label = esc_html__('Publish', 'event_espresso');
2570
-        }
2571
-        $box_label = apply_filters(
2572
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2573
-            $box_label,
2574
-            $this->_req_action,
2575
-            $this
2576
-        );
2577
-        add_meta_box(
2578
-            $meta_box_ref,
2579
-            $box_label,
2580
-            [$this, 'editor_overview'],
2581
-            $this->_current_screen->id,
2582
-            'side',
2583
-            'high'
2584
-        );
2585
-    }
2586
-
2587
-
2588
-    public function editor_overview()
2589
-    {
2590
-        // if we have extra content set let's add it in if not make sure its empty
2591
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2592
-            ? $this->_template_args['publish_box_extra_content']
2593
-            : '';
2594
-        echo EEH_Template::display_template(
2595
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2596
-            $this->_template_args,
2597
-            true
2598
-        );
2599
-    }
2600
-
2601
-
2602
-    /** end of globally available metaboxes section **/
2603
-
2604
-
2605
-    /**
2606
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2607
-     * protected method.
2608
-     *
2609
-     * @param string $name
2610
-     * @param int    $id
2611
-     * @param bool   $delete
2612
-     * @param string $save_close_redirect_URL
2613
-     * @param bool   $both_btns
2614
-     * @throws EE_Error
2615
-     * @throws InvalidArgumentException
2616
-     * @throws InvalidDataTypeException
2617
-     * @throws InvalidInterfaceException
2618
-     * @see   $this->_set_publish_post_box_vars for param details
2619
-     * @since 4.6.0
2620
-     */
2621
-    public function set_publish_post_box_vars(
2622
-        $name = '',
2623
-        $id = 0,
2624
-        $delete = false,
2625
-        $save_close_redirect_URL = '',
2626
-        $both_btns = true
2627
-    ) {
2628
-        $this->_set_publish_post_box_vars(
2629
-            $name,
2630
-            $id,
2631
-            $delete,
2632
-            $save_close_redirect_URL,
2633
-            $both_btns
2634
-        );
2635
-    }
2636
-
2637
-
2638
-    /**
2639
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2640
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2641
-     * save, and save and close buttons to work properly, then you will want to include a
2642
-     * values for the name and id arguments.
2643
-     *
2644
-     * @param string  $name                       key used for the action ID (i.e. event_id)
2645
-     * @param int     $id                         id attached to the item published
2646
-     * @param string  $delete                     page route callback for the delete action
2647
-     * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2648
-     * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2649
-     *                                            the Save button
2650
-     * @throws EE_Error
2651
-     * @throws InvalidArgumentException
2652
-     * @throws InvalidDataTypeException
2653
-     * @throws InvalidInterfaceException
2654
-     * @todo  Add in validation for name/id arguments.
2655
-     */
2656
-    protected function _set_publish_post_box_vars(
2657
-        $name = '',
2658
-        $id = 0,
2659
-        $delete = '',
2660
-        $save_close_redirect_URL = '',
2661
-        $both_btns = true
2662
-    ) {
2663
-        // if Save & Close, use a custom redirect URL or default to the main page?
2664
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2665
-            ? $save_close_redirect_URL
2666
-            : $this->_admin_base_url;
2667
-        // create the Save & Close and Save buttons
2668
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2669
-        // if we have extra content set let's add it in if not make sure its empty
2670
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2671
-            ? $this->_template_args['publish_box_extra_content']
2672
-            : '';
2673
-        if ($delete && ! empty($id)) {
2674
-            // make sure we have a default if just true is sent.
2675
-            $delete           = ! empty($delete) ? $delete : 'delete';
2676
-            $delete_link_args = [$name => $id];
2677
-            $delete           = $this->get_action_link_or_button(
2678
-                $delete,
2679
-                $delete,
2680
-                $delete_link_args,
2681
-                'submitdelete deletion',
2682
-                '',
2683
-                false
2684
-            );
2685
-        }
2686
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2687
-        if (! empty($name) && ! empty($id)) {
2688
-            $hidden_field_arr[ $name ] = [
2689
-                'type'  => 'hidden',
2690
-                'value' => $id,
2691
-            ];
2692
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2693
-        } else {
2694
-            $hf = '';
2695
-        }
2696
-        // add hidden field
2697
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2698
-            ? $hf[ $name ]['field']
2699
-            : $hf;
2700
-    }
2701
-
2702
-
2703
-    /**
2704
-     * displays an error message to ppl who have javascript disabled
2705
-     *
2706
-     * @return void
2707
-     */
2708
-    private function _display_no_javascript_warning()
2709
-    {
2710
-        ?>
2518
+	}
2519
+
2520
+
2521
+	private function _espresso_links_post_box()
2522
+	{
2523
+		// Hiding until we actually have content to put in here...
2524
+		// add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2525
+	}
2526
+
2527
+
2528
+	public function espresso_links_post_box()
2529
+	{
2530
+		// Hiding until we actually have content to put in here...
2531
+		// EEH_Template::display_template(
2532
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2533
+		// );
2534
+	}
2535
+
2536
+
2537
+	protected function _espresso_sponsors_post_box()
2538
+	{
2539
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2540
+			add_meta_box(
2541
+				'espresso_sponsors_post_box',
2542
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2543
+				[$this, 'espresso_sponsors_post_box'],
2544
+				$this->_wp_page_slug,
2545
+				'side'
2546
+			);
2547
+		}
2548
+	}
2549
+
2550
+
2551
+	public function espresso_sponsors_post_box()
2552
+	{
2553
+		EEH_Template::display_template(
2554
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2555
+		);
2556
+	}
2557
+
2558
+
2559
+	private function _publish_post_box()
2560
+	{
2561
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2562
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2563
+		// then we'll use that for the metabox label.
2564
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2565
+		if (! empty($this->_labels['publishbox'])) {
2566
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2567
+				: $this->_labels['publishbox'];
2568
+		} else {
2569
+			$box_label = esc_html__('Publish', 'event_espresso');
2570
+		}
2571
+		$box_label = apply_filters(
2572
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2573
+			$box_label,
2574
+			$this->_req_action,
2575
+			$this
2576
+		);
2577
+		add_meta_box(
2578
+			$meta_box_ref,
2579
+			$box_label,
2580
+			[$this, 'editor_overview'],
2581
+			$this->_current_screen->id,
2582
+			'side',
2583
+			'high'
2584
+		);
2585
+	}
2586
+
2587
+
2588
+	public function editor_overview()
2589
+	{
2590
+		// if we have extra content set let's add it in if not make sure its empty
2591
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2592
+			? $this->_template_args['publish_box_extra_content']
2593
+			: '';
2594
+		echo EEH_Template::display_template(
2595
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2596
+			$this->_template_args,
2597
+			true
2598
+		);
2599
+	}
2600
+
2601
+
2602
+	/** end of globally available metaboxes section **/
2603
+
2604
+
2605
+	/**
2606
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2607
+	 * protected method.
2608
+	 *
2609
+	 * @param string $name
2610
+	 * @param int    $id
2611
+	 * @param bool   $delete
2612
+	 * @param string $save_close_redirect_URL
2613
+	 * @param bool   $both_btns
2614
+	 * @throws EE_Error
2615
+	 * @throws InvalidArgumentException
2616
+	 * @throws InvalidDataTypeException
2617
+	 * @throws InvalidInterfaceException
2618
+	 * @see   $this->_set_publish_post_box_vars for param details
2619
+	 * @since 4.6.0
2620
+	 */
2621
+	public function set_publish_post_box_vars(
2622
+		$name = '',
2623
+		$id = 0,
2624
+		$delete = false,
2625
+		$save_close_redirect_URL = '',
2626
+		$both_btns = true
2627
+	) {
2628
+		$this->_set_publish_post_box_vars(
2629
+			$name,
2630
+			$id,
2631
+			$delete,
2632
+			$save_close_redirect_URL,
2633
+			$both_btns
2634
+		);
2635
+	}
2636
+
2637
+
2638
+	/**
2639
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2640
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2641
+	 * save, and save and close buttons to work properly, then you will want to include a
2642
+	 * values for the name and id arguments.
2643
+	 *
2644
+	 * @param string  $name                       key used for the action ID (i.e. event_id)
2645
+	 * @param int     $id                         id attached to the item published
2646
+	 * @param string  $delete                     page route callback for the delete action
2647
+	 * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2648
+	 * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2649
+	 *                                            the Save button
2650
+	 * @throws EE_Error
2651
+	 * @throws InvalidArgumentException
2652
+	 * @throws InvalidDataTypeException
2653
+	 * @throws InvalidInterfaceException
2654
+	 * @todo  Add in validation for name/id arguments.
2655
+	 */
2656
+	protected function _set_publish_post_box_vars(
2657
+		$name = '',
2658
+		$id = 0,
2659
+		$delete = '',
2660
+		$save_close_redirect_URL = '',
2661
+		$both_btns = true
2662
+	) {
2663
+		// if Save & Close, use a custom redirect URL or default to the main page?
2664
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2665
+			? $save_close_redirect_URL
2666
+			: $this->_admin_base_url;
2667
+		// create the Save & Close and Save buttons
2668
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2669
+		// if we have extra content set let's add it in if not make sure its empty
2670
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2671
+			? $this->_template_args['publish_box_extra_content']
2672
+			: '';
2673
+		if ($delete && ! empty($id)) {
2674
+			// make sure we have a default if just true is sent.
2675
+			$delete           = ! empty($delete) ? $delete : 'delete';
2676
+			$delete_link_args = [$name => $id];
2677
+			$delete           = $this->get_action_link_or_button(
2678
+				$delete,
2679
+				$delete,
2680
+				$delete_link_args,
2681
+				'submitdelete deletion',
2682
+				'',
2683
+				false
2684
+			);
2685
+		}
2686
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2687
+		if (! empty($name) && ! empty($id)) {
2688
+			$hidden_field_arr[ $name ] = [
2689
+				'type'  => 'hidden',
2690
+				'value' => $id,
2691
+			];
2692
+			$hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2693
+		} else {
2694
+			$hf = '';
2695
+		}
2696
+		// add hidden field
2697
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2698
+			? $hf[ $name ]['field']
2699
+			: $hf;
2700
+	}
2701
+
2702
+
2703
+	/**
2704
+	 * displays an error message to ppl who have javascript disabled
2705
+	 *
2706
+	 * @return void
2707
+	 */
2708
+	private function _display_no_javascript_warning()
2709
+	{
2710
+		?>
2711 2711
         <noscript>
2712 2712
             <div id="no-js-message" class="error">
2713 2713
                 <p style="font-size:1.3em;">
2714 2714
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2715 2715
                     <?php esc_html_e(
2716
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2717
-                        'event_espresso'
2718
-                    ); ?>
2716
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2717
+						'event_espresso'
2718
+					); ?>
2719 2719
                 </p>
2720 2720
             </div>
2721 2721
         </noscript>
2722 2722
         <?php
2723
-    }
2724
-
2725
-
2726
-    /**
2727
-     * displays espresso success and/or error notices
2728
-     *
2729
-     * @return void
2730
-     */
2731
-    private function _display_espresso_notices()
2732
-    {
2733
-        $notices = $this->_get_transient(true);
2734
-        echo stripslashes($notices);
2735
-    }
2736
-
2737
-
2738
-    /**
2739
-     * spinny things pacify the masses
2740
-     *
2741
-     * @return void
2742
-     */
2743
-    protected function _add_admin_page_ajax_loading_img()
2744
-    {
2745
-        ?>
2723
+	}
2724
+
2725
+
2726
+	/**
2727
+	 * displays espresso success and/or error notices
2728
+	 *
2729
+	 * @return void
2730
+	 */
2731
+	private function _display_espresso_notices()
2732
+	{
2733
+		$notices = $this->_get_transient(true);
2734
+		echo stripslashes($notices);
2735
+	}
2736
+
2737
+
2738
+	/**
2739
+	 * spinny things pacify the masses
2740
+	 *
2741
+	 * @return void
2742
+	 */
2743
+	protected function _add_admin_page_ajax_loading_img()
2744
+	{
2745
+		?>
2746 2746
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2747 2747
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2748
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2748
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2749 2749
         </div>
2750 2750
         <?php
2751
-    }
2751
+	}
2752 2752
 
2753 2753
 
2754
-    /**
2755
-     * add admin page overlay for modal boxes
2756
-     *
2757
-     * @return void
2758
-     */
2759
-    protected function _add_admin_page_overlay()
2760
-    {
2761
-        ?>
2754
+	/**
2755
+	 * add admin page overlay for modal boxes
2756
+	 *
2757
+	 * @return void
2758
+	 */
2759
+	protected function _add_admin_page_overlay()
2760
+	{
2761
+		?>
2762 2762
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2763 2763
         <?php
2764
-    }
2765
-
2766
-
2767
-    /**
2768
-     * facade for add_meta_box
2769
-     *
2770
-     * @param string  $action        where the metabox get's displayed
2771
-     * @param string  $title         Title of Metabox (output in metabox header)
2772
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2773
-     *                               instead of the one created in here.
2774
-     * @param array   $callback_args an array of args supplied for the metabox
2775
-     * @param string  $column        what metabox column
2776
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2777
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2778
-     *                               created but just set our own callback for wp's add_meta_box.
2779
-     * @throws DomainException
2780
-     */
2781
-    public function _add_admin_page_meta_box(
2782
-        $action,
2783
-        $title,
2784
-        $callback,
2785
-        $callback_args,
2786
-        $column = 'normal',
2787
-        $priority = 'high',
2788
-        $create_func = true
2789
-    ) {
2790
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2791
-        // if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2792
-        if (empty($callback_args) && $create_func) {
2793
-            $callback_args = [
2794
-                'template_path' => $this->_template_path,
2795
-                'template_args' => $this->_template_args,
2796
-            ];
2797
-        }
2798
-        // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2799
-        $call_back_func = $create_func
2800
-            ? function ($post, $metabox) {
2801
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2802
-                echo EEH_Template::display_template(
2803
-                    $metabox['args']['template_path'],
2804
-                    $metabox['args']['template_args'],
2805
-                    true
2806
-                );
2807
-            }
2808
-            : $callback;
2809
-        add_meta_box(
2810
-            str_replace('_', '-', $action) . '-mbox',
2811
-            $title,
2812
-            $call_back_func,
2813
-            $this->_wp_page_slug,
2814
-            $column,
2815
-            $priority,
2816
-            $callback_args
2817
-        );
2818
-    }
2819
-
2820
-
2821
-    /**
2822
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2823
-     *
2824
-     * @throws DomainException
2825
-     * @throws EE_Error
2826
-     */
2827
-    public function display_admin_page_with_metabox_columns()
2828
-    {
2829
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2830
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2831
-            $this->_column_template_path,
2832
-            $this->_template_args,
2833
-            true
2834
-        );
2835
-        // the final wrapper
2836
-        $this->admin_page_wrapper();
2837
-    }
2838
-
2839
-
2840
-    /**
2841
-     * generates  HTML wrapper for an admin details page
2842
-     *
2843
-     * @return void
2844
-     * @throws EE_Error
2845
-     * @throws DomainException
2846
-     */
2847
-    public function display_admin_page_with_sidebar()
2848
-    {
2849
-        $this->_display_admin_page(true);
2850
-    }
2851
-
2852
-
2853
-    /**
2854
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2855
-     *
2856
-     * @return void
2857
-     * @throws EE_Error
2858
-     * @throws DomainException
2859
-     */
2860
-    public function display_admin_page_with_no_sidebar()
2861
-    {
2862
-        $this->_display_admin_page();
2863
-    }
2864
-
2865
-
2866
-    /**
2867
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2868
-     *
2869
-     * @return void
2870
-     * @throws EE_Error
2871
-     * @throws DomainException
2872
-     */
2873
-    public function display_about_admin_page()
2874
-    {
2875
-        $this->_display_admin_page(false, true);
2876
-    }
2877
-
2878
-
2879
-    /**
2880
-     * display_admin_page
2881
-     * contains the code for actually displaying an admin page
2882
-     *
2883
-     * @param boolean $sidebar true with sidebar, false without
2884
-     * @param boolean $about   use the about_admin_wrapper instead of the default.
2885
-     * @return void
2886
-     * @throws DomainException
2887
-     * @throws EE_Error
2888
-     */
2889
-    private function _display_admin_page($sidebar = false, $about = false)
2890
-    {
2891
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2892
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2893
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2894
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2895
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2896
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2897
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2898
-            ? 'poststuff'
2899
-            : 'espresso-default-admin';
2900
-        $template_path                                     = $sidebar
2901
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2902
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2903
-        if ($this->request->isAjax()) {
2904
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2905
-        }
2906
-        $template_path                                     = ! empty($this->_column_template_path)
2907
-            ? $this->_column_template_path : $template_path;
2908
-        $this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2909
-            ? $this->_template_args['admin_page_content']
2910
-            : '';
2911
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2912
-            ? $this->_template_args['before_admin_page_content']
2913
-            : '';
2914
-        $this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2915
-            ? $this->_template_args['after_admin_page_content']
2916
-            : '';
2917
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2918
-            $template_path,
2919
-            $this->_template_args,
2920
-            true
2921
-        );
2922
-        // the final template wrapper
2923
-        $this->admin_page_wrapper($about);
2924
-    }
2925
-
2926
-
2927
-    /**
2928
-     * This is used to display caf preview pages.
2929
-     *
2930
-     * @param string $utm_campaign_source what is the key used for google analytics link
2931
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2932
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2933
-     * @return void
2934
-     * @throws DomainException
2935
-     * @throws EE_Error
2936
-     * @throws InvalidArgumentException
2937
-     * @throws InvalidDataTypeException
2938
-     * @throws InvalidInterfaceException
2939
-     * @since 4.3.2
2940
-     */
2941
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2942
-    {
2943
-        // let's generate a default preview action button if there isn't one already present.
2944
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2945
-            'Upgrade to Event Espresso 4 Right Now',
2946
-            'event_espresso'
2947
-        );
2948
-        $buy_now_url                                   = add_query_arg(
2949
-            [
2950
-                'ee_ver'       => 'ee4',
2951
-                'utm_source'   => 'ee4_plugin_admin',
2952
-                'utm_medium'   => 'link',
2953
-                'utm_campaign' => $utm_campaign_source,
2954
-                'utm_content'  => 'buy_now_button',
2955
-            ],
2956
-            'https://eventespresso.com/pricing/'
2957
-        );
2958
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2959
-            ? $this->get_action_link_or_button(
2960
-                '',
2961
-                'buy_now',
2962
-                [],
2963
-                'button-primary button-large',
2964
-                esc_url_raw($buy_now_url),
2965
-                true
2966
-            )
2967
-            : $this->_template_args['preview_action_button'];
2968
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2969
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2970
-            $this->_template_args,
2971
-            true
2972
-        );
2973
-        $this->_display_admin_page($display_sidebar);
2974
-    }
2975
-
2976
-
2977
-    /**
2978
-     * display_admin_list_table_page_with_sidebar
2979
-     * generates HTML wrapper for an admin_page with list_table
2980
-     *
2981
-     * @return void
2982
-     * @throws EE_Error
2983
-     * @throws DomainException
2984
-     */
2985
-    public function display_admin_list_table_page_with_sidebar()
2986
-    {
2987
-        $this->_display_admin_list_table_page(true);
2988
-    }
2989
-
2990
-
2991
-    /**
2992
-     * display_admin_list_table_page_with_no_sidebar
2993
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2994
-     *
2995
-     * @return void
2996
-     * @throws EE_Error
2997
-     * @throws DomainException
2998
-     */
2999
-    public function display_admin_list_table_page_with_no_sidebar()
3000
-    {
3001
-        $this->_display_admin_list_table_page();
3002
-    }
3003
-
3004
-
3005
-    /**
3006
-     * generates html wrapper for an admin_list_table page
3007
-     *
3008
-     * @param boolean $sidebar whether to display with sidebar or not.
3009
-     * @return void
3010
-     * @throws DomainException
3011
-     * @throws EE_Error
3012
-     */
3013
-    private function _display_admin_list_table_page($sidebar = false)
3014
-    {
3015
-        // setup search attributes
3016
-        $this->_set_search_attributes();
3017
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
3018
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3019
-        $this->_template_args['table_url']        = $this->request->isAjax()
3020
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
3021
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
3022
-        $this->_template_args['list_table']       = $this->_list_table_object;
3023
-        $this->_template_args['current_route']    = $this->_req_action;
3024
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3025
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3026
-        if (! empty($ajax_sorting_callback)) {
3027
-            $sortable_list_table_form_fields = wp_nonce_field(
3028
-                $ajax_sorting_callback . '_nonce',
3029
-                $ajax_sorting_callback . '_nonce',
3030
-                false,
3031
-                false
3032
-            );
3033
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3034
-                                                . $this->page_slug
3035
-                                                . '" />';
3036
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3037
-                                                . $ajax_sorting_callback
3038
-                                                . '" />';
3039
-        } else {
3040
-            $sortable_list_table_form_fields = '';
3041
-        }
3042
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3043
-        $hidden_form_fields                                      =
3044
-            isset($this->_template_args['list_table_hidden_fields'])
3045
-                ? $this->_template_args['list_table_hidden_fields']
3046
-                : '';
3047
-        $nonce_ref                                               = $this->_req_action . '_nonce';
3048
-        $hidden_form_fields                                      .= '<input type="hidden" name="'
3049
-                                                                    . $nonce_ref
3050
-                                                                    . '" value="'
3051
-                                                                    . wp_create_nonce($nonce_ref)
3052
-                                                                    . '">';
3053
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3054
-        // display message about search results?
3055
-        $search = $this->request->getRequestParam('s');
3056
-        $this->_template_args['before_list_table'] .= ! empty($search)
3057
-            ? '<p class="ee-search-results">' . sprintf(
3058
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3059
-                trim($search, '%')
3060
-            ) . '</p>'
3061
-            : '';
3062
-        // filter before_list_table template arg
3063
-        $this->_template_args['before_list_table'] = apply_filters(
3064
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3065
-            $this->_template_args['before_list_table'],
3066
-            $this->page_slug,
3067
-            $this->request->requestParams(),
3068
-            $this->_req_action
3069
-        );
3070
-        // convert to array and filter again
3071
-        // arrays are easier to inject new items in a specific location,
3072
-        // but would not be backwards compatible, so we have to add a new filter
3073
-        $this->_template_args['before_list_table'] = implode(
3074
-            " \n",
3075
-            (array) apply_filters(
3076
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3077
-                (array) $this->_template_args['before_list_table'],
3078
-                $this->page_slug,
3079
-                $this->request->requestParams(),
3080
-                $this->_req_action
3081
-            )
3082
-        );
3083
-        // filter after_list_table template arg
3084
-        $this->_template_args['after_list_table'] = apply_filters(
3085
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3086
-            $this->_template_args['after_list_table'],
3087
-            $this->page_slug,
3088
-            $this->request->requestParams(),
3089
-            $this->_req_action
3090
-        );
3091
-        // convert to array and filter again
3092
-        // arrays are easier to inject new items in a specific location,
3093
-        // but would not be backwards compatible, so we have to add a new filter
3094
-        $this->_template_args['after_list_table']   = implode(
3095
-            " \n",
3096
-            (array) apply_filters(
3097
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3098
-                (array) $this->_template_args['after_list_table'],
3099
-                $this->page_slug,
3100
-                $this->request->requestParams(),
3101
-                $this->_req_action
3102
-            )
3103
-        );
3104
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3105
-            $template_path,
3106
-            $this->_template_args,
3107
-            true
3108
-        );
3109
-        // the final template wrapper
3110
-        if ($sidebar) {
3111
-            $this->display_admin_page_with_sidebar();
3112
-        } else {
3113
-            $this->display_admin_page_with_no_sidebar();
3114
-        }
3115
-    }
3116
-
3117
-
3118
-    /**
3119
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3120
-     * html string for the legend.
3121
-     * $items are expected in an array in the following format:
3122
-     * $legend_items = array(
3123
-     *        'item_id' => array(
3124
-     *            'icon' => 'http://url_to_icon_being_described.png',
3125
-     *            'desc' => esc_html__('localized description of item');
3126
-     *        )
3127
-     * );
3128
-     *
3129
-     * @param array $items see above for format of array
3130
-     * @return string html string of legend
3131
-     * @throws DomainException
3132
-     */
3133
-    protected function _display_legend($items)
3134
-    {
3135
-        $this->_template_args['items'] = apply_filters(
3136
-            'FHEE__EE_Admin_Page___display_legend__items',
3137
-            (array) $items,
3138
-            $this
3139
-        );
3140
-        return EEH_Template::display_template(
3141
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3142
-            $this->_template_args,
3143
-            true
3144
-        );
3145
-    }
3146
-
3147
-
3148
-    /**
3149
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3150
-     * The returned json object is created from an array in the following format:
3151
-     * array(
3152
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3153
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3154
-     *  'notices' => '', // - contains any EE_Error formatted notices
3155
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3156
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3157
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3158
-     *  that might be included in here)
3159
-     * )
3160
-     * The json object is populated by whatever is set in the $_template_args property.
3161
-     *
3162
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3163
-     *                                 instead of displayed.
3164
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3165
-     * @return void
3166
-     * @throws EE_Error
3167
-     */
3168
-    protected function _return_json($sticky_notices = false, $notices_arguments = [])
3169
-    {
3170
-        // make sure any EE_Error notices have been handled.
3171
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3172
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3173
-        unset($this->_template_args['data']);
3174
-        $json = [
3175
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3176
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3177
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3178
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3179
-            'notices'   => EE_Error::get_notices(),
3180
-            'content'   => isset($this->_template_args['admin_page_content'])
3181
-                ? $this->_template_args['admin_page_content'] : '',
3182
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3183
-            'isEEajax'  => true
3184
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3185
-        ];
3186
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3187
-        if (null === error_get_last() || ! headers_sent()) {
3188
-            header('Content-Type: application/json; charset=UTF-8');
3189
-        }
3190
-        echo wp_json_encode($json);
3191
-        exit();
3192
-    }
3193
-
3194
-
3195
-    /**
3196
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3197
-     *
3198
-     * @return void
3199
-     * @throws EE_Error
3200
-     */
3201
-    public function return_json()
3202
-    {
3203
-        if ($this->request->isAjax()) {
3204
-            $this->_return_json();
3205
-        } else {
3206
-            throw new EE_Error(
3207
-                sprintf(
3208
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3209
-                    __FUNCTION__
3210
-                )
3211
-            );
3212
-        }
3213
-    }
3214
-
3215
-
3216
-    /**
3217
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3218
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3219
-     *
3220
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3221
-     */
3222
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3223
-    {
3224
-        $this->_hook_obj = $hook_obj;
3225
-    }
3226
-
3227
-
3228
-    /**
3229
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3230
-     *
3231
-     * @param boolean $about whether to use the special about page wrapper or default.
3232
-     * @return void
3233
-     * @throws DomainException
3234
-     * @throws EE_Error
3235
-     */
3236
-    public function admin_page_wrapper($about = false)
3237
-    {
3238
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3239
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3240
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3241
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3242
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3243
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3244
-            isset($this->_template_args['before_admin_page_content'])
3245
-                ? $this->_template_args['before_admin_page_content']
3246
-                : ''
3247
-        );
3248
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3249
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3250
-            isset($this->_template_args['after_admin_page_content'])
3251
-                ? $this->_template_args['after_admin_page_content']
3252
-                : ''
3253
-        );
3254
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3255
-        // load settings page wrapper template
3256
-        $template_path = ! $this->request->isAjax()
3257
-            ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3258
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
3259
-        // about page?
3260
-        $template_path = $about
3261
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3262
-            : $template_path;
3263
-        if ($this->request->isAjax()) {
3264
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3265
-                $template_path,
3266
-                $this->_template_args,
3267
-                true
3268
-            );
3269
-            $this->_return_json();
3270
-        } else {
3271
-            EEH_Template::display_template($template_path, $this->_template_args);
3272
-        }
3273
-    }
3274
-
3275
-
3276
-    /**
3277
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3278
-     *
3279
-     * @return string html
3280
-     * @throws EE_Error
3281
-     */
3282
-    protected function _get_main_nav_tabs()
3283
-    {
3284
-        // let's generate the html using the EEH_Tabbed_Content helper.
3285
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3286
-        // (rather than setting in the page_routes array)
3287
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3288
-    }
3289
-
3290
-
3291
-    /**
3292
-     *        sort nav tabs
3293
-     *
3294
-     * @param $a
3295
-     * @param $b
3296
-     * @return int
3297
-     */
3298
-    private function _sort_nav_tabs($a, $b)
3299
-    {
3300
-        if ($a['order'] === $b['order']) {
3301
-            return 0;
3302
-        }
3303
-        return ($a['order'] < $b['order']) ? -1 : 1;
3304
-    }
3305
-
3306
-
3307
-    /**
3308
-     *    generates HTML for the forms used on admin pages
3309
-     *
3310
-     * @param array  $input_vars   - array of input field details
3311
-     * @param string $generator    (options are 'string' or 'array', basically use this to indicate which generator to
3312
-     *                             use)
3313
-     * @param bool   $id
3314
-     * @return string
3315
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3316
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3317
-     */
3318
-    protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3319
-    {
3320
-        return $generator === 'string'
3321
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3322
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3323
-    }
3324
-
3325
-
3326
-    /**
3327
-     * generates the "Save" and "Save & Close" buttons for edit forms
3328
-     *
3329
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3330
-     *                                   Close" button.
3331
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3332
-     *                                   'Save', [1] => 'save & close')
3333
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3334
-     *                                   via the "name" value in the button).  We can also use this to just dump
3335
-     *                                   default actions by submitting some other value.
3336
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3337
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3338
-     *                                   close (normal form handling).
3339
-     */
3340
-    protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3341
-    {
3342
-        // make sure $text and $actions are in an array
3343
-        $text          = (array) $text;
3344
-        $actions       = (array) $actions;
3345
-        $referrer_url  = empty($referrer)
3346
-            ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3347
-              . $this->request->getServerParam('REQUEST_URI')
3348
-              . '" />'
3349
-            : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3350
-              . $referrer
3351
-              . '" />';
3352
-        $button_text   = ! empty($text)
3353
-            ? $text
3354
-            : [
3355
-                esc_html__('Save', 'event_espresso'),
3356
-                esc_html__('Save and Close', 'event_espresso'),
3357
-            ];
3358
-        $default_names = ['save', 'save_and_close'];
3359
-        // add in a hidden index for the current page (so save and close redirects properly)
3360
-        $this->_template_args['save_buttons'] = $referrer_url;
3361
-        foreach ($button_text as $key => $button) {
3362
-            $ref                                  = $default_names[ $key ];
3363
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3364
-                                                     . $ref
3365
-                                                     . '" value="'
3366
-                                                     . $button
3367
-                                                     . '" name="'
3368
-                                                     . (! empty($actions) ? $actions[ $key ] : $ref)
3369
-                                                     . '" id="'
3370
-                                                     . $this->_current_view . '_' . $ref
3371
-                                                     . '" />';
3372
-            if (! $both) {
3373
-                break;
3374
-            }
3375
-        }
3376
-    }
3377
-
3378
-
3379
-    /**
3380
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3381
-     *
3382
-     * @param string $route
3383
-     * @param array  $additional_hidden_fields
3384
-     * @see   $this->_set_add_edit_form_tags() for details on params
3385
-     * @since 4.6.0
3386
-     */
3387
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3388
-    {
3389
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3390
-    }
3391
-
3392
-
3393
-    /**
3394
-     * set form open and close tags on add/edit pages.
3395
-     *
3396
-     * @param string $route                    the route you want the form to direct to
3397
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3398
-     * @return void
3399
-     */
3400
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3401
-    {
3402
-        if (empty($route)) {
3403
-            $user_msg = esc_html__(
3404
-                'An error occurred. No action was set for this page\'s form.',
3405
-                'event_espresso'
3406
-            );
3407
-            $dev_msg  = $user_msg . "\n"
3408
-                        . sprintf(
3409
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3410
-                            __FUNCTION__,
3411
-                            __CLASS__
3412
-                        );
3413
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3414
-        }
3415
-        // open form
3416
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3417
-                                                             . $this->_admin_base_url
3418
-                                                             . '" id="'
3419
-                                                             . $route
3420
-                                                             . '_event_form" >';
3421
-        // add nonce
3422
-        $nonce                                             =
3423
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3424
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3425
-        // add REQUIRED form action
3426
-        $hidden_fields = [
3427
-            'action' => ['type' => 'hidden', 'value' => $route],
3428
-        ];
3429
-        // merge arrays
3430
-        $hidden_fields = is_array($additional_hidden_fields)
3431
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3432
-            : $hidden_fields;
3433
-        // generate form fields
3434
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3435
-        // add fields to form
3436
-        foreach ((array) $form_fields as $field_name => $form_field) {
3437
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3438
-        }
3439
-        // close form
3440
-        $this->_template_args['after_admin_page_content'] = '</form>';
3441
-    }
3442
-
3443
-
3444
-    /**
3445
-     * Public Wrapper for _redirect_after_action() method since its
3446
-     * discovered it would be useful for external code to have access.
3447
-     *
3448
-     * @param bool   $success
3449
-     * @param string $what
3450
-     * @param string $action_desc
3451
-     * @param array  $query_args
3452
-     * @param bool   $override_overwrite
3453
-     * @throws EE_Error
3454
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3455
-     * @since 4.5.0
3456
-     */
3457
-    public function redirect_after_action(
3458
-        $success = false,
3459
-        $what = 'item',
3460
-        $action_desc = 'processed',
3461
-        $query_args = [],
3462
-        $override_overwrite = false
3463
-    ) {
3464
-        $this->_redirect_after_action(
3465
-            $success,
3466
-            $what,
3467
-            $action_desc,
3468
-            $query_args,
3469
-            $override_overwrite
3470
-        );
3471
-    }
3472
-
3473
-
3474
-    /**
3475
-     * Helper method for merging existing request data with the returned redirect url.
3476
-     *
3477
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3478
-     * filters are still applied.
3479
-     *
3480
-     * @param array $new_route_data
3481
-     * @return array
3482
-     */
3483
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3484
-    {
3485
-        foreach ($this->request->requestParams() as $ref => $value) {
3486
-            // unset nonces
3487
-            if (strpos($ref, 'nonce') !== false) {
3488
-                $this->request->unSetRequestParam($ref);
3489
-                continue;
3490
-            }
3491
-            // urlencode values.
3492
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3493
-            $this->request->setRequestParam($ref, $value);
3494
-        }
3495
-        return array_merge($this->request->requestParams(), $new_route_data);
3496
-    }
3497
-
3498
-
3499
-    /**
3500
-     *    _redirect_after_action
3501
-     *
3502
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3503
-     * @param string $what               - what the action was performed on
3504
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3505
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3506
-     *                                   action is completed
3507
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3508
-     *                                   override this so that they show.
3509
-     * @return void
3510
-     * @throws EE_Error
3511
-     */
3512
-    protected function _redirect_after_action(
3513
-        $success = 0,
3514
-        $what = 'item',
3515
-        $action_desc = 'processed',
3516
-        $query_args = [],
3517
-        $override_overwrite = false
3518
-    ) {
3519
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3520
-        // class name for actions/filters.
3521
-        $classname = get_class($this);
3522
-        // set redirect url.
3523
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3524
-        // otherwise we go with whatever is set as the _admin_base_url
3525
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3526
-        $notices      = EE_Error::get_notices(false);
3527
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3528
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3529
-            EE_Error::overwrite_success();
3530
-        }
3531
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3532
-            // how many records affected ? more than one record ? or just one ?
3533
-            if ($success > 1) {
3534
-                // set plural msg
3535
-                EE_Error::add_success(
3536
-                    sprintf(
3537
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3538
-                        $what,
3539
-                        $action_desc
3540
-                    ),
3541
-                    __FILE__,
3542
-                    __FUNCTION__,
3543
-                    __LINE__
3544
-                );
3545
-            } elseif ($success === 1) {
3546
-                // set singular msg
3547
-                EE_Error::add_success(
3548
-                    sprintf(
3549
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3550
-                        $what,
3551
-                        $action_desc
3552
-                    ),
3553
-                    __FILE__,
3554
-                    __FUNCTION__,
3555
-                    __LINE__
3556
-                );
3557
-            }
3558
-        }
3559
-        // check that $query_args isn't something crazy
3560
-        if (! is_array($query_args)) {
3561
-            $query_args = [];
3562
-        }
3563
-        /**
3564
-         * Allow injecting actions before the query_args are modified for possible different
3565
-         * redirections on save and close actions
3566
-         *
3567
-         * @param array $query_args       The original query_args array coming into the
3568
-         *                                method.
3569
-         * @since 4.2.0
3570
-         */
3571
-        do_action(
3572
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3573
-            $query_args
3574
-        );
3575
-        // calculate where we're going (if we have a "save and close" button pushed)
3576
-
3577
-        if (
3578
-            $this->request->requestParamIsSet('save_and_close')
3579
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3580
-        ) {
3581
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3582
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3583
-            // regenerate query args array from referrer URL
3584
-            parse_str($parsed_url['query'], $query_args);
3585
-            // correct page and action will be in the query args now
3586
-            $redirect_url = admin_url('admin.php');
3587
-        }
3588
-        // merge any default query_args set in _default_route_query_args property
3589
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3590
-            $args_to_merge = [];
3591
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3592
-                // is there a wp_referer array in our _default_route_query_args property?
3593
-                if ($query_param === 'wp_referer') {
3594
-                    $query_value = (array) $query_value;
3595
-                    foreach ($query_value as $reference => $value) {
3596
-                        if (strpos($reference, 'nonce') !== false) {
3597
-                            continue;
3598
-                        }
3599
-                        // finally we will override any arguments in the referer with
3600
-                        // what might be set on the _default_route_query_args array.
3601
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3602
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3603
-                        } else {
3604
-                            $args_to_merge[ $reference ] = urlencode($value);
3605
-                        }
3606
-                    }
3607
-                    continue;
3608
-                }
3609
-                $args_to_merge[ $query_param ] = $query_value;
3610
-            }
3611
-            // now let's merge these arguments but override with what was specifically sent in to the
3612
-            // redirect.
3613
-            $query_args = array_merge($args_to_merge, $query_args);
3614
-        }
3615
-        $this->_process_notices($query_args);
3616
-        // generate redirect url
3617
-        // if redirecting to anything other than the main page, add a nonce
3618
-        if (isset($query_args['action'])) {
3619
-            // manually generate wp_nonce and merge that with the query vars
3620
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3621
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3622
-        }
3623
-        // we're adding some hooks and filters in here for processing any things just before redirects
3624
-        // (example: an admin page has done an insert or update and we want to run something after that).
3625
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3626
-        $redirect_url = apply_filters(
3627
-            'FHEE_redirect_' . $classname . $this->_req_action,
3628
-            self::add_query_args_and_nonce($query_args, $redirect_url),
3629
-            $query_args
3630
-        );
3631
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3632
-        if ($this->request->isAjax()) {
3633
-            $default_data                    = [
3634
-                'close'        => true,
3635
-                'redirect_url' => $redirect_url,
3636
-                'where'        => 'main',
3637
-                'what'         => 'append',
3638
-            ];
3639
-            $this->_template_args['success'] = $success;
3640
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3641
-                $default_data,
3642
-                $this->_template_args['data']
3643
-            ) : $default_data;
3644
-            $this->_return_json();
3645
-        }
3646
-        wp_safe_redirect($redirect_url);
3647
-        exit();
3648
-    }
3649
-
3650
-
3651
-    /**
3652
-     * process any notices before redirecting (or returning ajax request)
3653
-     * This method sets the $this->_template_args['notices'] attribute;
3654
-     *
3655
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3656
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3657
-     *                                  page_routes haven't been defined yet.
3658
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3659
-     *                                  still save a transient for the notice.
3660
-     * @return void
3661
-     * @throws EE_Error
3662
-     */
3663
-    protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3664
-    {
3665
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3666
-        if ($this->request->isAjax()) {
3667
-            $notices = EE_Error::get_notices(false);
3668
-            if (empty($this->_template_args['success'])) {
3669
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3670
-            }
3671
-            if (empty($this->_template_args['errors'])) {
3672
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3673
-            }
3674
-            if (empty($this->_template_args['attention'])) {
3675
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3676
-            }
3677
-        }
3678
-        $this->_template_args['notices'] = EE_Error::get_notices();
3679
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3680
-        if (! $this->request->isAjax() || $sticky_notices) {
3681
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3682
-            $this->_add_transient(
3683
-                $route,
3684
-                $this->_template_args['notices'],
3685
-                true,
3686
-                $skip_route_verify
3687
-            );
3688
-        }
3689
-    }
3690
-
3691
-
3692
-    /**
3693
-     * get_action_link_or_button
3694
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3695
-     *
3696
-     * @param string $action        use this to indicate which action the url is generated with.
3697
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3698
-     *                              property.
3699
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3700
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3701
-     * @param string $base_url      If this is not provided
3702
-     *                              the _admin_base_url will be used as the default for the button base_url.
3703
-     *                              Otherwise this value will be used.
3704
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3705
-     * @return string
3706
-     * @throws InvalidArgumentException
3707
-     * @throws InvalidInterfaceException
3708
-     * @throws InvalidDataTypeException
3709
-     * @throws EE_Error
3710
-     */
3711
-    public function get_action_link_or_button(
3712
-        $action,
3713
-        $type = 'add',
3714
-        $extra_request = [],
3715
-        $class = 'button-primary',
3716
-        $base_url = '',
3717
-        $exclude_nonce = false
3718
-    ) {
3719
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3720
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3721
-            throw new EE_Error(
3722
-                sprintf(
3723
-                    esc_html__(
3724
-                        'There is no page route for given action for the button.  This action was given: %s',
3725
-                        'event_espresso'
3726
-                    ),
3727
-                    $action
3728
-                )
3729
-            );
3730
-        }
3731
-        if (! isset($this->_labels['buttons'][ $type ])) {
3732
-            throw new EE_Error(
3733
-                sprintf(
3734
-                    esc_html__(
3735
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3736
-                        'event_espresso'
3737
-                    ),
3738
-                    $type
3739
-                )
3740
-            );
3741
-        }
3742
-        // finally check user access for this button.
3743
-        $has_access = $this->check_user_access($action, true);
3744
-        if (! $has_access) {
3745
-            return '';
3746
-        }
3747
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3748
-        $query_args = [
3749
-            'action' => $action,
3750
-        ];
3751
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3752
-        if (! empty($extra_request)) {
3753
-            $query_args = array_merge($extra_request, $query_args);
3754
-        }
3755
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3756
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3757
-    }
3758
-
3759
-
3760
-    /**
3761
-     * _per_page_screen_option
3762
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3763
-     *
3764
-     * @return void
3765
-     * @throws InvalidArgumentException
3766
-     * @throws InvalidInterfaceException
3767
-     * @throws InvalidDataTypeException
3768
-     */
3769
-    protected function _per_page_screen_option()
3770
-    {
3771
-        $option = 'per_page';
3772
-        $args   = [
3773
-            'label'   => apply_filters(
3774
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3775
-                $this->_admin_page_title,
3776
-                $this
3777
-            ),
3778
-            'default' => (int) apply_filters(
3779
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3780
-                20
3781
-            ),
3782
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3783
-        ];
3784
-        // ONLY add the screen option if the user has access to it.
3785
-        if ($this->check_user_access($this->_current_view, true)) {
3786
-            add_screen_option($option, $args);
3787
-        }
3788
-    }
3789
-
3790
-
3791
-    /**
3792
-     * set_per_page_screen_option
3793
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3794
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3795
-     * admin_menu.
3796
-     *
3797
-     * @return void
3798
-     */
3799
-    private function _set_per_page_screen_options()
3800
-    {
3801
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3802
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3803
-            if (! $user = wp_get_current_user()) {
3804
-                return;
3805
-            }
3806
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3807
-            if (! $option) {
3808
-                return;
3809
-            }
3810
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3811
-            $map_option = $option;
3812
-            $option     = str_replace('-', '_', $option);
3813
-            switch ($map_option) {
3814
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3815
-                    $max_value = apply_filters(
3816
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3817
-                        999,
3818
-                        $this->_current_page,
3819
-                        $this->_current_view
3820
-                    );
3821
-                    if ($value < 1) {
3822
-                        return;
3823
-                    }
3824
-                    $value = min($value, $max_value);
3825
-                    break;
3826
-                default:
3827
-                    $value = apply_filters(
3828
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3829
-                        false,
3830
-                        $option,
3831
-                        $value
3832
-                    );
3833
-                    if (false === $value) {
3834
-                        return;
3835
-                    }
3836
-                    break;
3837
-            }
3838
-            update_user_meta($user->ID, $option, $value);
3839
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3840
-            exit;
3841
-        }
3842
-    }
3843
-
3844
-
3845
-    /**
3846
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3847
-     *
3848
-     * @param array $data array that will be assigned to template args.
3849
-     */
3850
-    public function set_template_args($data)
3851
-    {
3852
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3853
-    }
3854
-
3855
-
3856
-    /**
3857
-     * This makes available the WP transient system for temporarily moving data between routes
3858
-     *
3859
-     * @param string $route             the route that should receive the transient
3860
-     * @param array  $data              the data that gets sent
3861
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3862
-     *                                  normal route transient.
3863
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3864
-     *                                  when we are adding a transient before page_routes have been defined.
3865
-     * @return void
3866
-     * @throws EE_Error
3867
-     */
3868
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3869
-    {
3870
-        $user_id = get_current_user_id();
3871
-        if (! $skip_route_verify) {
3872
-            $this->_verify_route($route);
3873
-        }
3874
-        // now let's set the string for what kind of transient we're setting
3875
-        $transient = $notices
3876
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3877
-            : 'rte_tx_' . $route . '_' . $user_id;
3878
-        $data      = $notices ? ['notices' => $data] : $data;
3879
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3880
-        $existing = is_multisite() && is_network_admin()
3881
-            ? get_site_transient($transient)
3882
-            : get_transient($transient);
3883
-        if ($existing) {
3884
-            $data = array_merge((array) $data, (array) $existing);
3885
-        }
3886
-        if (is_multisite() && is_network_admin()) {
3887
-            set_site_transient($transient, $data, 8);
3888
-        } else {
3889
-            set_transient($transient, $data, 8);
3890
-        }
3891
-    }
3892
-
3893
-
3894
-    /**
3895
-     * this retrieves the temporary transient that has been set for moving data between routes.
3896
-     *
3897
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3898
-     * @param string $route
3899
-     * @return mixed data
3900
-     */
3901
-    protected function _get_transient($notices = false, $route = '')
3902
-    {
3903
-        $user_id   = get_current_user_id();
3904
-        $route     = ! $route ? $this->_req_action : $route;
3905
-        $transient = $notices
3906
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3907
-            : 'rte_tx_' . $route . '_' . $user_id;
3908
-        $data      = is_multisite() && is_network_admin()
3909
-            ? get_site_transient($transient)
3910
-            : get_transient($transient);
3911
-        // delete transient after retrieval (just in case it hasn't expired);
3912
-        if (is_multisite() && is_network_admin()) {
3913
-            delete_site_transient($transient);
3914
-        } else {
3915
-            delete_transient($transient);
3916
-        }
3917
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3918
-    }
3919
-
3920
-
3921
-    /**
3922
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3923
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3924
-     * default route callback on the EE_Admin page you want it run.)
3925
-     *
3926
-     * @return void
3927
-     */
3928
-    protected function _transient_garbage_collection()
3929
-    {
3930
-        global $wpdb;
3931
-        // retrieve all existing transients
3932
-        $query =
3933
-            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3934
-        if ($results = $wpdb->get_results($query)) {
3935
-            foreach ($results as $result) {
3936
-                $transient = str_replace('_transient_', '', $result->option_name);
3937
-                get_transient($transient);
3938
-                if (is_multisite() && is_network_admin()) {
3939
-                    get_site_transient($transient);
3940
-                }
3941
-            }
3942
-        }
3943
-    }
3944
-
3945
-
3946
-    /**
3947
-     * get_view
3948
-     *
3949
-     * @return string content of _view property
3950
-     */
3951
-    public function get_view()
3952
-    {
3953
-        return $this->_view;
3954
-    }
3955
-
3956
-
3957
-    /**
3958
-     * getter for the protected $_views property
3959
-     *
3960
-     * @return array
3961
-     */
3962
-    public function get_views()
3963
-    {
3964
-        return $this->_views;
3965
-    }
3966
-
3967
-
3968
-    /**
3969
-     * get_current_page
3970
-     *
3971
-     * @return string _current_page property value
3972
-     */
3973
-    public function get_current_page()
3974
-    {
3975
-        return $this->_current_page;
3976
-    }
3977
-
3978
-
3979
-    /**
3980
-     * get_current_view
3981
-     *
3982
-     * @return string _current_view property value
3983
-     */
3984
-    public function get_current_view()
3985
-    {
3986
-        return $this->_current_view;
3987
-    }
3988
-
3989
-
3990
-    /**
3991
-     * get_current_screen
3992
-     *
3993
-     * @return object The current WP_Screen object
3994
-     */
3995
-    public function get_current_screen()
3996
-    {
3997
-        return $this->_current_screen;
3998
-    }
3999
-
4000
-
4001
-    /**
4002
-     * get_current_page_view_url
4003
-     *
4004
-     * @return string This returns the url for the current_page_view.
4005
-     */
4006
-    public function get_current_page_view_url()
4007
-    {
4008
-        return $this->_current_page_view_url;
4009
-    }
4010
-
4011
-
4012
-    /**
4013
-     * just returns the Request
4014
-     *
4015
-     * @return RequestInterface
4016
-     */
4017
-    public function get_request()
4018
-    {
4019
-        return $this->request;
4020
-    }
4021
-
4022
-
4023
-    /**
4024
-     * just returns the _req_data property
4025
-     *
4026
-     * @return array
4027
-     */
4028
-    public function get_request_data()
4029
-    {
4030
-        return $this->request->requestParams();
4031
-    }
4032
-
4033
-
4034
-    /**
4035
-     * returns the _req_data protected property
4036
-     *
4037
-     * @return string
4038
-     */
4039
-    public function get_req_action()
4040
-    {
4041
-        return $this->_req_action;
4042
-    }
4043
-
4044
-
4045
-    /**
4046
-     * @return bool  value of $_is_caf property
4047
-     */
4048
-    public function is_caf()
4049
-    {
4050
-        return $this->_is_caf;
4051
-    }
4052
-
4053
-
4054
-    /**
4055
-     * @return mixed
4056
-     */
4057
-    public function default_espresso_metaboxes()
4058
-    {
4059
-        return $this->_default_espresso_metaboxes;
4060
-    }
4061
-
4062
-
4063
-    /**
4064
-     * @return mixed
4065
-     */
4066
-    public function admin_base_url()
4067
-    {
4068
-        return $this->_admin_base_url;
4069
-    }
4070
-
4071
-
4072
-    /**
4073
-     * @return mixed
4074
-     */
4075
-    public function wp_page_slug()
4076
-    {
4077
-        return $this->_wp_page_slug;
4078
-    }
4079
-
4080
-
4081
-    /**
4082
-     * updates  espresso configuration settings
4083
-     *
4084
-     * @param string                   $tab
4085
-     * @param EE_Config_Base|EE_Config $config
4086
-     * @param string                   $file file where error occurred
4087
-     * @param string                   $func function  where error occurred
4088
-     * @param string                   $line line no where error occurred
4089
-     * @return boolean
4090
-     */
4091
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4092
-    {
4093
-        // remove any options that are NOT going to be saved with the config settings.
4094
-        if (isset($config->core->ee_ueip_optin)) {
4095
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4096
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4097
-            update_option('ee_ueip_has_notified', true);
4098
-        }
4099
-        // and save it (note we're also doing the network save here)
4100
-        $net_saved    = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4101
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4102
-        if ($config_saved && $net_saved) {
4103
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4104
-            return true;
4105
-        }
4106
-        EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4107
-        return false;
4108
-    }
4109
-
4110
-
4111
-    /**
4112
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4113
-     *
4114
-     * @return array
4115
-     */
4116
-    public function get_yes_no_values()
4117
-    {
4118
-        return $this->_yes_no_values;
4119
-    }
4120
-
4121
-
4122
-    protected function _get_dir()
4123
-    {
4124
-        $reflector = new ReflectionClass(get_class($this));
4125
-        return dirname($reflector->getFileName());
4126
-    }
4127
-
4128
-
4129
-    /**
4130
-     * A helper for getting a "next link".
4131
-     *
4132
-     * @param string $url   The url to link to
4133
-     * @param string $class The class to use.
4134
-     * @return string
4135
-     */
4136
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4137
-    {
4138
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4139
-    }
4140
-
4141
-
4142
-    /**
4143
-     * A helper for getting a "previous link".
4144
-     *
4145
-     * @param string $url   The url to link to
4146
-     * @param string $class The class to use.
4147
-     * @return string
4148
-     */
4149
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4150
-    {
4151
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4152
-    }
4153
-
4154
-
4155
-
4156
-
4157
-
4158
-
4159
-
4160
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4161
-
4162
-
4163
-    /**
4164
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4165
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4166
-     * _req_data array.
4167
-     *
4168
-     * @return bool success/fail
4169
-     * @throws EE_Error
4170
-     * @throws InvalidArgumentException
4171
-     * @throws ReflectionException
4172
-     * @throws InvalidDataTypeException
4173
-     * @throws InvalidInterfaceException
4174
-     */
4175
-    protected function _process_resend_registration()
4176
-    {
4177
-        $this->_template_args['success'] = EED_Messages::process_resend($this->request->requestParams());
4178
-        do_action(
4179
-            'AHEE__EE_Admin_Page___process_resend_registration',
4180
-            $this->_template_args['success'],
4181
-            $this->request->requestParams()
4182
-        );
4183
-        return $this->_template_args['success'];
4184
-    }
4185
-
4186
-
4187
-    /**
4188
-     * This automatically processes any payment message notifications when manual payment has been applied.
4189
-     *
4190
-     * @param EE_Payment $payment
4191
-     * @return bool success/fail
4192
-     */
4193
-    protected function _process_payment_notification(EE_Payment $payment)
4194
-    {
4195
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4196
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4197
-        $this->_template_args['success'] = apply_filters(
4198
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4199
-            false,
4200
-            $payment
4201
-        );
4202
-        return $this->_template_args['success'];
4203
-    }
2764
+	}
2765
+
2766
+
2767
+	/**
2768
+	 * facade for add_meta_box
2769
+	 *
2770
+	 * @param string  $action        where the metabox get's displayed
2771
+	 * @param string  $title         Title of Metabox (output in metabox header)
2772
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2773
+	 *                               instead of the one created in here.
2774
+	 * @param array   $callback_args an array of args supplied for the metabox
2775
+	 * @param string  $column        what metabox column
2776
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2777
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2778
+	 *                               created but just set our own callback for wp's add_meta_box.
2779
+	 * @throws DomainException
2780
+	 */
2781
+	public function _add_admin_page_meta_box(
2782
+		$action,
2783
+		$title,
2784
+		$callback,
2785
+		$callback_args,
2786
+		$column = 'normal',
2787
+		$priority = 'high',
2788
+		$create_func = true
2789
+	) {
2790
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2791
+		// if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2792
+		if (empty($callback_args) && $create_func) {
2793
+			$callback_args = [
2794
+				'template_path' => $this->_template_path,
2795
+				'template_args' => $this->_template_args,
2796
+			];
2797
+		}
2798
+		// if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2799
+		$call_back_func = $create_func
2800
+			? function ($post, $metabox) {
2801
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2802
+				echo EEH_Template::display_template(
2803
+					$metabox['args']['template_path'],
2804
+					$metabox['args']['template_args'],
2805
+					true
2806
+				);
2807
+			}
2808
+			: $callback;
2809
+		add_meta_box(
2810
+			str_replace('_', '-', $action) . '-mbox',
2811
+			$title,
2812
+			$call_back_func,
2813
+			$this->_wp_page_slug,
2814
+			$column,
2815
+			$priority,
2816
+			$callback_args
2817
+		);
2818
+	}
2819
+
2820
+
2821
+	/**
2822
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2823
+	 *
2824
+	 * @throws DomainException
2825
+	 * @throws EE_Error
2826
+	 */
2827
+	public function display_admin_page_with_metabox_columns()
2828
+	{
2829
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2830
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2831
+			$this->_column_template_path,
2832
+			$this->_template_args,
2833
+			true
2834
+		);
2835
+		// the final wrapper
2836
+		$this->admin_page_wrapper();
2837
+	}
2838
+
2839
+
2840
+	/**
2841
+	 * generates  HTML wrapper for an admin details page
2842
+	 *
2843
+	 * @return void
2844
+	 * @throws EE_Error
2845
+	 * @throws DomainException
2846
+	 */
2847
+	public function display_admin_page_with_sidebar()
2848
+	{
2849
+		$this->_display_admin_page(true);
2850
+	}
2851
+
2852
+
2853
+	/**
2854
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2855
+	 *
2856
+	 * @return void
2857
+	 * @throws EE_Error
2858
+	 * @throws DomainException
2859
+	 */
2860
+	public function display_admin_page_with_no_sidebar()
2861
+	{
2862
+		$this->_display_admin_page();
2863
+	}
2864
+
2865
+
2866
+	/**
2867
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2868
+	 *
2869
+	 * @return void
2870
+	 * @throws EE_Error
2871
+	 * @throws DomainException
2872
+	 */
2873
+	public function display_about_admin_page()
2874
+	{
2875
+		$this->_display_admin_page(false, true);
2876
+	}
2877
+
2878
+
2879
+	/**
2880
+	 * display_admin_page
2881
+	 * contains the code for actually displaying an admin page
2882
+	 *
2883
+	 * @param boolean $sidebar true with sidebar, false without
2884
+	 * @param boolean $about   use the about_admin_wrapper instead of the default.
2885
+	 * @return void
2886
+	 * @throws DomainException
2887
+	 * @throws EE_Error
2888
+	 */
2889
+	private function _display_admin_page($sidebar = false, $about = false)
2890
+	{
2891
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2892
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2893
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2894
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2895
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2896
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2897
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2898
+			? 'poststuff'
2899
+			: 'espresso-default-admin';
2900
+		$template_path                                     = $sidebar
2901
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2902
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2903
+		if ($this->request->isAjax()) {
2904
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2905
+		}
2906
+		$template_path                                     = ! empty($this->_column_template_path)
2907
+			? $this->_column_template_path : $template_path;
2908
+		$this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2909
+			? $this->_template_args['admin_page_content']
2910
+			: '';
2911
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2912
+			? $this->_template_args['before_admin_page_content']
2913
+			: '';
2914
+		$this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2915
+			? $this->_template_args['after_admin_page_content']
2916
+			: '';
2917
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2918
+			$template_path,
2919
+			$this->_template_args,
2920
+			true
2921
+		);
2922
+		// the final template wrapper
2923
+		$this->admin_page_wrapper($about);
2924
+	}
2925
+
2926
+
2927
+	/**
2928
+	 * This is used to display caf preview pages.
2929
+	 *
2930
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2931
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2932
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2933
+	 * @return void
2934
+	 * @throws DomainException
2935
+	 * @throws EE_Error
2936
+	 * @throws InvalidArgumentException
2937
+	 * @throws InvalidDataTypeException
2938
+	 * @throws InvalidInterfaceException
2939
+	 * @since 4.3.2
2940
+	 */
2941
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2942
+	{
2943
+		// let's generate a default preview action button if there isn't one already present.
2944
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2945
+			'Upgrade to Event Espresso 4 Right Now',
2946
+			'event_espresso'
2947
+		);
2948
+		$buy_now_url                                   = add_query_arg(
2949
+			[
2950
+				'ee_ver'       => 'ee4',
2951
+				'utm_source'   => 'ee4_plugin_admin',
2952
+				'utm_medium'   => 'link',
2953
+				'utm_campaign' => $utm_campaign_source,
2954
+				'utm_content'  => 'buy_now_button',
2955
+			],
2956
+			'https://eventespresso.com/pricing/'
2957
+		);
2958
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2959
+			? $this->get_action_link_or_button(
2960
+				'',
2961
+				'buy_now',
2962
+				[],
2963
+				'button-primary button-large',
2964
+				esc_url_raw($buy_now_url),
2965
+				true
2966
+			)
2967
+			: $this->_template_args['preview_action_button'];
2968
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2969
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2970
+			$this->_template_args,
2971
+			true
2972
+		);
2973
+		$this->_display_admin_page($display_sidebar);
2974
+	}
2975
+
2976
+
2977
+	/**
2978
+	 * display_admin_list_table_page_with_sidebar
2979
+	 * generates HTML wrapper for an admin_page with list_table
2980
+	 *
2981
+	 * @return void
2982
+	 * @throws EE_Error
2983
+	 * @throws DomainException
2984
+	 */
2985
+	public function display_admin_list_table_page_with_sidebar()
2986
+	{
2987
+		$this->_display_admin_list_table_page(true);
2988
+	}
2989
+
2990
+
2991
+	/**
2992
+	 * display_admin_list_table_page_with_no_sidebar
2993
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2994
+	 *
2995
+	 * @return void
2996
+	 * @throws EE_Error
2997
+	 * @throws DomainException
2998
+	 */
2999
+	public function display_admin_list_table_page_with_no_sidebar()
3000
+	{
3001
+		$this->_display_admin_list_table_page();
3002
+	}
3003
+
3004
+
3005
+	/**
3006
+	 * generates html wrapper for an admin_list_table page
3007
+	 *
3008
+	 * @param boolean $sidebar whether to display with sidebar or not.
3009
+	 * @return void
3010
+	 * @throws DomainException
3011
+	 * @throws EE_Error
3012
+	 */
3013
+	private function _display_admin_list_table_page($sidebar = false)
3014
+	{
3015
+		// setup search attributes
3016
+		$this->_set_search_attributes();
3017
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
3018
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3019
+		$this->_template_args['table_url']        = $this->request->isAjax()
3020
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
3021
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
3022
+		$this->_template_args['list_table']       = $this->_list_table_object;
3023
+		$this->_template_args['current_route']    = $this->_req_action;
3024
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3025
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3026
+		if (! empty($ajax_sorting_callback)) {
3027
+			$sortable_list_table_form_fields = wp_nonce_field(
3028
+				$ajax_sorting_callback . '_nonce',
3029
+				$ajax_sorting_callback . '_nonce',
3030
+				false,
3031
+				false
3032
+			);
3033
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3034
+												. $this->page_slug
3035
+												. '" />';
3036
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3037
+												. $ajax_sorting_callback
3038
+												. '" />';
3039
+		} else {
3040
+			$sortable_list_table_form_fields = '';
3041
+		}
3042
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3043
+		$hidden_form_fields                                      =
3044
+			isset($this->_template_args['list_table_hidden_fields'])
3045
+				? $this->_template_args['list_table_hidden_fields']
3046
+				: '';
3047
+		$nonce_ref                                               = $this->_req_action . '_nonce';
3048
+		$hidden_form_fields                                      .= '<input type="hidden" name="'
3049
+																	. $nonce_ref
3050
+																	. '" value="'
3051
+																	. wp_create_nonce($nonce_ref)
3052
+																	. '">';
3053
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3054
+		// display message about search results?
3055
+		$search = $this->request->getRequestParam('s');
3056
+		$this->_template_args['before_list_table'] .= ! empty($search)
3057
+			? '<p class="ee-search-results">' . sprintf(
3058
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3059
+				trim($search, '%')
3060
+			) . '</p>'
3061
+			: '';
3062
+		// filter before_list_table template arg
3063
+		$this->_template_args['before_list_table'] = apply_filters(
3064
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3065
+			$this->_template_args['before_list_table'],
3066
+			$this->page_slug,
3067
+			$this->request->requestParams(),
3068
+			$this->_req_action
3069
+		);
3070
+		// convert to array and filter again
3071
+		// arrays are easier to inject new items in a specific location,
3072
+		// but would not be backwards compatible, so we have to add a new filter
3073
+		$this->_template_args['before_list_table'] = implode(
3074
+			" \n",
3075
+			(array) apply_filters(
3076
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3077
+				(array) $this->_template_args['before_list_table'],
3078
+				$this->page_slug,
3079
+				$this->request->requestParams(),
3080
+				$this->_req_action
3081
+			)
3082
+		);
3083
+		// filter after_list_table template arg
3084
+		$this->_template_args['after_list_table'] = apply_filters(
3085
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3086
+			$this->_template_args['after_list_table'],
3087
+			$this->page_slug,
3088
+			$this->request->requestParams(),
3089
+			$this->_req_action
3090
+		);
3091
+		// convert to array and filter again
3092
+		// arrays are easier to inject new items in a specific location,
3093
+		// but would not be backwards compatible, so we have to add a new filter
3094
+		$this->_template_args['after_list_table']   = implode(
3095
+			" \n",
3096
+			(array) apply_filters(
3097
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3098
+				(array) $this->_template_args['after_list_table'],
3099
+				$this->page_slug,
3100
+				$this->request->requestParams(),
3101
+				$this->_req_action
3102
+			)
3103
+		);
3104
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3105
+			$template_path,
3106
+			$this->_template_args,
3107
+			true
3108
+		);
3109
+		// the final template wrapper
3110
+		if ($sidebar) {
3111
+			$this->display_admin_page_with_sidebar();
3112
+		} else {
3113
+			$this->display_admin_page_with_no_sidebar();
3114
+		}
3115
+	}
3116
+
3117
+
3118
+	/**
3119
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3120
+	 * html string for the legend.
3121
+	 * $items are expected in an array in the following format:
3122
+	 * $legend_items = array(
3123
+	 *        'item_id' => array(
3124
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3125
+	 *            'desc' => esc_html__('localized description of item');
3126
+	 *        )
3127
+	 * );
3128
+	 *
3129
+	 * @param array $items see above for format of array
3130
+	 * @return string html string of legend
3131
+	 * @throws DomainException
3132
+	 */
3133
+	protected function _display_legend($items)
3134
+	{
3135
+		$this->_template_args['items'] = apply_filters(
3136
+			'FHEE__EE_Admin_Page___display_legend__items',
3137
+			(array) $items,
3138
+			$this
3139
+		);
3140
+		return EEH_Template::display_template(
3141
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3142
+			$this->_template_args,
3143
+			true
3144
+		);
3145
+	}
3146
+
3147
+
3148
+	/**
3149
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3150
+	 * The returned json object is created from an array in the following format:
3151
+	 * array(
3152
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3153
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3154
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3155
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3156
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3157
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3158
+	 *  that might be included in here)
3159
+	 * )
3160
+	 * The json object is populated by whatever is set in the $_template_args property.
3161
+	 *
3162
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3163
+	 *                                 instead of displayed.
3164
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3165
+	 * @return void
3166
+	 * @throws EE_Error
3167
+	 */
3168
+	protected function _return_json($sticky_notices = false, $notices_arguments = [])
3169
+	{
3170
+		// make sure any EE_Error notices have been handled.
3171
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3172
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3173
+		unset($this->_template_args['data']);
3174
+		$json = [
3175
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3176
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3177
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3178
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3179
+			'notices'   => EE_Error::get_notices(),
3180
+			'content'   => isset($this->_template_args['admin_page_content'])
3181
+				? $this->_template_args['admin_page_content'] : '',
3182
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3183
+			'isEEajax'  => true
3184
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3185
+		];
3186
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3187
+		if (null === error_get_last() || ! headers_sent()) {
3188
+			header('Content-Type: application/json; charset=UTF-8');
3189
+		}
3190
+		echo wp_json_encode($json);
3191
+		exit();
3192
+	}
3193
+
3194
+
3195
+	/**
3196
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3197
+	 *
3198
+	 * @return void
3199
+	 * @throws EE_Error
3200
+	 */
3201
+	public function return_json()
3202
+	{
3203
+		if ($this->request->isAjax()) {
3204
+			$this->_return_json();
3205
+		} else {
3206
+			throw new EE_Error(
3207
+				sprintf(
3208
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3209
+					__FUNCTION__
3210
+				)
3211
+			);
3212
+		}
3213
+	}
3214
+
3215
+
3216
+	/**
3217
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3218
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3219
+	 *
3220
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3221
+	 */
3222
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3223
+	{
3224
+		$this->_hook_obj = $hook_obj;
3225
+	}
3226
+
3227
+
3228
+	/**
3229
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3230
+	 *
3231
+	 * @param boolean $about whether to use the special about page wrapper or default.
3232
+	 * @return void
3233
+	 * @throws DomainException
3234
+	 * @throws EE_Error
3235
+	 */
3236
+	public function admin_page_wrapper($about = false)
3237
+	{
3238
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3239
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3240
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3241
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3242
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3243
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3244
+			isset($this->_template_args['before_admin_page_content'])
3245
+				? $this->_template_args['before_admin_page_content']
3246
+				: ''
3247
+		);
3248
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3249
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3250
+			isset($this->_template_args['after_admin_page_content'])
3251
+				? $this->_template_args['after_admin_page_content']
3252
+				: ''
3253
+		);
3254
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3255
+		// load settings page wrapper template
3256
+		$template_path = ! $this->request->isAjax()
3257
+			? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3258
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
3259
+		// about page?
3260
+		$template_path = $about
3261
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3262
+			: $template_path;
3263
+		if ($this->request->isAjax()) {
3264
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3265
+				$template_path,
3266
+				$this->_template_args,
3267
+				true
3268
+			);
3269
+			$this->_return_json();
3270
+		} else {
3271
+			EEH_Template::display_template($template_path, $this->_template_args);
3272
+		}
3273
+	}
3274
+
3275
+
3276
+	/**
3277
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3278
+	 *
3279
+	 * @return string html
3280
+	 * @throws EE_Error
3281
+	 */
3282
+	protected function _get_main_nav_tabs()
3283
+	{
3284
+		// let's generate the html using the EEH_Tabbed_Content helper.
3285
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3286
+		// (rather than setting in the page_routes array)
3287
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3288
+	}
3289
+
3290
+
3291
+	/**
3292
+	 *        sort nav tabs
3293
+	 *
3294
+	 * @param $a
3295
+	 * @param $b
3296
+	 * @return int
3297
+	 */
3298
+	private function _sort_nav_tabs($a, $b)
3299
+	{
3300
+		if ($a['order'] === $b['order']) {
3301
+			return 0;
3302
+		}
3303
+		return ($a['order'] < $b['order']) ? -1 : 1;
3304
+	}
3305
+
3306
+
3307
+	/**
3308
+	 *    generates HTML for the forms used on admin pages
3309
+	 *
3310
+	 * @param array  $input_vars   - array of input field details
3311
+	 * @param string $generator    (options are 'string' or 'array', basically use this to indicate which generator to
3312
+	 *                             use)
3313
+	 * @param bool   $id
3314
+	 * @return string
3315
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3316
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3317
+	 */
3318
+	protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3319
+	{
3320
+		return $generator === 'string'
3321
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3322
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3323
+	}
3324
+
3325
+
3326
+	/**
3327
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3328
+	 *
3329
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3330
+	 *                                   Close" button.
3331
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3332
+	 *                                   'Save', [1] => 'save & close')
3333
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3334
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3335
+	 *                                   default actions by submitting some other value.
3336
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3337
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3338
+	 *                                   close (normal form handling).
3339
+	 */
3340
+	protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3341
+	{
3342
+		// make sure $text and $actions are in an array
3343
+		$text          = (array) $text;
3344
+		$actions       = (array) $actions;
3345
+		$referrer_url  = empty($referrer)
3346
+			? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3347
+			  . $this->request->getServerParam('REQUEST_URI')
3348
+			  . '" />'
3349
+			: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3350
+			  . $referrer
3351
+			  . '" />';
3352
+		$button_text   = ! empty($text)
3353
+			? $text
3354
+			: [
3355
+				esc_html__('Save', 'event_espresso'),
3356
+				esc_html__('Save and Close', 'event_espresso'),
3357
+			];
3358
+		$default_names = ['save', 'save_and_close'];
3359
+		// add in a hidden index for the current page (so save and close redirects properly)
3360
+		$this->_template_args['save_buttons'] = $referrer_url;
3361
+		foreach ($button_text as $key => $button) {
3362
+			$ref                                  = $default_names[ $key ];
3363
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3364
+													 . $ref
3365
+													 . '" value="'
3366
+													 . $button
3367
+													 . '" name="'
3368
+													 . (! empty($actions) ? $actions[ $key ] : $ref)
3369
+													 . '" id="'
3370
+													 . $this->_current_view . '_' . $ref
3371
+													 . '" />';
3372
+			if (! $both) {
3373
+				break;
3374
+			}
3375
+		}
3376
+	}
3377
+
3378
+
3379
+	/**
3380
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3381
+	 *
3382
+	 * @param string $route
3383
+	 * @param array  $additional_hidden_fields
3384
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3385
+	 * @since 4.6.0
3386
+	 */
3387
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3388
+	{
3389
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3390
+	}
3391
+
3392
+
3393
+	/**
3394
+	 * set form open and close tags on add/edit pages.
3395
+	 *
3396
+	 * @param string $route                    the route you want the form to direct to
3397
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3398
+	 * @return void
3399
+	 */
3400
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3401
+	{
3402
+		if (empty($route)) {
3403
+			$user_msg = esc_html__(
3404
+				'An error occurred. No action was set for this page\'s form.',
3405
+				'event_espresso'
3406
+			);
3407
+			$dev_msg  = $user_msg . "\n"
3408
+						. sprintf(
3409
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3410
+							__FUNCTION__,
3411
+							__CLASS__
3412
+						);
3413
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3414
+		}
3415
+		// open form
3416
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3417
+															 . $this->_admin_base_url
3418
+															 . '" id="'
3419
+															 . $route
3420
+															 . '_event_form" >';
3421
+		// add nonce
3422
+		$nonce                                             =
3423
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3424
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3425
+		// add REQUIRED form action
3426
+		$hidden_fields = [
3427
+			'action' => ['type' => 'hidden', 'value' => $route],
3428
+		];
3429
+		// merge arrays
3430
+		$hidden_fields = is_array($additional_hidden_fields)
3431
+			? array_merge($hidden_fields, $additional_hidden_fields)
3432
+			: $hidden_fields;
3433
+		// generate form fields
3434
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3435
+		// add fields to form
3436
+		foreach ((array) $form_fields as $field_name => $form_field) {
3437
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3438
+		}
3439
+		// close form
3440
+		$this->_template_args['after_admin_page_content'] = '</form>';
3441
+	}
3442
+
3443
+
3444
+	/**
3445
+	 * Public Wrapper for _redirect_after_action() method since its
3446
+	 * discovered it would be useful for external code to have access.
3447
+	 *
3448
+	 * @param bool   $success
3449
+	 * @param string $what
3450
+	 * @param string $action_desc
3451
+	 * @param array  $query_args
3452
+	 * @param bool   $override_overwrite
3453
+	 * @throws EE_Error
3454
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3455
+	 * @since 4.5.0
3456
+	 */
3457
+	public function redirect_after_action(
3458
+		$success = false,
3459
+		$what = 'item',
3460
+		$action_desc = 'processed',
3461
+		$query_args = [],
3462
+		$override_overwrite = false
3463
+	) {
3464
+		$this->_redirect_after_action(
3465
+			$success,
3466
+			$what,
3467
+			$action_desc,
3468
+			$query_args,
3469
+			$override_overwrite
3470
+		);
3471
+	}
3472
+
3473
+
3474
+	/**
3475
+	 * Helper method for merging existing request data with the returned redirect url.
3476
+	 *
3477
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3478
+	 * filters are still applied.
3479
+	 *
3480
+	 * @param array $new_route_data
3481
+	 * @return array
3482
+	 */
3483
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3484
+	{
3485
+		foreach ($this->request->requestParams() as $ref => $value) {
3486
+			// unset nonces
3487
+			if (strpos($ref, 'nonce') !== false) {
3488
+				$this->request->unSetRequestParam($ref);
3489
+				continue;
3490
+			}
3491
+			// urlencode values.
3492
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3493
+			$this->request->setRequestParam($ref, $value);
3494
+		}
3495
+		return array_merge($this->request->requestParams(), $new_route_data);
3496
+	}
3497
+
3498
+
3499
+	/**
3500
+	 *    _redirect_after_action
3501
+	 *
3502
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3503
+	 * @param string $what               - what the action was performed on
3504
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3505
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3506
+	 *                                   action is completed
3507
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3508
+	 *                                   override this so that they show.
3509
+	 * @return void
3510
+	 * @throws EE_Error
3511
+	 */
3512
+	protected function _redirect_after_action(
3513
+		$success = 0,
3514
+		$what = 'item',
3515
+		$action_desc = 'processed',
3516
+		$query_args = [],
3517
+		$override_overwrite = false
3518
+	) {
3519
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3520
+		// class name for actions/filters.
3521
+		$classname = get_class($this);
3522
+		// set redirect url.
3523
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3524
+		// otherwise we go with whatever is set as the _admin_base_url
3525
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3526
+		$notices      = EE_Error::get_notices(false);
3527
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3528
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3529
+			EE_Error::overwrite_success();
3530
+		}
3531
+		if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3532
+			// how many records affected ? more than one record ? or just one ?
3533
+			if ($success > 1) {
3534
+				// set plural msg
3535
+				EE_Error::add_success(
3536
+					sprintf(
3537
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3538
+						$what,
3539
+						$action_desc
3540
+					),
3541
+					__FILE__,
3542
+					__FUNCTION__,
3543
+					__LINE__
3544
+				);
3545
+			} elseif ($success === 1) {
3546
+				// set singular msg
3547
+				EE_Error::add_success(
3548
+					sprintf(
3549
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3550
+						$what,
3551
+						$action_desc
3552
+					),
3553
+					__FILE__,
3554
+					__FUNCTION__,
3555
+					__LINE__
3556
+				);
3557
+			}
3558
+		}
3559
+		// check that $query_args isn't something crazy
3560
+		if (! is_array($query_args)) {
3561
+			$query_args = [];
3562
+		}
3563
+		/**
3564
+		 * Allow injecting actions before the query_args are modified for possible different
3565
+		 * redirections on save and close actions
3566
+		 *
3567
+		 * @param array $query_args       The original query_args array coming into the
3568
+		 *                                method.
3569
+		 * @since 4.2.0
3570
+		 */
3571
+		do_action(
3572
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3573
+			$query_args
3574
+		);
3575
+		// calculate where we're going (if we have a "save and close" button pushed)
3576
+
3577
+		if (
3578
+			$this->request->requestParamIsSet('save_and_close')
3579
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3580
+		) {
3581
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3582
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3583
+			// regenerate query args array from referrer URL
3584
+			parse_str($parsed_url['query'], $query_args);
3585
+			// correct page and action will be in the query args now
3586
+			$redirect_url = admin_url('admin.php');
3587
+		}
3588
+		// merge any default query_args set in _default_route_query_args property
3589
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3590
+			$args_to_merge = [];
3591
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3592
+				// is there a wp_referer array in our _default_route_query_args property?
3593
+				if ($query_param === 'wp_referer') {
3594
+					$query_value = (array) $query_value;
3595
+					foreach ($query_value as $reference => $value) {
3596
+						if (strpos($reference, 'nonce') !== false) {
3597
+							continue;
3598
+						}
3599
+						// finally we will override any arguments in the referer with
3600
+						// what might be set on the _default_route_query_args array.
3601
+						if (isset($this->_default_route_query_args[ $reference ])) {
3602
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3603
+						} else {
3604
+							$args_to_merge[ $reference ] = urlencode($value);
3605
+						}
3606
+					}
3607
+					continue;
3608
+				}
3609
+				$args_to_merge[ $query_param ] = $query_value;
3610
+			}
3611
+			// now let's merge these arguments but override with what was specifically sent in to the
3612
+			// redirect.
3613
+			$query_args = array_merge($args_to_merge, $query_args);
3614
+		}
3615
+		$this->_process_notices($query_args);
3616
+		// generate redirect url
3617
+		// if redirecting to anything other than the main page, add a nonce
3618
+		if (isset($query_args['action'])) {
3619
+			// manually generate wp_nonce and merge that with the query vars
3620
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3621
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3622
+		}
3623
+		// we're adding some hooks and filters in here for processing any things just before redirects
3624
+		// (example: an admin page has done an insert or update and we want to run something after that).
3625
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3626
+		$redirect_url = apply_filters(
3627
+			'FHEE_redirect_' . $classname . $this->_req_action,
3628
+			self::add_query_args_and_nonce($query_args, $redirect_url),
3629
+			$query_args
3630
+		);
3631
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3632
+		if ($this->request->isAjax()) {
3633
+			$default_data                    = [
3634
+				'close'        => true,
3635
+				'redirect_url' => $redirect_url,
3636
+				'where'        => 'main',
3637
+				'what'         => 'append',
3638
+			];
3639
+			$this->_template_args['success'] = $success;
3640
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3641
+				$default_data,
3642
+				$this->_template_args['data']
3643
+			) : $default_data;
3644
+			$this->_return_json();
3645
+		}
3646
+		wp_safe_redirect($redirect_url);
3647
+		exit();
3648
+	}
3649
+
3650
+
3651
+	/**
3652
+	 * process any notices before redirecting (or returning ajax request)
3653
+	 * This method sets the $this->_template_args['notices'] attribute;
3654
+	 *
3655
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3656
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3657
+	 *                                  page_routes haven't been defined yet.
3658
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3659
+	 *                                  still save a transient for the notice.
3660
+	 * @return void
3661
+	 * @throws EE_Error
3662
+	 */
3663
+	protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3664
+	{
3665
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3666
+		if ($this->request->isAjax()) {
3667
+			$notices = EE_Error::get_notices(false);
3668
+			if (empty($this->_template_args['success'])) {
3669
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3670
+			}
3671
+			if (empty($this->_template_args['errors'])) {
3672
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3673
+			}
3674
+			if (empty($this->_template_args['attention'])) {
3675
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3676
+			}
3677
+		}
3678
+		$this->_template_args['notices'] = EE_Error::get_notices();
3679
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3680
+		if (! $this->request->isAjax() || $sticky_notices) {
3681
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3682
+			$this->_add_transient(
3683
+				$route,
3684
+				$this->_template_args['notices'],
3685
+				true,
3686
+				$skip_route_verify
3687
+			);
3688
+		}
3689
+	}
3690
+
3691
+
3692
+	/**
3693
+	 * get_action_link_or_button
3694
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3695
+	 *
3696
+	 * @param string $action        use this to indicate which action the url is generated with.
3697
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3698
+	 *                              property.
3699
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3700
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3701
+	 * @param string $base_url      If this is not provided
3702
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3703
+	 *                              Otherwise this value will be used.
3704
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3705
+	 * @return string
3706
+	 * @throws InvalidArgumentException
3707
+	 * @throws InvalidInterfaceException
3708
+	 * @throws InvalidDataTypeException
3709
+	 * @throws EE_Error
3710
+	 */
3711
+	public function get_action_link_or_button(
3712
+		$action,
3713
+		$type = 'add',
3714
+		$extra_request = [],
3715
+		$class = 'button-primary',
3716
+		$base_url = '',
3717
+		$exclude_nonce = false
3718
+	) {
3719
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3720
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3721
+			throw new EE_Error(
3722
+				sprintf(
3723
+					esc_html__(
3724
+						'There is no page route for given action for the button.  This action was given: %s',
3725
+						'event_espresso'
3726
+					),
3727
+					$action
3728
+				)
3729
+			);
3730
+		}
3731
+		if (! isset($this->_labels['buttons'][ $type ])) {
3732
+			throw new EE_Error(
3733
+				sprintf(
3734
+					esc_html__(
3735
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3736
+						'event_espresso'
3737
+					),
3738
+					$type
3739
+				)
3740
+			);
3741
+		}
3742
+		// finally check user access for this button.
3743
+		$has_access = $this->check_user_access($action, true);
3744
+		if (! $has_access) {
3745
+			return '';
3746
+		}
3747
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3748
+		$query_args = [
3749
+			'action' => $action,
3750
+		];
3751
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3752
+		if (! empty($extra_request)) {
3753
+			$query_args = array_merge($extra_request, $query_args);
3754
+		}
3755
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3756
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3757
+	}
3758
+
3759
+
3760
+	/**
3761
+	 * _per_page_screen_option
3762
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3763
+	 *
3764
+	 * @return void
3765
+	 * @throws InvalidArgumentException
3766
+	 * @throws InvalidInterfaceException
3767
+	 * @throws InvalidDataTypeException
3768
+	 */
3769
+	protected function _per_page_screen_option()
3770
+	{
3771
+		$option = 'per_page';
3772
+		$args   = [
3773
+			'label'   => apply_filters(
3774
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3775
+				$this->_admin_page_title,
3776
+				$this
3777
+			),
3778
+			'default' => (int) apply_filters(
3779
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3780
+				20
3781
+			),
3782
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3783
+		];
3784
+		// ONLY add the screen option if the user has access to it.
3785
+		if ($this->check_user_access($this->_current_view, true)) {
3786
+			add_screen_option($option, $args);
3787
+		}
3788
+	}
3789
+
3790
+
3791
+	/**
3792
+	 * set_per_page_screen_option
3793
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3794
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3795
+	 * admin_menu.
3796
+	 *
3797
+	 * @return void
3798
+	 */
3799
+	private function _set_per_page_screen_options()
3800
+	{
3801
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3802
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3803
+			if (! $user = wp_get_current_user()) {
3804
+				return;
3805
+			}
3806
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3807
+			if (! $option) {
3808
+				return;
3809
+			}
3810
+			$value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3811
+			$map_option = $option;
3812
+			$option     = str_replace('-', '_', $option);
3813
+			switch ($map_option) {
3814
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3815
+					$max_value = apply_filters(
3816
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3817
+						999,
3818
+						$this->_current_page,
3819
+						$this->_current_view
3820
+					);
3821
+					if ($value < 1) {
3822
+						return;
3823
+					}
3824
+					$value = min($value, $max_value);
3825
+					break;
3826
+				default:
3827
+					$value = apply_filters(
3828
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3829
+						false,
3830
+						$option,
3831
+						$value
3832
+					);
3833
+					if (false === $value) {
3834
+						return;
3835
+					}
3836
+					break;
3837
+			}
3838
+			update_user_meta($user->ID, $option, $value);
3839
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3840
+			exit;
3841
+		}
3842
+	}
3843
+
3844
+
3845
+	/**
3846
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3847
+	 *
3848
+	 * @param array $data array that will be assigned to template args.
3849
+	 */
3850
+	public function set_template_args($data)
3851
+	{
3852
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3853
+	}
3854
+
3855
+
3856
+	/**
3857
+	 * This makes available the WP transient system for temporarily moving data between routes
3858
+	 *
3859
+	 * @param string $route             the route that should receive the transient
3860
+	 * @param array  $data              the data that gets sent
3861
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3862
+	 *                                  normal route transient.
3863
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3864
+	 *                                  when we are adding a transient before page_routes have been defined.
3865
+	 * @return void
3866
+	 * @throws EE_Error
3867
+	 */
3868
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3869
+	{
3870
+		$user_id = get_current_user_id();
3871
+		if (! $skip_route_verify) {
3872
+			$this->_verify_route($route);
3873
+		}
3874
+		// now let's set the string for what kind of transient we're setting
3875
+		$transient = $notices
3876
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3877
+			: 'rte_tx_' . $route . '_' . $user_id;
3878
+		$data      = $notices ? ['notices' => $data] : $data;
3879
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3880
+		$existing = is_multisite() && is_network_admin()
3881
+			? get_site_transient($transient)
3882
+			: get_transient($transient);
3883
+		if ($existing) {
3884
+			$data = array_merge((array) $data, (array) $existing);
3885
+		}
3886
+		if (is_multisite() && is_network_admin()) {
3887
+			set_site_transient($transient, $data, 8);
3888
+		} else {
3889
+			set_transient($transient, $data, 8);
3890
+		}
3891
+	}
3892
+
3893
+
3894
+	/**
3895
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3896
+	 *
3897
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3898
+	 * @param string $route
3899
+	 * @return mixed data
3900
+	 */
3901
+	protected function _get_transient($notices = false, $route = '')
3902
+	{
3903
+		$user_id   = get_current_user_id();
3904
+		$route     = ! $route ? $this->_req_action : $route;
3905
+		$transient = $notices
3906
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3907
+			: 'rte_tx_' . $route . '_' . $user_id;
3908
+		$data      = is_multisite() && is_network_admin()
3909
+			? get_site_transient($transient)
3910
+			: get_transient($transient);
3911
+		// delete transient after retrieval (just in case it hasn't expired);
3912
+		if (is_multisite() && is_network_admin()) {
3913
+			delete_site_transient($transient);
3914
+		} else {
3915
+			delete_transient($transient);
3916
+		}
3917
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3918
+	}
3919
+
3920
+
3921
+	/**
3922
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3923
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3924
+	 * default route callback on the EE_Admin page you want it run.)
3925
+	 *
3926
+	 * @return void
3927
+	 */
3928
+	protected function _transient_garbage_collection()
3929
+	{
3930
+		global $wpdb;
3931
+		// retrieve all existing transients
3932
+		$query =
3933
+			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3934
+		if ($results = $wpdb->get_results($query)) {
3935
+			foreach ($results as $result) {
3936
+				$transient = str_replace('_transient_', '', $result->option_name);
3937
+				get_transient($transient);
3938
+				if (is_multisite() && is_network_admin()) {
3939
+					get_site_transient($transient);
3940
+				}
3941
+			}
3942
+		}
3943
+	}
3944
+
3945
+
3946
+	/**
3947
+	 * get_view
3948
+	 *
3949
+	 * @return string content of _view property
3950
+	 */
3951
+	public function get_view()
3952
+	{
3953
+		return $this->_view;
3954
+	}
3955
+
3956
+
3957
+	/**
3958
+	 * getter for the protected $_views property
3959
+	 *
3960
+	 * @return array
3961
+	 */
3962
+	public function get_views()
3963
+	{
3964
+		return $this->_views;
3965
+	}
3966
+
3967
+
3968
+	/**
3969
+	 * get_current_page
3970
+	 *
3971
+	 * @return string _current_page property value
3972
+	 */
3973
+	public function get_current_page()
3974
+	{
3975
+		return $this->_current_page;
3976
+	}
3977
+
3978
+
3979
+	/**
3980
+	 * get_current_view
3981
+	 *
3982
+	 * @return string _current_view property value
3983
+	 */
3984
+	public function get_current_view()
3985
+	{
3986
+		return $this->_current_view;
3987
+	}
3988
+
3989
+
3990
+	/**
3991
+	 * get_current_screen
3992
+	 *
3993
+	 * @return object The current WP_Screen object
3994
+	 */
3995
+	public function get_current_screen()
3996
+	{
3997
+		return $this->_current_screen;
3998
+	}
3999
+
4000
+
4001
+	/**
4002
+	 * get_current_page_view_url
4003
+	 *
4004
+	 * @return string This returns the url for the current_page_view.
4005
+	 */
4006
+	public function get_current_page_view_url()
4007
+	{
4008
+		return $this->_current_page_view_url;
4009
+	}
4010
+
4011
+
4012
+	/**
4013
+	 * just returns the Request
4014
+	 *
4015
+	 * @return RequestInterface
4016
+	 */
4017
+	public function get_request()
4018
+	{
4019
+		return $this->request;
4020
+	}
4021
+
4022
+
4023
+	/**
4024
+	 * just returns the _req_data property
4025
+	 *
4026
+	 * @return array
4027
+	 */
4028
+	public function get_request_data()
4029
+	{
4030
+		return $this->request->requestParams();
4031
+	}
4032
+
4033
+
4034
+	/**
4035
+	 * returns the _req_data protected property
4036
+	 *
4037
+	 * @return string
4038
+	 */
4039
+	public function get_req_action()
4040
+	{
4041
+		return $this->_req_action;
4042
+	}
4043
+
4044
+
4045
+	/**
4046
+	 * @return bool  value of $_is_caf property
4047
+	 */
4048
+	public function is_caf()
4049
+	{
4050
+		return $this->_is_caf;
4051
+	}
4052
+
4053
+
4054
+	/**
4055
+	 * @return mixed
4056
+	 */
4057
+	public function default_espresso_metaboxes()
4058
+	{
4059
+		return $this->_default_espresso_metaboxes;
4060
+	}
4061
+
4062
+
4063
+	/**
4064
+	 * @return mixed
4065
+	 */
4066
+	public function admin_base_url()
4067
+	{
4068
+		return $this->_admin_base_url;
4069
+	}
4070
+
4071
+
4072
+	/**
4073
+	 * @return mixed
4074
+	 */
4075
+	public function wp_page_slug()
4076
+	{
4077
+		return $this->_wp_page_slug;
4078
+	}
4079
+
4080
+
4081
+	/**
4082
+	 * updates  espresso configuration settings
4083
+	 *
4084
+	 * @param string                   $tab
4085
+	 * @param EE_Config_Base|EE_Config $config
4086
+	 * @param string                   $file file where error occurred
4087
+	 * @param string                   $func function  where error occurred
4088
+	 * @param string                   $line line no where error occurred
4089
+	 * @return boolean
4090
+	 */
4091
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4092
+	{
4093
+		// remove any options that are NOT going to be saved with the config settings.
4094
+		if (isset($config->core->ee_ueip_optin)) {
4095
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4096
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4097
+			update_option('ee_ueip_has_notified', true);
4098
+		}
4099
+		// and save it (note we're also doing the network save here)
4100
+		$net_saved    = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4101
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4102
+		if ($config_saved && $net_saved) {
4103
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4104
+			return true;
4105
+		}
4106
+		EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4107
+		return false;
4108
+	}
4109
+
4110
+
4111
+	/**
4112
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4113
+	 *
4114
+	 * @return array
4115
+	 */
4116
+	public function get_yes_no_values()
4117
+	{
4118
+		return $this->_yes_no_values;
4119
+	}
4120
+
4121
+
4122
+	protected function _get_dir()
4123
+	{
4124
+		$reflector = new ReflectionClass(get_class($this));
4125
+		return dirname($reflector->getFileName());
4126
+	}
4127
+
4128
+
4129
+	/**
4130
+	 * A helper for getting a "next link".
4131
+	 *
4132
+	 * @param string $url   The url to link to
4133
+	 * @param string $class The class to use.
4134
+	 * @return string
4135
+	 */
4136
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4137
+	{
4138
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4139
+	}
4140
+
4141
+
4142
+	/**
4143
+	 * A helper for getting a "previous link".
4144
+	 *
4145
+	 * @param string $url   The url to link to
4146
+	 * @param string $class The class to use.
4147
+	 * @return string
4148
+	 */
4149
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4150
+	{
4151
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4152
+	}
4153
+
4154
+
4155
+
4156
+
4157
+
4158
+
4159
+
4160
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4161
+
4162
+
4163
+	/**
4164
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4165
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4166
+	 * _req_data array.
4167
+	 *
4168
+	 * @return bool success/fail
4169
+	 * @throws EE_Error
4170
+	 * @throws InvalidArgumentException
4171
+	 * @throws ReflectionException
4172
+	 * @throws InvalidDataTypeException
4173
+	 * @throws InvalidInterfaceException
4174
+	 */
4175
+	protected function _process_resend_registration()
4176
+	{
4177
+		$this->_template_args['success'] = EED_Messages::process_resend($this->request->requestParams());
4178
+		do_action(
4179
+			'AHEE__EE_Admin_Page___process_resend_registration',
4180
+			$this->_template_args['success'],
4181
+			$this->request->requestParams()
4182
+		);
4183
+		return $this->_template_args['success'];
4184
+	}
4185
+
4186
+
4187
+	/**
4188
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4189
+	 *
4190
+	 * @param EE_Payment $payment
4191
+	 * @return bool success/fail
4192
+	 */
4193
+	protected function _process_payment_notification(EE_Payment $payment)
4194
+	{
4195
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4196
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4197
+		$this->_template_args['success'] = apply_filters(
4198
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4199
+			false,
4200
+			$payment
4201
+		);
4202
+		return $this->_template_args['success'];
4203
+	}
4204 4204
 }
Please login to merge, or discard this patch.
core/services/request/sanitizers/RequestSanitizer.php 1 patch
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -4,61 +4,61 @@
 block discarded – undo
4 4
 
5 5
 class RequestSanitizer
6 6
 {
7
-    /**
8
-     * Will sanitize the supplied request parameter based on the specified data type
9
-     *
10
-     * @param mixed  $param     the supplied request parameter
11
-     * @param string $type      the specified data type (default: "string")
12
-     *                          valid values: "bool", "float", "int", "key", "url", or "string"
13
-     * @param bool   $is_array  if true, then $param will be treated as an array of $type
14
-     * @param string $delimiter if $param is a CSV like value (ex: 1,2,3,4,5...) then this is the value separator
15
-     * @return array|bool|float|int|string
16
-     * @since 4.10.14.p
17
-     */
18
-    public function clean($param, string $type = 'string', bool $is_array = false, string $delimiter = '')
19
-    {
20
-        if ($delimiter !== '' && is_string($param)) {
21
-            $param = explode($delimiter, $param);
22
-            // unset the delimiter else this function will recurse forever when we loop over the array of results
23
-            $delimiter = '';
24
-        }
25
-        // check if we are getting an improperly typed array and correct
26
-        $is_array = $is_array || is_array($param);
27
-        if ($is_array) {
28
-            $values = [];
29
-            foreach ((array) $param as $key => $value) {
30
-                $values[ $key ] = $this->clean($value, $type, is_array($value), $delimiter);
31
-            }
32
-            return $values;
33
-        }
34
-        return $this->sanitizeParam($param, $type);
35
-    }
7
+	/**
8
+	 * Will sanitize the supplied request parameter based on the specified data type
9
+	 *
10
+	 * @param mixed  $param     the supplied request parameter
11
+	 * @param string $type      the specified data type (default: "string")
12
+	 *                          valid values: "bool", "float", "int", "key", "url", or "string"
13
+	 * @param bool   $is_array  if true, then $param will be treated as an array of $type
14
+	 * @param string $delimiter if $param is a CSV like value (ex: 1,2,3,4,5...) then this is the value separator
15
+	 * @return array|bool|float|int|string
16
+	 * @since 4.10.14.p
17
+	 */
18
+	public function clean($param, string $type = 'string', bool $is_array = false, string $delimiter = '')
19
+	{
20
+		if ($delimiter !== '' && is_string($param)) {
21
+			$param = explode($delimiter, $param);
22
+			// unset the delimiter else this function will recurse forever when we loop over the array of results
23
+			$delimiter = '';
24
+		}
25
+		// check if we are getting an improperly typed array and correct
26
+		$is_array = $is_array || is_array($param);
27
+		if ($is_array) {
28
+			$values = [];
29
+			foreach ((array) $param as $key => $value) {
30
+				$values[ $key ] = $this->clean($value, $type, is_array($value), $delimiter);
31
+			}
32
+			return $values;
33
+		}
34
+		return $this->sanitizeParam($param, $type);
35
+	}
36 36
 
37 37
 
38
-    /**
39
-     * @param mixed  $param
40
-     * @param string $type
41
-     * @return array|float|int|mixed|string|string[]|null
42
-     * @since   $VID:$
43
-     */
44
-    public function sanitizeParam($param, string $type = 'string')
45
-    {
46
-        switch ($type) {
47
-            case 'bool':
48
-                return filter_var($param, FILTER_VALIDATE_BOOLEAN);
49
-            case 'float':
50
-                return (float) $param;
51
-            case 'fqcn':
52
-                return preg_replace('[^\\\w\d]', '', $param);
53
-            case 'int':
54
-                return (int) $param;
55
-            case 'key':
56
-                return sanitize_key($param);
57
-            case 'url':
58
-                return esc_url_raw($param);
59
-            case 'string':
60
-            default:
61
-                return sanitize_text_field($param);
62
-        }
63
-    }
38
+	/**
39
+	 * @param mixed  $param
40
+	 * @param string $type
41
+	 * @return array|float|int|mixed|string|string[]|null
42
+	 * @since   $VID:$
43
+	 */
44
+	public function sanitizeParam($param, string $type = 'string')
45
+	{
46
+		switch ($type) {
47
+			case 'bool':
48
+				return filter_var($param, FILTER_VALIDATE_BOOLEAN);
49
+			case 'float':
50
+				return (float) $param;
51
+			case 'fqcn':
52
+				return preg_replace('[^\\\w\d]', '', $param);
53
+			case 'int':
54
+				return (int) $param;
55
+			case 'key':
56
+				return sanitize_key($param);
57
+			case 'url':
58
+				return esc_url_raw($param);
59
+			case 'string':
60
+			default:
61
+				return sanitize_text_field($param);
62
+		}
63
+	}
64 64
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Country.model.php 2 patches
Indentation   +205 added lines, -205 removed lines patch added patch discarded remove patch
@@ -11,209 +11,209 @@
 block discarded – undo
11 11
 class EEM_Country extends EEM_Base
12 12
 {
13 13
 
14
-    // private instance of the Attendee object
15
-    protected static $_instance = null;
16
-
17
-    // array of all countries
18
-    private static $_all_countries = false;
19
-
20
-    // array of all active countries
21
-    private static $_active_countries = false;
22
-
23
-
24
-    /**
25
-     * Resets the country
26
-     *
27
-     * @param string $timezone
28
-     * @return EEM_Country|EEM_Base|null
29
-     * @throws EE_Error
30
-     * @throws ReflectionException
31
-     */
32
-    public static function reset($timezone = null)
33
-    {
34
-        self::$_active_countries = null;
35
-        self::$_all_countries    = null;
36
-        return parent::reset($timezone);
37
-    }
38
-
39
-
40
-    protected function __construct($timezone = '')
41
-    {
42
-        $this->singular_item = esc_html__('Country', 'event_espresso');
43
-        $this->plural_item   = esc_html__('Countries', 'event_espresso');
44
-
45
-        $this->_tables = [
46
-            'Country' => new EE_Primary_Table('esp_country', 'CNT_ISO'),
47
-        ];
48
-
49
-        $this->_fields          = [
50
-            'Country' => [
51
-                'CNT_active'      => new EE_Boolean_Field(
52
-                    'CNT_active',
53
-                    esc_html__('Country Appears in Dropdown Select Lists', 'event_espresso'),
54
-                    false,
55
-                    true
56
-                ),
57
-                'CNT_ISO'         => new EE_Primary_Key_String_Field(
58
-                    'CNT_ISO',
59
-                    esc_html__('Country ISO Code', 'event_espresso')
60
-                ),
61
-                'CNT_ISO3'        => new EE_All_Caps_Text_Field(
62
-                    'CNT_ISO3',
63
-                    esc_html__('Country ISO3 Code', 'event_espresso'),
64
-                    false,
65
-                    ''
66
-                ),
67
-                'RGN_ID'          => new EE_Integer_Field(
68
-                    'RGN_ID',
69
-                    esc_html__('Region ID', 'event_espresso'),
70
-                    false,
71
-                    0
72
-                ),
73
-                // should be a foreign key, but no region table exists yet
74
-                'CNT_name'        => new EE_Plain_Text_Field(
75
-                    'CNT_name',
76
-                    esc_html__('Country Name', 'event_espresso'),
77
-                    false,
78
-                    ''
79
-                ),
80
-                'CNT_cur_code'    => new EE_All_Caps_Text_Field(
81
-                    'CNT_cur_code',
82
-                    esc_html__('Country Currency Code', 'event_espresso'),
83
-                    false
84
-                ),
85
-                'CNT_cur_single'  => new EE_Plain_Text_Field(
86
-                    'CNT_cur_single',
87
-                    esc_html__('Currency Name Singular', 'event_espresso'),
88
-                    false
89
-                ),
90
-                'CNT_cur_plural'  => new EE_Plain_Text_Field(
91
-                    'CNT_cur_plural',
92
-                    esc_html__('Currency Name Plural', 'event_espresso'),
93
-                    false
94
-                ),
95
-                'CNT_cur_sign'    => new EE_Plain_Text_Field(
96
-                    'CNT_cur_sign',
97
-                    esc_html__('Currency Sign', 'event_espresso'),
98
-                    false
99
-                ),
100
-                'CNT_cur_sign_b4' => new EE_Boolean_Field(
101
-                    'CNT_cur_sign_b4',
102
-                    esc_html__('Currency Sign Before Number', 'event_espresso'),
103
-                    false,
104
-                    true
105
-                ),
106
-                'CNT_cur_dec_plc' => new EE_Integer_Field(
107
-                    'CNT_cur_dec_plc',
108
-                    esc_html__('Currency Decimal Places', 'event_espresso'),
109
-                    false,
110
-                    2
111
-                ),
112
-                'CNT_cur_dec_mrk' => new EE_Plain_Text_Field(
113
-                    'CNT_cur_dec_mrk',
114
-                    esc_html__('Currency Decimal Mark', 'event_espresso'),
115
-                    false,
116
-                    '.'
117
-                ),
118
-                'CNT_cur_thsnds'  => new EE_Plain_Text_Field(
119
-                    'CNT_cur_thsnds',
120
-                    esc_html__('Currency Thousands Separator', 'event_espresso'),
121
-                    false,
122
-                    ','
123
-                ),
124
-                'CNT_tel_code'    => new EE_Plain_Text_Field(
125
-                    'CNT_tel_code',
126
-                    esc_html__('Country Telephone Code', 'event_espresso'),
127
-                    false,
128
-                    ''
129
-                ),
130
-                'CNT_is_EU'       => new EE_Boolean_Field(
131
-                    'CNT_is_EU',
132
-                    esc_html__('Country is Member of EU', 'event_espresso'),
133
-                    false,
134
-                    false
135
-                ),
136
-            ],
137
-        ];
138
-        $this->_model_relations = [
139
-            'Attendee' => new EE_Has_Many_Relation(),
140
-            'State'    => new EE_Has_Many_Relation(),
141
-            'Venue'    => new EE_Has_Many_Relation(),
142
-        ];
143
-        // only anyone to view, but only those with the default role can do anything
144
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
145
-
146
-        parent::__construct($timezone);
147
-    }
148
-
149
-
150
-    /**
151
-     * @return EE_Country[]
152
-     * @throws EE_Error
153
-     */
154
-    public function get_all_countries()
155
-    {
156
-        if (! self::$_all_countries) {
157
-            self::$_all_countries = $this->get_all(['order_by' => ['CNT_name' => 'ASC'], 'limit' => [0, 99999]]);
158
-        }
159
-        return self::$_all_countries;
160
-    }
161
-
162
-
163
-    /**
164
-     * Gets and caches the list of active countries. If you know the list of active countries
165
-     * has changed during this request, first use EEM_Country::reset() to flush the cache
166
-     *
167
-     * @return EE_Country[]
168
-     * @throws EE_Error
169
-     */
170
-    public function get_all_active_countries()
171
-    {
172
-        if (! self::$_active_countries) {
173
-            self::$_active_countries =
174
-                $this->get_all([['CNT_active' => true], 'order_by' => ['CNT_name' => 'ASC'], 'limit' => [0, 99999]]);
175
-        }
176
-        return self::$_active_countries;
177
-    }
178
-
179
-
180
-    /**
181
-     * Gets the country's name by its ISO
182
-     *
183
-     * @param string $country_ISO
184
-     * @return string
185
-     * @throws EE_Error
186
-     */
187
-    public function get_country_name_by_ISO($country_ISO)
188
-    {
189
-        $countries = $this->get_all_countries();
190
-        if (isset($countries[ $country_ISO ]) && $countries[ $country_ISO ] instanceof EE_Country) {
191
-            return $countries[ $country_ISO ]->name();
192
-        }
193
-        $names = $this->get_col([['CNT_ISO' => $country_ISO], 'limit' => 1], 'CNT_name');
194
-        if (is_array($names) && ! empty($names)) {
195
-            return reset($names);
196
-        } else {
197
-            return '';
198
-        }
199
-    }
200
-
201
-
202
-    /**
203
-     * Gets the country's name by its name
204
-     *
205
-     * @param string $country_name
206
-     * @return EE_Country|null
207
-     * @throws EE_Error
208
-     */
209
-    public function getCountryByName($country_name)
210
-    {
211
-        $countries = $this->get_all_countries();
212
-        foreach ($countries as $country) {
213
-            if ($country instanceof EE_Country && $country->name() === $country_name) {
214
-                return $country;
215
-            }
216
-        }
217
-        return $this->get_one([['CNT_name' => $country_name]]);
218
-    }
14
+	// private instance of the Attendee object
15
+	protected static $_instance = null;
16
+
17
+	// array of all countries
18
+	private static $_all_countries = false;
19
+
20
+	// array of all active countries
21
+	private static $_active_countries = false;
22
+
23
+
24
+	/**
25
+	 * Resets the country
26
+	 *
27
+	 * @param string $timezone
28
+	 * @return EEM_Country|EEM_Base|null
29
+	 * @throws EE_Error
30
+	 * @throws ReflectionException
31
+	 */
32
+	public static function reset($timezone = null)
33
+	{
34
+		self::$_active_countries = null;
35
+		self::$_all_countries    = null;
36
+		return parent::reset($timezone);
37
+	}
38
+
39
+
40
+	protected function __construct($timezone = '')
41
+	{
42
+		$this->singular_item = esc_html__('Country', 'event_espresso');
43
+		$this->plural_item   = esc_html__('Countries', 'event_espresso');
44
+
45
+		$this->_tables = [
46
+			'Country' => new EE_Primary_Table('esp_country', 'CNT_ISO'),
47
+		];
48
+
49
+		$this->_fields          = [
50
+			'Country' => [
51
+				'CNT_active'      => new EE_Boolean_Field(
52
+					'CNT_active',
53
+					esc_html__('Country Appears in Dropdown Select Lists', 'event_espresso'),
54
+					false,
55
+					true
56
+				),
57
+				'CNT_ISO'         => new EE_Primary_Key_String_Field(
58
+					'CNT_ISO',
59
+					esc_html__('Country ISO Code', 'event_espresso')
60
+				),
61
+				'CNT_ISO3'        => new EE_All_Caps_Text_Field(
62
+					'CNT_ISO3',
63
+					esc_html__('Country ISO3 Code', 'event_espresso'),
64
+					false,
65
+					''
66
+				),
67
+				'RGN_ID'          => new EE_Integer_Field(
68
+					'RGN_ID',
69
+					esc_html__('Region ID', 'event_espresso'),
70
+					false,
71
+					0
72
+				),
73
+				// should be a foreign key, but no region table exists yet
74
+				'CNT_name'        => new EE_Plain_Text_Field(
75
+					'CNT_name',
76
+					esc_html__('Country Name', 'event_espresso'),
77
+					false,
78
+					''
79
+				),
80
+				'CNT_cur_code'    => new EE_All_Caps_Text_Field(
81
+					'CNT_cur_code',
82
+					esc_html__('Country Currency Code', 'event_espresso'),
83
+					false
84
+				),
85
+				'CNT_cur_single'  => new EE_Plain_Text_Field(
86
+					'CNT_cur_single',
87
+					esc_html__('Currency Name Singular', 'event_espresso'),
88
+					false
89
+				),
90
+				'CNT_cur_plural'  => new EE_Plain_Text_Field(
91
+					'CNT_cur_plural',
92
+					esc_html__('Currency Name Plural', 'event_espresso'),
93
+					false
94
+				),
95
+				'CNT_cur_sign'    => new EE_Plain_Text_Field(
96
+					'CNT_cur_sign',
97
+					esc_html__('Currency Sign', 'event_espresso'),
98
+					false
99
+				),
100
+				'CNT_cur_sign_b4' => new EE_Boolean_Field(
101
+					'CNT_cur_sign_b4',
102
+					esc_html__('Currency Sign Before Number', 'event_espresso'),
103
+					false,
104
+					true
105
+				),
106
+				'CNT_cur_dec_plc' => new EE_Integer_Field(
107
+					'CNT_cur_dec_plc',
108
+					esc_html__('Currency Decimal Places', 'event_espresso'),
109
+					false,
110
+					2
111
+				),
112
+				'CNT_cur_dec_mrk' => new EE_Plain_Text_Field(
113
+					'CNT_cur_dec_mrk',
114
+					esc_html__('Currency Decimal Mark', 'event_espresso'),
115
+					false,
116
+					'.'
117
+				),
118
+				'CNT_cur_thsnds'  => new EE_Plain_Text_Field(
119
+					'CNT_cur_thsnds',
120
+					esc_html__('Currency Thousands Separator', 'event_espresso'),
121
+					false,
122
+					','
123
+				),
124
+				'CNT_tel_code'    => new EE_Plain_Text_Field(
125
+					'CNT_tel_code',
126
+					esc_html__('Country Telephone Code', 'event_espresso'),
127
+					false,
128
+					''
129
+				),
130
+				'CNT_is_EU'       => new EE_Boolean_Field(
131
+					'CNT_is_EU',
132
+					esc_html__('Country is Member of EU', 'event_espresso'),
133
+					false,
134
+					false
135
+				),
136
+			],
137
+		];
138
+		$this->_model_relations = [
139
+			'Attendee' => new EE_Has_Many_Relation(),
140
+			'State'    => new EE_Has_Many_Relation(),
141
+			'Venue'    => new EE_Has_Many_Relation(),
142
+		];
143
+		// only anyone to view, but only those with the default role can do anything
144
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
145
+
146
+		parent::__construct($timezone);
147
+	}
148
+
149
+
150
+	/**
151
+	 * @return EE_Country[]
152
+	 * @throws EE_Error
153
+	 */
154
+	public function get_all_countries()
155
+	{
156
+		if (! self::$_all_countries) {
157
+			self::$_all_countries = $this->get_all(['order_by' => ['CNT_name' => 'ASC'], 'limit' => [0, 99999]]);
158
+		}
159
+		return self::$_all_countries;
160
+	}
161
+
162
+
163
+	/**
164
+	 * Gets and caches the list of active countries. If you know the list of active countries
165
+	 * has changed during this request, first use EEM_Country::reset() to flush the cache
166
+	 *
167
+	 * @return EE_Country[]
168
+	 * @throws EE_Error
169
+	 */
170
+	public function get_all_active_countries()
171
+	{
172
+		if (! self::$_active_countries) {
173
+			self::$_active_countries =
174
+				$this->get_all([['CNT_active' => true], 'order_by' => ['CNT_name' => 'ASC'], 'limit' => [0, 99999]]);
175
+		}
176
+		return self::$_active_countries;
177
+	}
178
+
179
+
180
+	/**
181
+	 * Gets the country's name by its ISO
182
+	 *
183
+	 * @param string $country_ISO
184
+	 * @return string
185
+	 * @throws EE_Error
186
+	 */
187
+	public function get_country_name_by_ISO($country_ISO)
188
+	{
189
+		$countries = $this->get_all_countries();
190
+		if (isset($countries[ $country_ISO ]) && $countries[ $country_ISO ] instanceof EE_Country) {
191
+			return $countries[ $country_ISO ]->name();
192
+		}
193
+		$names = $this->get_col([['CNT_ISO' => $country_ISO], 'limit' => 1], 'CNT_name');
194
+		if (is_array($names) && ! empty($names)) {
195
+			return reset($names);
196
+		} else {
197
+			return '';
198
+		}
199
+	}
200
+
201
+
202
+	/**
203
+	 * Gets the country's name by its name
204
+	 *
205
+	 * @param string $country_name
206
+	 * @return EE_Country|null
207
+	 * @throws EE_Error
208
+	 */
209
+	public function getCountryByName($country_name)
210
+	{
211
+		$countries = $this->get_all_countries();
212
+		foreach ($countries as $country) {
213
+			if ($country instanceof EE_Country && $country->name() === $country_name) {
214
+				return $country;
215
+			}
216
+		}
217
+		return $this->get_one([['CNT_name' => $country_name]]);
218
+	}
219 219
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -46,7 +46,7 @@  discard block
 block discarded – undo
46 46
             'Country' => new EE_Primary_Table('esp_country', 'CNT_ISO'),
47 47
         ];
48 48
 
49
-        $this->_fields          = [
49
+        $this->_fields = [
50 50
             'Country' => [
51 51
                 'CNT_active'      => new EE_Boolean_Field(
52 52
                     'CNT_active',
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
             'Venue'    => new EE_Has_Many_Relation(),
142 142
         ];
143 143
         // only anyone to view, but only those with the default role can do anything
144
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
144
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
145 145
 
146 146
         parent::__construct($timezone);
147 147
     }
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
      */
154 154
     public function get_all_countries()
155 155
     {
156
-        if (! self::$_all_countries) {
156
+        if ( ! self::$_all_countries) {
157 157
             self::$_all_countries = $this->get_all(['order_by' => ['CNT_name' => 'ASC'], 'limit' => [0, 99999]]);
158 158
         }
159 159
         return self::$_all_countries;
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
      */
170 170
     public function get_all_active_countries()
171 171
     {
172
-        if (! self::$_active_countries) {
172
+        if ( ! self::$_active_countries) {
173 173
             self::$_active_countries =
174 174
                 $this->get_all([['CNT_active' => true], 'order_by' => ['CNT_name' => 'ASC'], 'limit' => [0, 99999]]);
175 175
         }
@@ -187,8 +187,8 @@  discard block
 block discarded – undo
187 187
     public function get_country_name_by_ISO($country_ISO)
188 188
     {
189 189
         $countries = $this->get_all_countries();
190
-        if (isset($countries[ $country_ISO ]) && $countries[ $country_ISO ] instanceof EE_Country) {
191
-            return $countries[ $country_ISO ]->name();
190
+        if (isset($countries[$country_ISO]) && $countries[$country_ISO] instanceof EE_Country) {
191
+            return $countries[$country_ISO]->name();
192 192
         }
193 193
         $names = $this->get_col([['CNT_ISO' => $country_ISO], 'limit' => 1], 'CNT_name');
194 194
         if (is_array($names) && ! empty($names)) {
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelectorPostData.php 2 patches
Indentation   +231 added lines, -231 removed lines patch added patch discarded remove patch
@@ -16,235 +16,235 @@
 block discarded – undo
16 16
 class ProcessTicketSelectorPostData
17 17
 {
18 18
 
19
-    const DATA_KEY_EVENT_ID      = 'id';
20
-
21
-    const DATA_KEY_MAX_ATNDZ     = 'max_atndz';
22
-
23
-    const DATA_KEY_QUANTITY      = 'qty';
24
-
25
-    const DATA_KEY_RETURN_URL    = 'return_url';
26
-
27
-    const DATA_KEY_ROWS          = 'rows';
28
-
29
-    const DATA_KEY_TICKET_ID     = 'ticket_id';
30
-
31
-    const DATA_KEY_TOTAL_TICKETS = 'total_tickets';
32
-
33
-    const INPUT_KEY_EVENT_ID     = 'tkt-slctr-event-id';
34
-
35
-    const INPUT_KEY_MAX_ATNDZ    = 'tkt-slctr-max-atndz-';
36
-
37
-    const INPUT_KEY_ROWS         = 'tkt-slctr-rows-';
38
-
39
-    const INPUT_KEY_QTY          = 'tkt-slctr-qty-';
40
-
41
-    const INPUT_KEY_TICKET_ID    = 'tkt-slctr-ticket-id-';
42
-
43
-    const INPUT_KEY_RETURN_URL   = 'tkt-slctr-return-url-';
44
-
45
-
46
-    /**
47
-     * @var int
48
-     */
49
-    protected $event_id;
50
-
51
-    /**
52
-     * @var array
53
-     */
54
-    protected $inputs_to_clean = [];
55
-
56
-    /**
57
-     * @var array
58
-     */
59
-    protected $valid_data = [];
60
-
61
-    /**
62
-     * @var RequestInterface
63
-     */
64
-    protected $request;
65
-
66
-
67
-    /**
68
-     * @param RequestInterface $request
69
-     */
70
-    public function __construct(RequestInterface $request)
71
-    {
72
-        $this->request         = $request;
73
-        $this->inputs_to_clean = [
74
-            self::DATA_KEY_MAX_ATNDZ     => self::INPUT_KEY_MAX_ATNDZ,
75
-            self::DATA_KEY_ROWS          => self::INPUT_KEY_ROWS,
76
-            self::DATA_KEY_QUANTITY      => self::INPUT_KEY_QTY,
77
-            self::DATA_KEY_TOTAL_TICKETS => self::INPUT_KEY_TICKET_ID,
78
-            self::DATA_KEY_RETURN_URL    => self::INPUT_KEY_RETURN_URL,
79
-        ];
80
-    }
81
-
82
-
83
-    /**
84
-     * @return int
85
-     * @throws DomainException
86
-     */
87
-    public function getEventId(): int
88
-    {
89
-        // do we have an event id?
90
-        if ($this->event_id === null) {
91
-            $this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, 'int');
92
-            if (! $this->event_id) {
93
-                // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
94
-                throw new DomainException(
95
-                    sprintf(
96
-                        esc_html__(
97
-                            'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
98
-                            'event_espresso'
99
-                        ),
100
-                        '<br/>'
101
-                    )
102
-                );
103
-            }
104
-        }
105
-        // event id is valid
106
-        return $this->event_id;
107
-    }
108
-
109
-
110
-    /**
111
-     * @return array
112
-     * @throws DomainException
113
-     */
114
-    public function validatePostData(): array
115
-    {
116
-        // grab valid id
117
-        $this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
118
-        // let's track the total number of tickets ordered.'
119
-        $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
120
-        // cycle through $inputs_to_clean array
121
-        foreach ($this->inputs_to_clean as $what => $input_to_clean) {
122
-            $input_key = "{$input_to_clean}{$this->event_id}";
123
-            // check for POST data
124
-            if ($this->request->requestParamIsSet($input_key)) {
125
-                switch ($what) {
126
-                    // integers
127
-                    case self::DATA_KEY_ROWS:
128
-                    case self::DATA_KEY_MAX_ATNDZ:
129
-                        $this->processInteger($what, $input_key);
130
-                        break;
131
-                    // arrays of integers
132
-                    case self::DATA_KEY_QUANTITY:
133
-                        $this->processQuantity($input_key);
134
-                        break;
135
-                    // array of integers
136
-                    case self::DATA_KEY_TOTAL_TICKETS:
137
-                        $this->processTicketIDs($input_key);
138
-                        break;
139
-                    case self::DATA_KEY_RETURN_URL:
140
-                        $this->processReturnURL($input_key);
141
-                        break;
142
-                }
143
-            }
144
-        }
145
-        return $this->valid_data;
146
-    }
147
-
148
-
149
-    /**
150
-     * @param string $what
151
-     * @param string $input_key
152
-     */
153
-    protected function processInteger(string $what, string $input_key)
154
-    {
155
-        $this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, 'int');
156
-    }
157
-
158
-
159
-    /**
160
-     * @param string $input_key
161
-     * @throws DomainException
162
-     */
163
-    protected function processQuantity(string $input_key)
164
-    {
165
-        // first get number of ticket option rows
166
-        $rows    = $this->request->getRequestParam(self::INPUT_KEY_ROWS . $this->event_id, 1, 'int');
167
-        $raw_qty = $this->request->getRequestParam($input_key);
168
-        // explode integers by the dash if qty is a string
169
-        $delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
170
-        /** @var array $row_qty */
171
-        $row_qty = $this->request->getRequestParam($input_key, [], 'int', true, $delimiter);
172
-        // if qty is coming from a radio button input, then we need to assemble an array of rows
173
-        if ($delimiter === '-') {
174
-            $row = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
175
-            $qty = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
176
-            // restructure the row qty array so that $row is now the key instead of the first value
177
-            $row_qty = [$row => $qty];
178
-            for ($x = 1; $x <= $rows; $x++) {
179
-                if (! isset($row_qty[ $x ])) {
180
-                    $row_qty[ $x ] = 0;
181
-                }
182
-            }
183
-        }
184
-        if (empty($row_qty) || ! is_array($row_qty) || $rows !== count($row_qty)) {
185
-            throw new DomainException(
186
-                sprintf(
187
-                    esc_html__(
188
-                        'An error occurred while trying to retrieve the ticket selections for the event.%sPlease click the back button on your browser and try again.',
189
-                        'event_espresso'
190
-                    ),
191
-                    '<br/>'
192
-                )
193
-            );
194
-        }
195
-        ksort($row_qty);
196
-        // cycle thru values
197
-        foreach ($row_qty as $qty) {
198
-            $qty = absint($qty);
199
-            // sanitize as integers
200
-            $this->valid_data[ self::DATA_KEY_QUANTITY ][]     = $qty;
201
-            $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] += $qty;
202
-        }
203
-    }
204
-
205
-
206
-    /**
207
-     * @param string $input_key
208
-     */
209
-    protected function processReturnURL(string $input_key)
210
-    {
211
-        // grab and sanitize return-url
212
-        $input_value = $this->request->getRequestParam($input_key, '', 'url');
213
-        // was the request coming from an iframe ? if so, then:
214
-        if (strpos($input_value, 'event_list=iframe')) {
215
-            // get anchor fragment
216
-            $input_value = explode('#', $input_value);
217
-            $input_value = end($input_value);
218
-            // use event list url instead, but append anchor
219
-            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
220
-        }
221
-        $this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
222
-    }
223
-
224
-
225
-    /**
226
-     * @param string $input_key
227
-     * @throws DomainException
228
-     */
229
-    protected function processTicketIDs(string $input_key)
230
-    {
231
-        $ticket_ids          = (array) $this->request->getRequestParam($input_key, [], 'int', true);
232
-        $filtered_ticket_ids = array_filter($ticket_ids);
233
-        if (empty($filtered_ticket_ids)) {
234
-            throw new DomainException(
235
-                sprintf(
236
-                    esc_html__(
237
-                        'An error occurred while trying to retrieve the ticket IDs for the event.%sPlease click the back button on your browser and try again.',
238
-                        'event_espresso'
239
-                    ),
240
-                    '<br/>'
241
-                )
242
-            );
243
-        }
244
-        // cycle thru values
245
-        foreach ($ticket_ids as $key => $value) {
246
-            // allow only integers
247
-            $this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
248
-        }
249
-    }
19
+	const DATA_KEY_EVENT_ID      = 'id';
20
+
21
+	const DATA_KEY_MAX_ATNDZ     = 'max_atndz';
22
+
23
+	const DATA_KEY_QUANTITY      = 'qty';
24
+
25
+	const DATA_KEY_RETURN_URL    = 'return_url';
26
+
27
+	const DATA_KEY_ROWS          = 'rows';
28
+
29
+	const DATA_KEY_TICKET_ID     = 'ticket_id';
30
+
31
+	const DATA_KEY_TOTAL_TICKETS = 'total_tickets';
32
+
33
+	const INPUT_KEY_EVENT_ID     = 'tkt-slctr-event-id';
34
+
35
+	const INPUT_KEY_MAX_ATNDZ    = 'tkt-slctr-max-atndz-';
36
+
37
+	const INPUT_KEY_ROWS         = 'tkt-slctr-rows-';
38
+
39
+	const INPUT_KEY_QTY          = 'tkt-slctr-qty-';
40
+
41
+	const INPUT_KEY_TICKET_ID    = 'tkt-slctr-ticket-id-';
42
+
43
+	const INPUT_KEY_RETURN_URL   = 'tkt-slctr-return-url-';
44
+
45
+
46
+	/**
47
+	 * @var int
48
+	 */
49
+	protected $event_id;
50
+
51
+	/**
52
+	 * @var array
53
+	 */
54
+	protected $inputs_to_clean = [];
55
+
56
+	/**
57
+	 * @var array
58
+	 */
59
+	protected $valid_data = [];
60
+
61
+	/**
62
+	 * @var RequestInterface
63
+	 */
64
+	protected $request;
65
+
66
+
67
+	/**
68
+	 * @param RequestInterface $request
69
+	 */
70
+	public function __construct(RequestInterface $request)
71
+	{
72
+		$this->request         = $request;
73
+		$this->inputs_to_clean = [
74
+			self::DATA_KEY_MAX_ATNDZ     => self::INPUT_KEY_MAX_ATNDZ,
75
+			self::DATA_KEY_ROWS          => self::INPUT_KEY_ROWS,
76
+			self::DATA_KEY_QUANTITY      => self::INPUT_KEY_QTY,
77
+			self::DATA_KEY_TOTAL_TICKETS => self::INPUT_KEY_TICKET_ID,
78
+			self::DATA_KEY_RETURN_URL    => self::INPUT_KEY_RETURN_URL,
79
+		];
80
+	}
81
+
82
+
83
+	/**
84
+	 * @return int
85
+	 * @throws DomainException
86
+	 */
87
+	public function getEventId(): int
88
+	{
89
+		// do we have an event id?
90
+		if ($this->event_id === null) {
91
+			$this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, 'int');
92
+			if (! $this->event_id) {
93
+				// $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
94
+				throw new DomainException(
95
+					sprintf(
96
+						esc_html__(
97
+							'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
98
+							'event_espresso'
99
+						),
100
+						'<br/>'
101
+					)
102
+				);
103
+			}
104
+		}
105
+		// event id is valid
106
+		return $this->event_id;
107
+	}
108
+
109
+
110
+	/**
111
+	 * @return array
112
+	 * @throws DomainException
113
+	 */
114
+	public function validatePostData(): array
115
+	{
116
+		// grab valid id
117
+		$this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
118
+		// let's track the total number of tickets ordered.'
119
+		$this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
120
+		// cycle through $inputs_to_clean array
121
+		foreach ($this->inputs_to_clean as $what => $input_to_clean) {
122
+			$input_key = "{$input_to_clean}{$this->event_id}";
123
+			// check for POST data
124
+			if ($this->request->requestParamIsSet($input_key)) {
125
+				switch ($what) {
126
+					// integers
127
+					case self::DATA_KEY_ROWS:
128
+					case self::DATA_KEY_MAX_ATNDZ:
129
+						$this->processInteger($what, $input_key);
130
+						break;
131
+					// arrays of integers
132
+					case self::DATA_KEY_QUANTITY:
133
+						$this->processQuantity($input_key);
134
+						break;
135
+					// array of integers
136
+					case self::DATA_KEY_TOTAL_TICKETS:
137
+						$this->processTicketIDs($input_key);
138
+						break;
139
+					case self::DATA_KEY_RETURN_URL:
140
+						$this->processReturnURL($input_key);
141
+						break;
142
+				}
143
+			}
144
+		}
145
+		return $this->valid_data;
146
+	}
147
+
148
+
149
+	/**
150
+	 * @param string $what
151
+	 * @param string $input_key
152
+	 */
153
+	protected function processInteger(string $what, string $input_key)
154
+	{
155
+		$this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, 'int');
156
+	}
157
+
158
+
159
+	/**
160
+	 * @param string $input_key
161
+	 * @throws DomainException
162
+	 */
163
+	protected function processQuantity(string $input_key)
164
+	{
165
+		// first get number of ticket option rows
166
+		$rows    = $this->request->getRequestParam(self::INPUT_KEY_ROWS . $this->event_id, 1, 'int');
167
+		$raw_qty = $this->request->getRequestParam($input_key);
168
+		// explode integers by the dash if qty is a string
169
+		$delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
170
+		/** @var array $row_qty */
171
+		$row_qty = $this->request->getRequestParam($input_key, [], 'int', true, $delimiter);
172
+		// if qty is coming from a radio button input, then we need to assemble an array of rows
173
+		if ($delimiter === '-') {
174
+			$row = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
175
+			$qty = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
176
+			// restructure the row qty array so that $row is now the key instead of the first value
177
+			$row_qty = [$row => $qty];
178
+			for ($x = 1; $x <= $rows; $x++) {
179
+				if (! isset($row_qty[ $x ])) {
180
+					$row_qty[ $x ] = 0;
181
+				}
182
+			}
183
+		}
184
+		if (empty($row_qty) || ! is_array($row_qty) || $rows !== count($row_qty)) {
185
+			throw new DomainException(
186
+				sprintf(
187
+					esc_html__(
188
+						'An error occurred while trying to retrieve the ticket selections for the event.%sPlease click the back button on your browser and try again.',
189
+						'event_espresso'
190
+					),
191
+					'<br/>'
192
+				)
193
+			);
194
+		}
195
+		ksort($row_qty);
196
+		// cycle thru values
197
+		foreach ($row_qty as $qty) {
198
+			$qty = absint($qty);
199
+			// sanitize as integers
200
+			$this->valid_data[ self::DATA_KEY_QUANTITY ][]     = $qty;
201
+			$this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] += $qty;
202
+		}
203
+	}
204
+
205
+
206
+	/**
207
+	 * @param string $input_key
208
+	 */
209
+	protected function processReturnURL(string $input_key)
210
+	{
211
+		// grab and sanitize return-url
212
+		$input_value = $this->request->getRequestParam($input_key, '', 'url');
213
+		// was the request coming from an iframe ? if so, then:
214
+		if (strpos($input_value, 'event_list=iframe')) {
215
+			// get anchor fragment
216
+			$input_value = explode('#', $input_value);
217
+			$input_value = end($input_value);
218
+			// use event list url instead, but append anchor
219
+			$input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
220
+		}
221
+		$this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
222
+	}
223
+
224
+
225
+	/**
226
+	 * @param string $input_key
227
+	 * @throws DomainException
228
+	 */
229
+	protected function processTicketIDs(string $input_key)
230
+	{
231
+		$ticket_ids          = (array) $this->request->getRequestParam($input_key, [], 'int', true);
232
+		$filtered_ticket_ids = array_filter($ticket_ids);
233
+		if (empty($filtered_ticket_ids)) {
234
+			throw new DomainException(
235
+				sprintf(
236
+					esc_html__(
237
+						'An error occurred while trying to retrieve the ticket IDs for the event.%sPlease click the back button on your browser and try again.',
238
+						'event_espresso'
239
+					),
240
+					'<br/>'
241
+				)
242
+			);
243
+		}
244
+		// cycle thru values
245
+		foreach ($ticket_ids as $key => $value) {
246
+			// allow only integers
247
+			$this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
248
+		}
249
+	}
250 250
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
         // do we have an event id?
90 90
         if ($this->event_id === null) {
91 91
             $this->event_id = $this->request->getRequestParam(self::INPUT_KEY_EVENT_ID, 0, 'int');
92
-            if (! $this->event_id) {
92
+            if ( ! $this->event_id) {
93 93
                 // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
94 94
                 throw new DomainException(
95 95
                     sprintf(
@@ -114,9 +114,9 @@  discard block
 block discarded – undo
114 114
     public function validatePostData(): array
115 115
     {
116 116
         // grab valid id
117
-        $this->valid_data[ self::DATA_KEY_EVENT_ID ] = $this->getEventId();
117
+        $this->valid_data[self::DATA_KEY_EVENT_ID] = $this->getEventId();
118 118
         // let's track the total number of tickets ordered.'
119
-        $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] = 0;
119
+        $this->valid_data[self:: DATA_KEY_TOTAL_TICKETS] = 0;
120 120
         // cycle through $inputs_to_clean array
121 121
         foreach ($this->inputs_to_clean as $what => $input_to_clean) {
122 122
             $input_key = "{$input_to_clean}{$this->event_id}";
@@ -152,7 +152,7 @@  discard block
 block discarded – undo
152 152
      */
153 153
     protected function processInteger(string $what, string $input_key)
154 154
     {
155
-        $this->valid_data[ $what ] = $this->request->getRequestParam($input_key, 0, 'int');
155
+        $this->valid_data[$what] = $this->request->getRequestParam($input_key, 0, 'int');
156 156
     }
157 157
 
158 158
 
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
     protected function processQuantity(string $input_key)
164 164
     {
165 165
         // first get number of ticket option rows
166
-        $rows    = $this->request->getRequestParam(self::INPUT_KEY_ROWS . $this->event_id, 1, 'int');
166
+        $rows    = $this->request->getRequestParam(self::INPUT_KEY_ROWS.$this->event_id, 1, 'int');
167 167
         $raw_qty = $this->request->getRequestParam($input_key);
168 168
         // explode integers by the dash if qty is a string
169 169
         $delimiter = is_string($raw_qty) && strpos($raw_qty, '-') ? '-' : '';
@@ -176,8 +176,8 @@  discard block
 block discarded – undo
176 176
             // restructure the row qty array so that $row is now the key instead of the first value
177 177
             $row_qty = [$row => $qty];
178 178
             for ($x = 1; $x <= $rows; $x++) {
179
-                if (! isset($row_qty[ $x ])) {
180
-                    $row_qty[ $x ] = 0;
179
+                if ( ! isset($row_qty[$x])) {
180
+                    $row_qty[$x] = 0;
181 181
                 }
182 182
             }
183 183
         }
@@ -197,8 +197,8 @@  discard block
 block discarded – undo
197 197
         foreach ($row_qty as $qty) {
198 198
             $qty = absint($qty);
199 199
             // sanitize as integers
200
-            $this->valid_data[ self::DATA_KEY_QUANTITY ][]     = $qty;
201
-            $this->valid_data[ self:: DATA_KEY_TOTAL_TICKETS ] += $qty;
200
+            $this->valid_data[self::DATA_KEY_QUANTITY][] = $qty;
201
+            $this->valid_data[self:: DATA_KEY_TOTAL_TICKETS] += $qty;
202 202
         }
203 203
     }
204 204
 
@@ -216,9 +216,9 @@  discard block
 block discarded – undo
216 216
             $input_value = explode('#', $input_value);
217 217
             $input_value = end($input_value);
218 218
             // use event list url instead, but append anchor
219
-            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
219
+            $input_value = EEH_Event_View::event_archive_url().'#'.$input_value;
220 220
         }
221
-        $this->valid_data[ self::DATA_KEY_RETURN_URL ] = $input_value;
221
+        $this->valid_data[self::DATA_KEY_RETURN_URL] = $input_value;
222 222
     }
223 223
 
224 224
 
@@ -244,7 +244,7 @@  discard block
 block discarded – undo
244 244
         // cycle thru values
245 245
         foreach ($ticket_ids as $key => $value) {
246 246
             // allow only integers
247
-            $this->valid_data[ self::DATA_KEY_TICKET_ID ][ $key ] = absint($value);
247
+            $this->valid_data[self::DATA_KEY_TICKET_ID][$key] = absint($value);
248 248
         }
249 249
     }
250 250
 }
Please login to merge, or discard this patch.
modules/ticket_selector/ProcessTicketSelector.php 2 patches
Indentation   +375 added lines, -375 removed lines patch added patch discarded remove patch
@@ -34,400 +34,400 @@
 block discarded – undo
34 34
 class ProcessTicketSelector
35 35
 {
36 36
 
37
-    /**
38
-     * @var EE_Cart $cart
39
-     */
40
-    private $cart;
37
+	/**
38
+	 * @var EE_Cart $cart
39
+	 */
40
+	private $cart;
41 41
 
42
-    /**
43
-     * @var EE_Core_Config $core_config
44
-     */
45
-    private $core_config;
42
+	/**
43
+	 * @var EE_Core_Config $core_config
44
+	 */
45
+	private $core_config;
46 46
 
47
-    /**
48
-     * @var RequestInterface $request
49
-     */
50
-    private $request;
47
+	/**
48
+	 * @var RequestInterface $request
49
+	 */
50
+	private $request;
51 51
 
52
-    /**
53
-     * @var EE_Session $session
54
-     */
55
-    private $session;
52
+	/**
53
+	 * @var EE_Session $session
54
+	 */
55
+	private $session;
56 56
 
57
-    /**
58
-     * @var EEM_Ticket $ticket_model
59
-     */
60
-    private $ticket_model;
57
+	/**
58
+	 * @var EEM_Ticket $ticket_model
59
+	 */
60
+	private $ticket_model;
61 61
 
62
-    /**
63
-     * @var TicketDatetimeAvailabilityTracker $tracker
64
-     */
65
-    private $tracker;
62
+	/**
63
+	 * @var TicketDatetimeAvailabilityTracker $tracker
64
+	 */
65
+	private $tracker;
66 66
 
67 67
 
68
-    /**
69
-     * ProcessTicketSelector constructor.
70
-     * NOTE: PLZ use the Loader to instantiate this class if need be
71
-     * so that all dependencies get injected correctly (which will happen automatically)
72
-     * Null values for parameters are only for backwards compatibility but will be removed later on.
73
-     *
74
-     * @param EE_Core_Config                    $core_config
75
-     * @param RequestInterface                           $request
76
-     * @param EE_Session                        $session
77
-     * @param EEM_Ticket                        $ticket_model
78
-     * @param TicketDatetimeAvailabilityTracker $tracker
79
-     * @throws InvalidArgumentException
80
-     * @throws InvalidDataTypeException
81
-     * @throws InvalidInterfaceException
82
-     */
83
-    public function __construct(
84
-        EE_Core_Config $core_config = null,
85
-        RequestInterface $request = null,
86
-        EE_Session $session = null,
87
-        EEM_Ticket $ticket_model = null,
88
-        TicketDatetimeAvailabilityTracker $tracker = null
89
-    ) {
90
-        $loader = LoaderFactory::getLoader();
91
-        $this->core_config = $core_config instanceof EE_Core_Config
92
-            ? $core_config
93
-            : $loader->getShared('EE_Core_Config');
94
-        $this->request = $request instanceof RequestInterface
95
-            ? $request
96
-            : $loader->getShared('EventEspresso\core\services\request\Request');
97
-        $this->session = $session instanceof EE_Session
98
-            ? $session
99
-            : $loader->getShared('EE_Session');
100
-        $this->ticket_model = $ticket_model instanceof EEM_Ticket
101
-            ? $ticket_model
102
-            : $loader->getShared('EEM_Ticket');
103
-        $this->tracker = $tracker instanceof TicketDatetimeAvailabilityTracker
104
-            ? $tracker
105
-            : $loader->getShared('EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker');
106
-    }
68
+	/**
69
+	 * ProcessTicketSelector constructor.
70
+	 * NOTE: PLZ use the Loader to instantiate this class if need be
71
+	 * so that all dependencies get injected correctly (which will happen automatically)
72
+	 * Null values for parameters are only for backwards compatibility but will be removed later on.
73
+	 *
74
+	 * @param EE_Core_Config                    $core_config
75
+	 * @param RequestInterface                           $request
76
+	 * @param EE_Session                        $session
77
+	 * @param EEM_Ticket                        $ticket_model
78
+	 * @param TicketDatetimeAvailabilityTracker $tracker
79
+	 * @throws InvalidArgumentException
80
+	 * @throws InvalidDataTypeException
81
+	 * @throws InvalidInterfaceException
82
+	 */
83
+	public function __construct(
84
+		EE_Core_Config $core_config = null,
85
+		RequestInterface $request = null,
86
+		EE_Session $session = null,
87
+		EEM_Ticket $ticket_model = null,
88
+		TicketDatetimeAvailabilityTracker $tracker = null
89
+	) {
90
+		$loader = LoaderFactory::getLoader();
91
+		$this->core_config = $core_config instanceof EE_Core_Config
92
+			? $core_config
93
+			: $loader->getShared('EE_Core_Config');
94
+		$this->request = $request instanceof RequestInterface
95
+			? $request
96
+			: $loader->getShared('EventEspresso\core\services\request\Request');
97
+		$this->session = $session instanceof EE_Session
98
+			? $session
99
+			: $loader->getShared('EE_Session');
100
+		$this->ticket_model = $ticket_model instanceof EEM_Ticket
101
+			? $ticket_model
102
+			: $loader->getShared('EEM_Ticket');
103
+		$this->tracker = $tracker instanceof TicketDatetimeAvailabilityTracker
104
+			? $tracker
105
+			: $loader->getShared('EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker');
106
+	}
107 107
 
108 108
 
109
-    /**
110
-     * cancelTicketSelections
111
-     *
112
-     * @return bool
113
-     * @throws EE_Error
114
-     * @throws InvalidArgumentException
115
-     * @throws InvalidInterfaceException
116
-     * @throws InvalidDataTypeException
117
-     * @throws ReflectionException
118
-     */
119
-    public function cancelTicketSelections()
120
-    {
121
-        // check nonce
122
-        if (! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
123
-            return false;
124
-        }
125
-        $this->session->clear_session(__CLASS__, __FUNCTION__);
126
-        if ($this->request->requestParamIsSet('event_id')) {
127
-            EEH_URL::safeRedirectAndExit(
128
-                EEH_Event_View::event_link_url(
129
-                    $this->request->getRequestParam('event_id', 0, 'int')
130
-                )
131
-            );
132
-        }
133
-        EEH_URL::safeRedirectAndExit(
134
-            site_url('/' . $this->core_config->event_cpt_slug . '/')
135
-        );
136
-        return true;
137
-    }
109
+	/**
110
+	 * cancelTicketSelections
111
+	 *
112
+	 * @return bool
113
+	 * @throws EE_Error
114
+	 * @throws InvalidArgumentException
115
+	 * @throws InvalidInterfaceException
116
+	 * @throws InvalidDataTypeException
117
+	 * @throws ReflectionException
118
+	 */
119
+	public function cancelTicketSelections()
120
+	{
121
+		// check nonce
122
+		if (! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
123
+			return false;
124
+		}
125
+		$this->session->clear_session(__CLASS__, __FUNCTION__);
126
+		if ($this->request->requestParamIsSet('event_id')) {
127
+			EEH_URL::safeRedirectAndExit(
128
+				EEH_Event_View::event_link_url(
129
+					$this->request->getRequestParam('event_id', 0, 'int')
130
+				)
131
+			);
132
+		}
133
+		EEH_URL::safeRedirectAndExit(
134
+			site_url('/' . $this->core_config->event_cpt_slug . '/')
135
+		);
136
+		return true;
137
+	}
138 138
 
139 139
 
140
-    /**
141
-     * processTicketSelectorNonce
142
-     *
143
-     * @param  string $nonce_name
144
-     * @param string  $id
145
-     * @return bool
146
-     */
147
-    private function processTicketSelectorNonce($nonce_name, $id = '')
148
-    {
149
-        $nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
150
-        if (
151
-            ! $this->request->isAdmin()
152
-            && (
153
-                ! $this->request->requestParamIsSet($nonce_name_with_id)
154
-                || ! wp_verify_nonce(
155
-                    $this->request->getRequestParam($nonce_name_with_id),
156
-                    $nonce_name
157
-                )
158
-            )
159
-        ) {
160
-            EE_Error::add_error(
161
-                sprintf(
162
-                    esc_html__(
163
-                        'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
164
-                        'event_espresso'
165
-                    ),
166
-                    '<br/>'
167
-                ),
168
-                __FILE__,
169
-                __FUNCTION__,
170
-                __LINE__
171
-            );
172
-            return false;
173
-        }
174
-        return true;
175
-    }
140
+	/**
141
+	 * processTicketSelectorNonce
142
+	 *
143
+	 * @param  string $nonce_name
144
+	 * @param string  $id
145
+	 * @return bool
146
+	 */
147
+	private function processTicketSelectorNonce($nonce_name, $id = '')
148
+	{
149
+		$nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
150
+		if (
151
+			! $this->request->isAdmin()
152
+			&& (
153
+				! $this->request->requestParamIsSet($nonce_name_with_id)
154
+				|| ! wp_verify_nonce(
155
+					$this->request->getRequestParam($nonce_name_with_id),
156
+					$nonce_name
157
+				)
158
+			)
159
+		) {
160
+			EE_Error::add_error(
161
+				sprintf(
162
+					esc_html__(
163
+						'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
164
+						'event_espresso'
165
+					),
166
+					'<br/>'
167
+				),
168
+				__FILE__,
169
+				__FUNCTION__,
170
+				__LINE__
171
+			);
172
+			return false;
173
+		}
174
+		return true;
175
+	}
176 176
 
177 177
 
178
-    /**
179
-     * process_ticket_selections
180
-     *
181
-     * @return bool
182
-     * @throws EE_Error
183
-     * @throws InvalidArgumentException
184
-     * @throws InvalidDataTypeException
185
-     * @throws InvalidInterfaceException
186
-     * @throws ReflectionException
187
-     */
188
-    public function processTicketSelections()
189
-    {
190
-        do_action('EED_Ticket_Selector__process_ticket_selections__before');
191
-        if ($this->request->isBot()) {
192
-            EEH_URL::safeRedirectAndExit(
193
-                apply_filters(
194
-                    'FHEE__EE_Ticket_Selector__process_ticket_selections__bot_redirect_url',
195
-                    site_url()
196
-                )
197
-            );
198
-        }
199
-        // we should really only have 1 registration in the works now
200
-        // (ie, no MER) so unless otherwise requested, clear the session
201
-        if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
202
-            $this->session->clear_session(__CLASS__, __FUNCTION__);
203
-        }
204
-        // validate/sanitize/filter data
205
-        try {
206
-            $post_data_validator = new ProcessTicketSelectorPostData($this->request);
207
-            $valid               = apply_filters(
208
-                'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data',
209
-                $post_data_validator->validatePostData()
210
-            );
211
-        } catch (Exception $exception) {
212
-            EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
213
-        }
214
-        // check total tickets ordered vs max number of attendees that can register
215
-        if (! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
216
-            $this->maxAttendeesViolation($valid);
217
-        } else {
218
-            // all data appears to be valid
219
-            if ($this->processSuccessfulCart($this->addTicketsToCart($valid))) {
220
-                return true;
221
-            }
222
-        }
223
-        // die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
224
-        // at this point, just return if registration is being made from admin
225
-        if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
226
-            return false;
227
-        }
228
-        if ($valid['return_url']) {
229
-            EEH_URL::safeRedirectAndExit($valid['return_url']);
230
-        }
231
-        // do we have an event id?
232
-        $id = $post_data_validator->getEventId();
233
-        if ($id) {
234
-            EEH_URL::safeRedirectAndExit(get_permalink($id));
235
-        }
236
-        echo EE_Error::get_notices(); // already escaped
237
-        return false;
238
-    }
178
+	/**
179
+	 * process_ticket_selections
180
+	 *
181
+	 * @return bool
182
+	 * @throws EE_Error
183
+	 * @throws InvalidArgumentException
184
+	 * @throws InvalidDataTypeException
185
+	 * @throws InvalidInterfaceException
186
+	 * @throws ReflectionException
187
+	 */
188
+	public function processTicketSelections()
189
+	{
190
+		do_action('EED_Ticket_Selector__process_ticket_selections__before');
191
+		if ($this->request->isBot()) {
192
+			EEH_URL::safeRedirectAndExit(
193
+				apply_filters(
194
+					'FHEE__EE_Ticket_Selector__process_ticket_selections__bot_redirect_url',
195
+					site_url()
196
+				)
197
+			);
198
+		}
199
+		// we should really only have 1 registration in the works now
200
+		// (ie, no MER) so unless otherwise requested, clear the session
201
+		if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
202
+			$this->session->clear_session(__CLASS__, __FUNCTION__);
203
+		}
204
+		// validate/sanitize/filter data
205
+		try {
206
+			$post_data_validator = new ProcessTicketSelectorPostData($this->request);
207
+			$valid               = apply_filters(
208
+				'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data',
209
+				$post_data_validator->validatePostData()
210
+			);
211
+		} catch (Exception $exception) {
212
+			EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
213
+		}
214
+		// check total tickets ordered vs max number of attendees that can register
215
+		if (! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
216
+			$this->maxAttendeesViolation($valid);
217
+		} else {
218
+			// all data appears to be valid
219
+			if ($this->processSuccessfulCart($this->addTicketsToCart($valid))) {
220
+				return true;
221
+			}
222
+		}
223
+		// die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
224
+		// at this point, just return if registration is being made from admin
225
+		if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
226
+			return false;
227
+		}
228
+		if ($valid['return_url']) {
229
+			EEH_URL::safeRedirectAndExit($valid['return_url']);
230
+		}
231
+		// do we have an event id?
232
+		$id = $post_data_validator->getEventId();
233
+		if ($id) {
234
+			EEH_URL::safeRedirectAndExit(get_permalink($id));
235
+		}
236
+		echo EE_Error::get_notices(); // already escaped
237
+		return false;
238
+	}
239 239
 
240 240
 
241
-    /**
242
-     * @param array $valid
243
-     */
244
-    private function maxAttendeesViolation(array $valid)
245
-    {
246
-        // ordering too many tickets !!!
247
-        $total_tickets_string = esc_html(
248
-            _n(
249
-                'You have attempted to purchase %s ticket.',
250
-                'You have attempted to purchase %s tickets.',
251
-                $valid['total_tickets'],
252
-                'event_espresso'
253
-            )
254
-        );
255
-        $limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
256
-        // dev only message
257
-        $max_attendees_string = esc_html(
258
-            _n(
259
-                'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
260
-                'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
261
-                $valid['max_atndz'],
262
-                'event_espresso'
263
-            )
264
-        );
265
-        $limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
266
-        EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
267
-    }
241
+	/**
242
+	 * @param array $valid
243
+	 */
244
+	private function maxAttendeesViolation(array $valid)
245
+	{
246
+		// ordering too many tickets !!!
247
+		$total_tickets_string = esc_html(
248
+			_n(
249
+				'You have attempted to purchase %s ticket.',
250
+				'You have attempted to purchase %s tickets.',
251
+				$valid['total_tickets'],
252
+				'event_espresso'
253
+			)
254
+		);
255
+		$limit_error_1 = sprintf($total_tickets_string, $valid['total_tickets']);
256
+		// dev only message
257
+		$max_attendees_string = esc_html(
258
+			_n(
259
+				'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
260
+				'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
261
+				$valid['max_atndz'],
262
+				'event_espresso'
263
+			)
264
+		);
265
+		$limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
266
+		EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
267
+	}
268 268
 
269 269
 
270
-    /**
271
-     * @param array $valid
272
-     * @return int
273
-     * @throws EE_Error
274
-     * @throws InvalidArgumentException
275
-     * @throws InvalidDataTypeException
276
-     * @throws InvalidInterfaceException
277
-     */
278
-    private function addTicketsToCart(array $valid)
279
-    {
280
-        $tickets_added = 0;
281
-        $tickets_selected = false;
282
-        if (! empty($valid) && $valid['total_tickets'] > 0) {
283
-            // load cart using factory because we don't want to do so until actually needed
284
-            $this->cart = CartFactory::getCart();
285
-            // if the user is an admin that can edit registrations,
286
-            // then we'll also allow them to add any tickets, even if they are expired
287
-            $current_user_is_admin = current_user_can('ee_edit_registrations');
288
-            // cycle thru the number of data rows sent from the event listing
289
-            for ($x = 0; $x < $valid['rows']; $x++) {
290
-                // does this row actually contain a ticket quantity?
291
-                if (isset($valid['qty'][ $x ]) && $valid['qty'][ $x ] > 0) {
292
-                    // YES we have a ticket quantity
293
-                    $tickets_selected = true;
294
-                    $valid_ticket = false;
295
-                    if (isset($valid['ticket_id'][ $x ])) {
296
-                        // get ticket via the ticket id we put in the form
297
-                        $ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][ $x ]);
298
-                        if ($ticket instanceof EE_Ticket && ($ticket->is_on_sale() || $current_user_is_admin)) {
299
-                            $valid_ticket = true;
300
-                            $tickets_added += $this->addTicketToCart(
301
-                                $ticket,
302
-                                $valid['qty'][ $x ]
303
-                            );
304
-                        }
305
-                    }
306
-                    if ($valid_ticket !== true) {
307
-                        // nothing added to cart retrieved
308
-                        EE_Error::add_error(
309
-                            sprintf(
310
-                                esc_html__(
311
-                                    'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
312
-                                    'event_espresso'
313
-                                ),
314
-                                '<br/>'
315
-                            ),
316
-                            __FILE__,
317
-                            __FUNCTION__,
318
-                            __LINE__
319
-                        );
320
-                    }
321
-                    if (EE_Error::has_error()) {
322
-                        break;
323
-                    }
324
-                }
325
-            }
326
-        }
327
-        do_action(
328
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
329
-            $this->cart,
330
-            $this
331
-        );
332
-        if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
333
-            // no ticket quantities were selected
334
-            EE_Error::add_error(
335
-                esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
336
-                __FILE__,
337
-                __FUNCTION__,
338
-                __LINE__
339
-            );
340
-        }
341
-        return $tickets_added;
342
-    }
270
+	/**
271
+	 * @param array $valid
272
+	 * @return int
273
+	 * @throws EE_Error
274
+	 * @throws InvalidArgumentException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws InvalidInterfaceException
277
+	 */
278
+	private function addTicketsToCart(array $valid)
279
+	{
280
+		$tickets_added = 0;
281
+		$tickets_selected = false;
282
+		if (! empty($valid) && $valid['total_tickets'] > 0) {
283
+			// load cart using factory because we don't want to do so until actually needed
284
+			$this->cart = CartFactory::getCart();
285
+			// if the user is an admin that can edit registrations,
286
+			// then we'll also allow them to add any tickets, even if they are expired
287
+			$current_user_is_admin = current_user_can('ee_edit_registrations');
288
+			// cycle thru the number of data rows sent from the event listing
289
+			for ($x = 0; $x < $valid['rows']; $x++) {
290
+				// does this row actually contain a ticket quantity?
291
+				if (isset($valid['qty'][ $x ]) && $valid['qty'][ $x ] > 0) {
292
+					// YES we have a ticket quantity
293
+					$tickets_selected = true;
294
+					$valid_ticket = false;
295
+					if (isset($valid['ticket_id'][ $x ])) {
296
+						// get ticket via the ticket id we put in the form
297
+						$ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][ $x ]);
298
+						if ($ticket instanceof EE_Ticket && ($ticket->is_on_sale() || $current_user_is_admin)) {
299
+							$valid_ticket = true;
300
+							$tickets_added += $this->addTicketToCart(
301
+								$ticket,
302
+								$valid['qty'][ $x ]
303
+							);
304
+						}
305
+					}
306
+					if ($valid_ticket !== true) {
307
+						// nothing added to cart retrieved
308
+						EE_Error::add_error(
309
+							sprintf(
310
+								esc_html__(
311
+									'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
312
+									'event_espresso'
313
+								),
314
+								'<br/>'
315
+							),
316
+							__FILE__,
317
+							__FUNCTION__,
318
+							__LINE__
319
+						);
320
+					}
321
+					if (EE_Error::has_error()) {
322
+						break;
323
+					}
324
+				}
325
+			}
326
+		}
327
+		do_action(
328
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
329
+			$this->cart,
330
+			$this
331
+		);
332
+		if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
333
+			// no ticket quantities were selected
334
+			EE_Error::add_error(
335
+				esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
336
+				__FILE__,
337
+				__FUNCTION__,
338
+				__LINE__
339
+			);
340
+		}
341
+		return $tickets_added;
342
+	}
343 343
 
344 344
 
345
-    /**
346
-     * adds a ticket to the cart
347
-     *
348
-     * @param EE_Ticket $ticket
349
-     * @param int       $qty
350
-     * @return bool TRUE on success, FALSE on fail
351
-     * @throws InvalidArgumentException
352
-     * @throws InvalidInterfaceException
353
-     * @throws InvalidDataTypeException
354
-     * @throws EE_Error
355
-     */
356
-    private function addTicketToCart(EE_Ticket $ticket, $qty = 1)
357
-    {
358
-        // get the number of spaces left for this datetime ticket
359
-        $available_spaces = $this->tracker->ticketDatetimeAvailability($ticket);
360
-        // compare available spaces against the number of tickets being purchased
361
-        if ($available_spaces >= $qty) {
362
-            // allow addons to prevent a ticket from being added to cart
363
-            if (
364
-                ! apply_filters(
365
-                    'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
366
-                    true,
367
-                    $ticket,
368
-                    $qty,
369
-                    $available_spaces
370
-                )
371
-            ) {
372
-                return false;
373
-            }
374
-            $qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
375
-            // add event to cart
376
-            if ($this->cart->add_ticket_to_cart($ticket, $qty)) {
377
-                $this->tracker->recalculateTicketDatetimeAvailability($ticket, $qty);
378
-                return true;
379
-            }
380
-            return false;
381
-        }
382
-        $this->tracker->processAvailabilityError($ticket, $qty, $this->cart->all_ticket_quantity_count());
383
-        return false;
384
-    }
345
+	/**
346
+	 * adds a ticket to the cart
347
+	 *
348
+	 * @param EE_Ticket $ticket
349
+	 * @param int       $qty
350
+	 * @return bool TRUE on success, FALSE on fail
351
+	 * @throws InvalidArgumentException
352
+	 * @throws InvalidInterfaceException
353
+	 * @throws InvalidDataTypeException
354
+	 * @throws EE_Error
355
+	 */
356
+	private function addTicketToCart(EE_Ticket $ticket, $qty = 1)
357
+	{
358
+		// get the number of spaces left for this datetime ticket
359
+		$available_spaces = $this->tracker->ticketDatetimeAvailability($ticket);
360
+		// compare available spaces against the number of tickets being purchased
361
+		if ($available_spaces >= $qty) {
362
+			// allow addons to prevent a ticket from being added to cart
363
+			if (
364
+				! apply_filters(
365
+					'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
366
+					true,
367
+					$ticket,
368
+					$qty,
369
+					$available_spaces
370
+				)
371
+			) {
372
+				return false;
373
+			}
374
+			$qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
375
+			// add event to cart
376
+			if ($this->cart->add_ticket_to_cart($ticket, $qty)) {
377
+				$this->tracker->recalculateTicketDatetimeAvailability($ticket, $qty);
378
+				return true;
379
+			}
380
+			return false;
381
+		}
382
+		$this->tracker->processAvailabilityError($ticket, $qty, $this->cart->all_ticket_quantity_count());
383
+		return false;
384
+	}
385 385
 
386 386
 
387
-    /**
388
-     * @param $tickets_added
389
-     * @return bool
390
-     * @throws InvalidInterfaceException
391
-     * @throws InvalidDataTypeException
392
-     * @throws EE_Error
393
-     * @throws InvalidArgumentException
394
-     */
395
-    private function processSuccessfulCart($tickets_added)
396
-    {
397
-        // exit('KILL REDIRECT BEFORE CART UPDATE'); // <<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
398
-        if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
399
-            // make sure cart is loaded
400
-            if (! $this->cart instanceof EE_Cart) {
401
-                $this->cart = CartFactory::getCart();
402
-            }
403
-            do_action(
404
-                'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
405
-                $this->cart,
406
-                $this
407
-            );
408
-            $this->cart->recalculate_all_cart_totals();
409
-            $this->cart->save_cart(false);
410
-            // exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
411
-            // just return TRUE for registrations being made from admin
412
-            if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
413
-                return true;
414
-            }
415
-            EEH_URL::safeRedirectAndExit(
416
-                apply_filters(
417
-                    'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
418
-                    $this->core_config->reg_page_url()
419
-                )
420
-            );
421
-        }
422
-        if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
423
-            // nothing added to cart
424
-            EE_Error::add_attention(
425
-                esc_html__('No tickets were added for the event', 'event_espresso'),
426
-                __FILE__,
427
-                __FUNCTION__,
428
-                __LINE__
429
-            );
430
-        }
431
-        return false;
432
-    }
387
+	/**
388
+	 * @param $tickets_added
389
+	 * @return bool
390
+	 * @throws InvalidInterfaceException
391
+	 * @throws InvalidDataTypeException
392
+	 * @throws EE_Error
393
+	 * @throws InvalidArgumentException
394
+	 */
395
+	private function processSuccessfulCart($tickets_added)
396
+	{
397
+		// exit('KILL REDIRECT BEFORE CART UPDATE'); // <<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
398
+		if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
399
+			// make sure cart is loaded
400
+			if (! $this->cart instanceof EE_Cart) {
401
+				$this->cart = CartFactory::getCart();
402
+			}
403
+			do_action(
404
+				'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
405
+				$this->cart,
406
+				$this
407
+			);
408
+			$this->cart->recalculate_all_cart_totals();
409
+			$this->cart->save_cart(false);
410
+			// exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
411
+			// just return TRUE for registrations being made from admin
412
+			if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
413
+				return true;
414
+			}
415
+			EEH_URL::safeRedirectAndExit(
416
+				apply_filters(
417
+					'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
418
+					$this->core_config->reg_page_url()
419
+				)
420
+			);
421
+		}
422
+		if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
423
+			// nothing added to cart
424
+			EE_Error::add_attention(
425
+				esc_html__('No tickets were added for the event', 'event_espresso'),
426
+				__FILE__,
427
+				__FUNCTION__,
428
+				__LINE__
429
+			);
430
+		}
431
+		return false;
432
+	}
433 433
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
     public function cancelTicketSelections()
120 120
     {
121 121
         // check nonce
122
-        if (! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
122
+        if ( ! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
123 123
             return false;
124 124
         }
125 125
         $this->session->clear_session(__CLASS__, __FUNCTION__);
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
             );
132 132
         }
133 133
         EEH_URL::safeRedirectAndExit(
134
-            site_url('/' . $this->core_config->event_cpt_slug . '/')
134
+            site_url('/'.$this->core_config->event_cpt_slug.'/')
135 135
         );
136 136
         return true;
137 137
     }
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
             EE_Error::add_error($exception->getMessage(), __FILE__, __FUNCTION__, __LINE__);
213 213
         }
214 214
         // check total tickets ordered vs max number of attendees that can register
215
-        if (! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
215
+        if ( ! empty($valid) && $valid['total_tickets'] > $valid['max_atndz']) {
216 216
             $this->maxAttendeesViolation($valid);
217 217
         } else {
218 218
             // all data appears to be valid
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
             )
264 264
         );
265 265
         $limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
266
-        EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
266
+        EE_Error::add_error($limit_error_1.'<br/>'.$limit_error_2, __FILE__, __FUNCTION__, __LINE__);
267 267
     }
268 268
 
269 269
 
@@ -279,7 +279,7 @@  discard block
 block discarded – undo
279 279
     {
280 280
         $tickets_added = 0;
281 281
         $tickets_selected = false;
282
-        if (! empty($valid) && $valid['total_tickets'] > 0) {
282
+        if ( ! empty($valid) && $valid['total_tickets'] > 0) {
283 283
             // load cart using factory because we don't want to do so until actually needed
284 284
             $this->cart = CartFactory::getCart();
285 285
             // if the user is an admin that can edit registrations,
@@ -288,18 +288,18 @@  discard block
 block discarded – undo
288 288
             // cycle thru the number of data rows sent from the event listing
289 289
             for ($x = 0; $x < $valid['rows']; $x++) {
290 290
                 // does this row actually contain a ticket quantity?
291
-                if (isset($valid['qty'][ $x ]) && $valid['qty'][ $x ] > 0) {
291
+                if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
292 292
                     // YES we have a ticket quantity
293 293
                     $tickets_selected = true;
294 294
                     $valid_ticket = false;
295
-                    if (isset($valid['ticket_id'][ $x ])) {
295
+                    if (isset($valid['ticket_id'][$x])) {
296 296
                         // get ticket via the ticket id we put in the form
297
-                        $ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][ $x ]);
297
+                        $ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][$x]);
298 298
                         if ($ticket instanceof EE_Ticket && ($ticket->is_on_sale() || $current_user_is_admin)) {
299 299
                             $valid_ticket = true;
300 300
                             $tickets_added += $this->addTicketToCart(
301 301
                                 $ticket,
302
-                                $valid['qty'][ $x ]
302
+                                $valid['qty'][$x]
303 303
                             );
304 304
                         }
305 305
                     }
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
             $this->cart,
330 330
             $this
331 331
         );
332
-        if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
332
+        if ( ! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
333 333
             // no ticket quantities were selected
334 334
             EE_Error::add_error(
335 335
                 esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
@@ -397,7 +397,7 @@  discard block
 block discarded – undo
397 397
         // exit('KILL REDIRECT BEFORE CART UPDATE'); // <<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
398 398
         if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
399 399
             // make sure cart is loaded
400
-            if (! $this->cart instanceof EE_Cart) {
400
+            if ( ! $this->cart instanceof EE_Cart) {
401 401
                 $this->cart = CartFactory::getCart();
402 402
             }
403 403
             do_action(
@@ -419,7 +419,7 @@  discard block
 block discarded – undo
419 419
                 )
420 420
             );
421 421
         }
422
-        if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
422
+        if ( ! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
423 423
             // nothing added to cart
424 424
             EE_Error::add_attention(
425 425
                 esc_html__('No tickets were added for the event', 'event_espresso'),
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -38,103 +38,103 @@
 block discarded – undo
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
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.6.2');
65
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                        esc_html__(
79
-                            '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.',
80
-                            'event_espresso'
81
-                        ),
82
-                        EE_MIN_PHP_VER_REQUIRED,
83
-                        PHP_VERSION,
84
-                        '<br/>',
85
-                        '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+						esc_html__(
79
+							'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.',
80
+							'event_espresso'
81
+						),
82
+						EE_MIN_PHP_VER_REQUIRED,
83
+						PHP_VERSION,
84
+						'<br/>',
85
+						'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
-        /**
98
-         * espresso_version
99
-         * Returns the plugin version
100
-         *
101
-         * @return string
102
-         */
103
-        function espresso_version()
104
-        {
105
-            return apply_filters('FHEE__espresso__espresso_version', '4.10.20.rc.004');
106
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
97
+		/**
98
+		 * espresso_version
99
+		 * Returns the plugin version
100
+		 *
101
+		 * @return string
102
+		 */
103
+		function espresso_version()
104
+		{
105
+			return apply_filters('FHEE__espresso__espresso_version', '4.10.20.rc.004');
106
+		}
107 107
 
108
-        /**
109
-         * espresso_plugin_activation
110
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
-         */
112
-        function espresso_plugin_activation()
113
-        {
114
-            update_option('ee_espresso_activation', true);
115
-        }
108
+		/**
109
+		 * espresso_plugin_activation
110
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
111
+		 */
112
+		function espresso_plugin_activation()
113
+		{
114
+			update_option('ee_espresso_activation', true);
115
+		}
116 116
 
117
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
117
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
118 118
 
119
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
120
-        bootstrap_espresso();
121
-    }
119
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
120
+		bootstrap_espresso();
121
+	}
122 122
 }
123 123
 if (! function_exists('espresso_deactivate_plugin')) {
124
-    /**
125
-     *    deactivate_plugin
126
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
-     *
128
-     * @access public
129
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
-     * @return    void
131
-     */
132
-    function espresso_deactivate_plugin($plugin_basename = '')
133
-    {
134
-        if (! function_exists('deactivate_plugins')) {
135
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
-        }
137
-        unset($_GET['activate'], $_REQUEST['activate']);
138
-        deactivate_plugins($plugin_basename);
139
-    }
124
+	/**
125
+	 *    deactivate_plugin
126
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
127
+	 *
128
+	 * @access public
129
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
130
+	 * @return    void
131
+	 */
132
+	function espresso_deactivate_plugin($plugin_basename = '')
133
+	{
134
+		if (! function_exists('deactivate_plugins')) {
135
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
136
+		}
137
+		unset($_GET['activate'], $_REQUEST['activate']);
138
+		deactivate_plugins($plugin_basename);
139
+	}
140 140
 }
Please login to merge, or discard this patch.
modules/events_archive/EED_Events_Archive.module.php 1 patch
Indentation   +1102 added lines, -1102 removed lines patch added patch discarded remove patch
@@ -16,1097 +16,1097 @@  discard block
 block discarded – undo
16 16
 class EED_Events_Archive extends EED_Module
17 17
 {
18 18
 
19
-    const EVENT_DETAILS_PRIORITY = 100;
20
-
21
-    const EVENT_DATETIMES_PRIORITY = 110;
22
-
23
-    const EVENT_TICKETS_PRIORITY = 120;
24
-
25
-    const EVENT_VENUES_PRIORITY = 130;
26
-
27
-
28
-    public static $espresso_event_list_ID = 0;
29
-
30
-    public static $espresso_grid_event_lists = array();
31
-
32
-    /**
33
-     * @type bool $using_get_the_excerpt
34
-     */
35
-    protected static $using_get_the_excerpt = false;
36
-
37
-    /**
38
-     * Used to flag when the event list is being called from an external iframe.
39
-     *
40
-     * @var bool $iframe
41
-     */
42
-    protected static $iframe = false;
43
-
44
-    /**
45
-     * @var EventListIframeEmbedButton $_iframe_embed_button
46
-     */
47
-    private static $_iframe_embed_button;
48
-
49
-    /**
50
-     * @type EE_Template_Part_Manager $template_parts
51
-     */
52
-    protected $template_parts;
53
-
54
-
55
-    /**
56
-     * @return EED_Events_Archive
57
-     */
58
-    public static function instance()
59
-    {
60
-        return parent::get_instance(__CLASS__);
61
-    }
62
-
63
-
64
-    /**
65
-     * set_hooks - for hooking into EE Core, other modules, etc
66
-     *
67
-     * @return void
68
-     * @throws InvalidArgumentException
69
-     * @throws InvalidDataTypeException
70
-     * @throws InvalidInterfaceException
71
-     */
72
-    public static function set_hooks()
73
-    {
74
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
75
-        $custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
76
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
77
-        );
78
-        $custom_post_types = $custom_post_type_definitions->getDefinitions();
79
-        EE_Config::register_route(
80
-            $custom_post_types['espresso_events']['plural_slug'],
81
-            'Events_Archive',
82
-            'run'
83
-        );
84
-        EE_Config::register_route(
85
-            'event_list',
86
-            'Events_Archive',
87
-            'event_list'
88
-        );
89
-        EE_Config::register_route(
90
-            'iframe',
91
-            'Events_Archive',
92
-            'event_list_iframe',
93
-            'event_list'
94
-        );
95
-        add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
96
-    }
97
-
98
-
99
-    /**
100
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
101
-     *
102
-     * @access    public
103
-     * @return    void
104
-     */
105
-    public static function set_hooks_admin()
106
-    {
107
-        add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
108
-        // hook into the end of the \EE_Admin_Page::_load_page_dependencies()
109
-        // to load assets for "espresso_events" page on the "default" route (action)
110
-        add_action(
111
-            'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
112
-            array('EED_Events_Archive', 'event_list_iframe_embed_button'),
113
-            10
114
-        );
115
-    }
116
-
117
-
118
-    /**
119
-     *    set_definitions
120
-     *
121
-     * @access    public
122
-     * @return    void
123
-     */
124
-    public static function set_definitions()
125
-    {
126
-        define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
127
-        define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
128
-    }
129
-
130
-
131
-    /**
132
-     * set up EE_Events_Archive_Config
133
-     */
134
-    protected function set_config()
135
-    {
136
-        $this->set_config_section('template_settings');
137
-        $this->set_config_class('EE_Events_Archive_Config');
138
-        $this->set_config_name('EED_Events_Archive');
139
-    }
140
-
141
-
142
-    /**
143
-     * @return EventListIframeEmbedButton
144
-     */
145
-    public static function get_iframe_embed_button()
146
-    {
147
-        if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
148
-            self::$_iframe_embed_button = new EventListIframeEmbedButton();
149
-        }
150
-        return self::$_iframe_embed_button;
151
-    }
152
-
153
-
154
-    /**
155
-     * event_list_iframe_embed_button
156
-     *
157
-     * @return    void
158
-     * @throws EE_Error
159
-     */
160
-    public static function event_list_iframe_embed_button()
161
-    {
162
-        $iframe_embed_button = EED_Events_Archive::get_iframe_embed_button();
163
-        $iframe_embed_button->addEmbedButton();
164
-    }
165
-
166
-
167
-    /**
168
-     *    initialize_template_parts
169
-     *
170
-     * @access    public
171
-     * @param EE_Events_Archive_Config $config
172
-     * @return EE_Template_Part_Manager
173
-     */
174
-    public function initialize_template_parts(EE_Events_Archive_Config $config = null)
175
-    {
176
-        $config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
177
-        EEH_Autoloader::instance()->register_template_part_autoloaders();
178
-        $template_parts = new EE_Template_Part_Manager();
179
-        $template_parts->add_template_part(
180
-            'tickets',
181
-            esc_html__('Ticket Selector', 'event_espresso'),
182
-            'content-espresso_events-tickets.php',
183
-            $config->display_order_tickets
184
-        );
185
-        $template_parts->add_template_part(
186
-            'datetimes',
187
-            esc_html__('Dates and Times', 'event_espresso'),
188
-            'content-espresso_events-datetimes.php',
189
-            $config->display_order_datetimes
190
-        );
191
-        $template_parts->add_template_part(
192
-            'event',
193
-            esc_html__('Event Description', 'event_espresso'),
194
-            'content-espresso_events-details.php',
195
-            $config->display_order_event
196
-        );
197
-        $template_parts->add_template_part(
198
-            'venue',
199
-            esc_html__('Venue Information', 'event_espresso'),
200
-            'content-espresso_events-venues.php',
201
-            $config->display_order_venue
202
-        );
203
-        do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
204
-        return $template_parts;
205
-    }
206
-
207
-
208
-    /**
209
-     *    run - initial module setup - this gets called by the EE_Front_Controller if the module route is found in the
210
-     *    incoming request
211
-     *
212
-     * @access    public
213
-     * @param WP $WP
214
-     * @return    void
215
-     */
216
-    public function run($WP)
217
-    {
218
-        do_action('AHEE__EED_Events_Archive__before_run');
219
-        // ensure valid EE_Events_Archive_Config() object exists
220
-        $this->set_config();
221
-        /** @type EE_Events_Archive_Config $config */
222
-        $config = $this->config();
223
-        // load other required components
224
-        $this->load_event_list_assets();
225
-        // filter the WP posts_join, posts_where, and posts_orderby SQL clauses
226
-        // add query filters
227
-        EEH_Event_Query::add_query_filters();
228
-        // set params that will get used by the filters
229
-        EEH_Event_Query::set_query_params(
230
-            '',    // month
231
-            '',    // category
232
-            $config->display_expired_events,    // show_expired
233
-            'start_date',    // orderby
234
-            'ASC'    // sort
235
-        );
236
-        // check what template is loaded
237
-        add_filter('template_include', array($this, 'template_include'), 999, 1);
238
-    }
239
-
240
-
241
-    /**
242
-     * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
243
-     *
244
-     * @return    void
245
-     */
246
-    public function event_list()
247
-    {
248
-        // ensure valid EE_Events_Archive_Config() object exists
249
-        $this->set_config();
250
-        // load other required components
251
-        $this->load_event_list_assets();
252
-    }
253
-
254
-
255
-    /**
256
-     * @access    public
257
-     * @return    void
258
-     * @throws EE_Error
259
-     * @throws DomainException
260
-     */
261
-    public function event_list_iframe()
262
-    {
263
-        EED_Events_Archive::$iframe = true;
264
-        $event_list_iframe          = new EventsArchiveIframe($this);
265
-        $event_list_iframe->display();
266
-    }
267
-
268
-
269
-    /**
270
-     * @access public
271
-     * @return string
272
-     */
273
-    public static function is_iframe()
274
-    {
275
-        return EED_Events_Archive::$iframe;
276
-    }
277
-
278
-
279
-    /**
280
-     * @access public
281
-     * @return string
282
-     */
283
-    public static function link_target()
284
-    {
285
-        return EED_Events_Archive::$iframe ? ' target="_blank"' : '';
286
-    }
287
-
288
-
289
-    /**
290
-     *    template_include
291
-     *
292
-     * @access    public
293
-     * @param string $template
294
-     * @return    string
295
-     */
296
-    public function template_include($template = '')
297
-    {
298
-        // don't add content filter for dedicated EE child themes or private posts
299
-        if (! EEH_Template::is_espresso_theme()) {
300
-            /** @type EE_Events_Archive_Config $config */
301
-            $config = $this->config();
302
-            // add status banner ?
303
-            if ($config->display_status_banner) {
304
-                add_filter('the_title', array('EED_Events_Archive', 'the_title'), 100, 2);
305
-            }
306
-            // if NOT a custom template
307
-            if (
308
-                apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
309
-                || EE_Registry::instance()
310
-                              ->load_core('Front_Controller')
311
-                              ->get_selected_template() !== 'archive-espresso_events.php'
312
-            ) {
313
-                // don't display entry meta because the existing theme will take care of that
314
-                add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
315
-                // load functions.php file for the theme (loaded by WP if using child theme)
316
-                EEH_Template::load_espresso_theme_functions();
317
-                // because we don't know if the theme is using the_excerpt()
318
-                add_filter(
319
-                    'the_excerpt',
320
-                    array('EED_Events_Archive', 'event_details'),
321
-                    EED_Events_Archive::EVENT_DETAILS_PRIORITY
322
-                );
323
-                // or the_content
324
-                add_filter(
325
-                    'the_content',
326
-                    array('EED_Events_Archive', 'event_details'),
327
-                    EED_Events_Archive::EVENT_DETAILS_PRIORITY
328
-                );
329
-                // and just in case they are running get_the_excerpt() which DESTROYS things
330
-                add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
331
-                // don't display entry meta because the existing theme will take care of that
332
-                add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
333
-            }
334
-        }
335
-        return $template;
336
-    }
337
-
338
-
339
-    /**
340
-     *    get_the_excerpt - kinda hacky, but if a theme is using get_the_excerpt(), then we need to remove our filters
341
-     *    on the_content()
342
-     *
343
-     * @access    public
344
-     * @param        string $excerpt
345
-     * @return        string
346
-     */
347
-    public static function get_the_excerpt($excerpt = '')
348
-    {
349
-        if (post_password_required()) {
350
-            return $excerpt;
351
-        }
352
-        if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
353
-            remove_filter(
354
-                'the_excerpt',
355
-                array('EED_Events_Archive', 'event_details'),
356
-                EED_Events_Archive::EVENT_DETAILS_PRIORITY
357
-            );
358
-            remove_filter(
359
-                'the_content',
360
-                array('EED_Events_Archive', 'event_details'),
361
-                EED_Events_Archive::EVENT_DETAILS_PRIORITY
362
-            );
363
-            $excerpt = EED_Events_Archive::event_details($excerpt);
364
-        } else {
365
-            EED_Events_Archive::$using_get_the_excerpt = true;
366
-            add_filter('wp_trim_excerpt', array('EED_Events_Archive', 'end_get_the_excerpt'), 999, 1);
367
-        }
368
-        return $excerpt;
369
-    }
370
-
371
-
372
-    /**
373
-     * end_get_the_excerpt
374
-     *
375
-     * @access public
376
-     * @param  string $text
377
-     * @return string
378
-     */
379
-    public static function end_get_the_excerpt($text = '')
380
-    {
381
-        EED_Events_Archive::$using_get_the_excerpt = false;
382
-        return $text;
383
-    }
384
-
385
-
386
-    /**
387
-     *    the_title
388
-     *
389
-     * @access        public
390
-     * @param        string $title
391
-     * @param        string $id
392
-     * @return        string
393
-     */
394
-    public static function the_title($title = '', $id = '')
395
-    {
396
-        global $post;
397
-        if ($post instanceof WP_Post) {
398
-            return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID) . $title : $title;
399
-        }
400
-        return $title;
401
-    }
402
-
403
-
404
-    /**
405
-     *    event_details
406
-     *
407
-     * @access    public
408
-     * @param        string $content
409
-     * @return        string
410
-     */
411
-    public static function event_details($content)
412
-    {
413
-        global $post;
414
-        static $current_post_ID = 0;
415
-        if (
416
-            $current_post_ID !== $post->ID
417
-            && $post->post_type === 'espresso_events'
418
-            && ! EED_Events_Archive::$using_get_the_excerpt
419
-            && ! post_password_required()
420
-            && (
421
-                apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
422
-                || ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
423
-            )
424
-        ) {
425
-            // Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
426
-            // Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
427
-            // BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
428
-            // We want to allow those plugins to still do their thing and have access to our content, but depending on
429
-            // how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
430
-            // so the following allows this filter to be applied multiple times, but only once for real
431
-            $current_post_ID = did_action('loop_start') ? $post->ID : 0;
432
-            if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
433
-                $content = EED_Events_Archive::use_sortable_display_order();
434
-            } else {
435
-                $content = EED_Events_Archive::use_filterable_display_order();
436
-            }
437
-        }
438
-        return $content;
439
-    }
440
-
441
-
442
-    /**
443
-     *    use_sortable_display_order
444
-     *
445
-     * @access    protected
446
-     * @return string
447
-     */
448
-    protected static function use_sortable_display_order()
449
-    {
450
-        // no further password checks required atm
451
-        add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
452
-        // we need to first remove this callback from being applied to the_content() or the_excerpt()
453
-        // (otherwise it will recurse and blow up the interweb)
454
-        remove_filter(
455
-            'the_excerpt',
456
-            array('EED_Events_Archive', 'event_details'),
457
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
458
-        );
459
-        remove_filter(
460
-            'the_content',
461
-            array('EED_Events_Archive', 'event_details'),
462
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
463
-        );
464
-        remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
465
-        // now add additional content depending on whether event is using the_excerpt() or the_content()
466
-        EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
467
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
468
-        $content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
469
-        // re-add our main filters (or else the next event won't have them)
470
-        add_filter(
471
-            'the_excerpt',
472
-            array('EED_Events_Archive', 'event_details'),
473
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
474
-        );
475
-        add_filter(
476
-            'the_content',
477
-            array('EED_Events_Archive', 'event_details'),
478
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
479
-        );
480
-        add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
481
-        remove_filter(
482
-            'FHEE__EED_Events_Archive__event_details__no_post_password_required',
483
-            '__return_true'
484
-        );
485
-        return $content;
486
-    }
487
-
488
-
489
-    /**
490
-     *    use_filterable_display_order
491
-     *
492
-     * @access    protected
493
-     * @return    string
494
-     */
495
-    protected static function use_filterable_display_order()
496
-    {
497
-        // we need to first remove this callback from being applied to the_content()
498
-        // (otherwise it will recurse and blow up the interweb)
499
-        remove_filter(
500
-            'the_excerpt',
501
-            array('EED_Events_Archive', 'event_details'),
502
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
503
-        );
504
-        remove_filter(
505
-            'the_content',
506
-            array('EED_Events_Archive', 'event_details'),
507
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
508
-        );
509
-        remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
510
-        // now add additional content depending on whether event is using the_excerpt() or the_content()
511
-        EED_Events_Archive::_add_additional_excerpt_filters();
512
-        EED_Events_Archive::_add_additional_content_filters();
513
-        do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
514
-        // now load our template
515
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
516
-        // re-add our main filters (or else the next event won't have them)
517
-        add_filter(
518
-            'the_excerpt',
519
-            array('EED_Events_Archive', 'event_details'),
520
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
521
-        );
522
-        add_filter(
523
-            'the_content',
524
-            array('EED_Events_Archive', 'event_details'),
525
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
526
-        );
527
-        add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
528
-        // but remove the other filters so that they don't get applied to the next post
529
-        EED_Events_Archive::_remove_additional_events_archive_filters();
530
-        do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
531
-        // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
532
-        // return ! empty( $template ) ? $template : $content;
533
-        return $content;
534
-    }
535
-
536
-
537
-    /**
538
-     *    event_datetimes - adds datetimes ABOVE content
539
-     *
540
-     * @access    public
541
-     * @param        string $content
542
-     * @return        string
543
-     */
544
-    public static function event_datetimes($content)
545
-    {
546
-        if (post_password_required()) {
547
-            return $content;
548
-        }
549
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
550
-    }
551
-
552
-
553
-    /**
554
-     *    event_tickets - adds tickets ABOVE content (which includes datetimes)
555
-     *
556
-     * @access    public
557
-     * @param        string $content
558
-     * @return        string
559
-     */
560
-    public static function event_tickets($content)
561
-    {
562
-        if (post_password_required()) {
563
-            return $content;
564
-        }
565
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
566
-    }
567
-
568
-
569
-    /**
570
-     *    event_venues - adds venues BELOW content
571
-     *
572
-     * @access    public
573
-     * @param    string $content
574
-     * @return    string
575
-     */
576
-    public static function event_venue($content)
577
-    {
578
-        return EED_Events_Archive::event_venues($content);
579
-    }
580
-
581
-
582
-    /**
583
-     *    event_venues - adds venues BELOW content
584
-     *
585
-     * @access    public
586
-     * @param        string $content
587
-     * @return        string
588
-     */
589
-    public static function event_venues($content)
590
-    {
591
-        if (post_password_required()) {
592
-            return $content;
593
-        }
594
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
595
-    }
596
-
597
-
598
-    /**
599
-     *    _add_additional_content_filters
600
-     *
601
-     * @access    private
602
-     * @return        void
603
-     */
604
-    private static function _add_additional_excerpt_filters()
605
-    {
606
-        add_filter(
607
-            'the_excerpt',
608
-            array('EED_Events_Archive', 'event_datetimes'),
609
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
610
-        );
611
-        add_filter(
612
-            'the_excerpt',
613
-            array('EED_Events_Archive', 'event_tickets'),
614
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
615
-        );
616
-        add_filter(
617
-            'the_excerpt',
618
-            array('EED_Events_Archive', 'event_venues'),
619
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
620
-        );
621
-    }
622
-
623
-
624
-    /**
625
-     *    _add_additional_content_filters
626
-     *
627
-     * @access    private
628
-     * @return        void
629
-     */
630
-    private static function _add_additional_content_filters()
631
-    {
632
-        add_filter(
633
-            'the_content',
634
-            array('EED_Events_Archive', 'event_datetimes'),
635
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
636
-        );
637
-        add_filter(
638
-            'the_content',
639
-            array('EED_Events_Archive', 'event_tickets'),
640
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
641
-        );
642
-        add_filter(
643
-            'the_content',
644
-            array('EED_Events_Archive', 'event_venues'),
645
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
646
-        );
647
-    }
648
-
649
-
650
-    /**
651
-     *    _remove_additional_events_archive_filters
652
-     *
653
-     * @access    private
654
-     * @return        void
655
-     */
656
-    private static function _remove_additional_events_archive_filters()
657
-    {
658
-        remove_filter(
659
-            'the_excerpt',
660
-            array('EED_Events_Archive', 'event_datetimes'),
661
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
662
-        );
663
-        remove_filter(
664
-            'the_excerpt',
665
-            array('EED_Events_Archive', 'event_tickets'),
666
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
667
-        );
668
-        remove_filter(
669
-            'the_excerpt',
670
-            array('EED_Events_Archive', 'event_venues'),
671
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
672
-        );
673
-        remove_filter(
674
-            'the_content',
675
-            array('EED_Events_Archive', 'event_datetimes'),
676
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
677
-        );
678
-        remove_filter(
679
-            'the_content',
680
-            array('EED_Events_Archive', 'event_tickets'),
681
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
682
-        );
683
-        remove_filter(
684
-            'the_content',
685
-            array('EED_Events_Archive', 'event_venues'),
686
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
687
-        );
688
-    }
689
-
690
-
691
-    /**
692
-     *    remove_all_events_archive_filters
693
-     *
694
-     * @access    public
695
-     * @return        void
696
-     */
697
-    public static function remove_all_events_archive_filters()
698
-    {
699
-        // remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
700
-        remove_filter('the_title', array('EED_Events_Archive', 'the_title'), 1);
701
-        remove_filter(
702
-            'the_excerpt',
703
-            array('EED_Events_Archive', 'event_details'),
704
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
705
-        );
706
-        remove_filter(
707
-            'the_excerpt',
708
-            array('EED_Events_Archive', 'event_datetimes'),
709
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
710
-        );
711
-        remove_filter(
712
-            'the_excerpt',
713
-            array('EED_Events_Archive', 'event_tickets'),
714
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
715
-        );
716
-        remove_filter(
717
-            'the_excerpt',
718
-            array('EED_Events_Archive', 'event_venues'),
719
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
720
-        );
721
-        remove_filter(
722
-            'the_content',
723
-            array('EED_Events_Archive', 'event_details'),
724
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
725
-        );
726
-        remove_filter(
727
-            'the_content',
728
-            array('EED_Events_Archive', 'event_datetimes'),
729
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
730
-        );
731
-        remove_filter(
732
-            'the_content',
733
-            array('EED_Events_Archive', 'event_tickets'),
734
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
735
-        );
736
-        remove_filter(
737
-            'the_content',
738
-            array('EED_Events_Archive', 'event_venues'),
739
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
740
-        );
741
-        // don't display entry meta because the existing theme will take care of that
742
-        remove_filter(
743
-            'FHEE__content_espresso_events_details_template__display_entry_meta',
744
-            '__return_false'
745
-        );
746
-    }
747
-
748
-
749
-    /**
750
-     *    load_event_list_assets
751
-     *
752
-     * @access    public
753
-     * @return    void
754
-     */
755
-    public function load_event_list_assets()
756
-    {
757
-        do_action('AHEE__EED_Events_Archive__before_load_assets');
758
-        add_filter('FHEE_load_EE_Session', '__return_true');
759
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
760
-        add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
761
-        if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
762
-            add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
763
-        }
764
-    }
765
-
766
-
767
-    /**
768
-     *    wp_enqueue_scripts
769
-     *
770
-     * @access    public
771
-     * @return    void
772
-     */
773
-    public function wp_enqueue_scripts()
774
-    {
775
-        // get some style
776
-        if (apply_filters('FHEE_enable_default_espresso_css', false)) {
777
-            // first check uploads folder
778
-            if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
779
-                wp_register_style(
780
-                    $this->theme,
781
-                    get_stylesheet_directory_uri() . $this->theme . '/style.css',
782
-                    array('dashicons', 'espresso_default')
783
-                );
784
-            } else {
785
-            }
786
-            wp_enqueue_style($this->theme);
787
-        }
788
-    }
789
-
790
-
791
-    /**
792
-     *    template_settings_form
793
-     *
794
-     * @access    public
795
-     * @static
796
-     * @return    string
797
-     */
798
-    public static function template_settings_form()
799
-    {
800
-        $template_settings = EE_Registry::instance()->CFG->template_settings;
801
-        $template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive)
802
-            ? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
803
-        $template_settings->EED_Events_Archive = apply_filters(
804
-            'FHEE__EED_Events_Archive__template_settings_form__event_list_config',
805
-            $template_settings->EED_Events_Archive
806
-        );
807
-        $events_archive_settings = array(
808
-            'display_status_banner' => 0,
809
-            'display_description' => 1,
810
-            'display_ticket_selector' => 0,
811
-            'display_datetimes' => 1,
812
-            'display_venue' => 0,
813
-            'display_expired_events' => 0,
814
-        );
815
-        $events_archive_settings = array_merge(
816
-            $events_archive_settings,
817
-            (array) $template_settings->EED_Events_Archive
818
-        );
819
-        EEH_Template::display_template(
820
-            EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php',
821
-            $events_archive_settings
822
-        );
823
-    }
824
-
825
-
826
-    /**
827
-     *    update_template_settings
828
-     *
829
-     * @access    public
830
-     * @param    EE_Template_Config $CFG
831
-     * @param    array $REQ
832
-     * @return    EE_Template_Config
833
-     */
834
-    public static function update_template_settings($CFG, $REQ)
835
-    {
836
-        $CFG->EED_Events_Archive = new EE_Events_Archive_Config();
837
-        // unless we are resetting the config...
838
-        if (
839
-            ! isset($REQ['EED_Events_Archive_reset_event_list_settings'])
840
-            || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1
841
-        ) {
842
-            $CFG->EED_Events_Archive->display_status_banner = isset($REQ['EED_Events_Archive_display_status_banner'])
843
-                ? absint($REQ['EED_Events_Archive_display_status_banner']) : 0;
844
-            $CFG->EED_Events_Archive->display_description = isset($REQ['EED_Events_Archive_display_description'])
845
-                ? absint($REQ['EED_Events_Archive_display_description']) : 1;
846
-            $CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector'])
847
-                ? absint($REQ['EED_Events_Archive_display_ticket_selector']) : 0;
848
-            $CFG->EED_Events_Archive->display_datetimes = isset($REQ['EED_Events_Archive_display_datetimes']) ? absint(
849
-                $REQ['EED_Events_Archive_display_datetimes']
850
-            ) : 1;
851
-            $CFG->EED_Events_Archive->display_venue = isset($REQ['EED_Events_Archive_display_venue']) ? absint(
852
-                $REQ['EED_Events_Archive_display_venue']
853
-            ) : 0;
854
-            $CFG->EED_Events_Archive->display_expired_events = isset($REQ['EED_Events_Archive_display_expired_events'])
855
-                ? absint($REQ['EED_Events_Archive_display_expired_events']) : 0;
856
-        }
857
-        return $CFG;
858
-    }
859
-
860
-
861
-    /**
862
-     *    event_list_css
863
-     *
864
-     * @access    public
865
-     * @param string $extra_class
866
-     * @return    string
867
-     */
868
-    public static function event_list_css($extra_class = '')
869
-    {
870
-        $event_list_css = ! empty($extra_class) ? array($extra_class) : array();
871
-        $event_list_css[] = 'espresso-event-list-event';
872
-        return implode(' ', $event_list_css);
873
-    }
874
-
875
-
876
-    /**
877
-     *    event_categories
878
-     *
879
-     * @access    public
880
-     * @return    array
881
-     */
882
-    public static function event_categories()
883
-    {
884
-        return EE_Registry::instance()->load_model('Term')->get_all_ee_categories();
885
-    }
886
-
887
-
888
-    /**
889
-     *    display_description
890
-     *
891
-     * @access    public
892
-     * @param $value
893
-     * @return    bool
894
-     */
895
-    public static function display_description($value)
896
-    {
897
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
898
-        $display_description = isset($config->display_description) ? $config->display_description : 1;
899
-        return $display_description === $value ? true : false;
900
-    }
901
-
902
-
903
-    /**
904
-     *    display_ticket_selector
905
-     *
906
-     * @access    public
907
-     * @return    bool
908
-     */
909
-    public static function display_ticket_selector()
910
-    {
911
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
912
-        return isset($config->display_ticket_selector) && $config->display_ticket_selector ? true : false;
913
-    }
914
-
915
-
916
-    /**
917
-     *    display_venue
918
-     *
919
-     * @access    public
920
-     * @return    bool
921
-     */
922
-    public static function display_venue()
923
-    {
924
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
925
-        return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name() ? true : false;
926
-    }
927
-
928
-
929
-    /**
930
-     *    display_datetimes
931
-     *
932
-     * @access    public
933
-     * @return    bool
934
-     */
935
-    public static function display_datetimes()
936
-    {
937
-        $config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
938
-        return isset($config->display_datetimes) && $config->display_datetimes ? true : false;
939
-    }
940
-
941
-
942
-    /**
943
-     *    event_list_title
944
-     *
945
-     * @access    public
946
-     * @return    string
947
-     */
948
-    public static function event_list_title()
949
-    {
950
-        return apply_filters(
951
-            'FHEE__archive_espresso_events_template__upcoming_events_h1',
952
-            esc_html__('Upcoming Events', 'event_espresso')
953
-        );
954
-    }
955
-
956
-
957
-    // GRAVEYARD
958
-
959
-
960
-    /**
961
-     * @since 4.4.0
962
-     */
963
-    public static function _doing_it_wrong_notice($function = '')
964
-    {
965
-        EE_Error::doing_it_wrong(
966
-            __FUNCTION__,
967
-            sprintf(
968
-                esc_html__(
969
-                    'EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s',
970
-                    'event_espresso'
971
-                ),
972
-                $function,
973
-                '<br />',
974
-                '4.6.0'
975
-            ),
976
-            '4.4.0'
977
-        );
978
-    }
979
-
980
-
981
-    /**
982
-     * @deprecated
983
-     * @since 4.4.0
984
-     */
985
-    public function get_post_data()
986
-    {
987
-        EEH_Event_Query::set_query_params();
988
-    }
989
-
990
-
991
-    /**
992
-     * @deprecated
993
-     * @since 4.4.0
994
-     */
995
-    public function posts_fields($SQL, WP_Query $wp_query)
996
-    {
997
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
998
-        return EEH_Event_Query::posts_fields($SQL, $wp_query);
999
-    }
1000
-
1001
-
1002
-    /**
1003
-     * @deprecated
1004
-     * @since 4.4.0
1005
-     */
1006
-    public static function posts_fields_sql_for_orderby($orderby_params = array())
1007
-    {
1008
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1009
-        return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
1010
-    }
1011
-
1012
-
1013
-    /**
1014
-     * @deprecated
1015
-     * @since 4.4.0
1016
-     */
1017
-    public function posts_join($SQL, WP_Query $wp_query)
1018
-    {
1019
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1020
-        return EEH_Event_Query::posts_join($SQL, $wp_query);
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     * @deprecated
1026
-     * @since 4.4.0
1027
-     */
1028
-    public static function posts_join_sql_for_terms($join_terms = null)
1029
-    {
1030
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1031
-        return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
1032
-    }
1033
-
1034
-
1035
-    /**
1036
-     * @deprecated
1037
-     * @since 4.4.0
1038
-     */
1039
-    public static function posts_join_for_orderby($orderby_params = array())
1040
-    {
1041
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1042
-        return EEH_Event_Query::posts_join_for_orderby($orderby_params);
1043
-    }
1044
-
1045
-
1046
-    /**
1047
-     * @deprecated
1048
-     * @since 4.4.0
1049
-     */
1050
-    public function posts_where($SQL, WP_Query $wp_query)
1051
-    {
1052
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1053
-        return EEH_Event_Query::posts_where($SQL, $wp_query);
1054
-    }
1055
-
1056
-
1057
-    /**
1058
-     * @deprecated
1059
-     * @since 4.4.0
1060
-     */
1061
-    public static function posts_where_sql_for_show_expired($show_expired = false)
1062
-    {
1063
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1064
-        return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * @deprecated
1070
-     * @since 4.4.0
1071
-     */
1072
-    public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
1073
-    {
1074
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1075
-        return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1076
-    }
1077
-
1078
-
1079
-    /**
1080
-     * @deprecated
1081
-     * @since 4.4.0
1082
-     */
1083
-    public static function posts_where_sql_for_event_list_month($month = null)
1084
-    {
1085
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1086
-        return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1087
-    }
1088
-
1089
-
1090
-    /**
1091
-     * @deprecated
1092
-     * @since 4.4.0
1093
-     */
1094
-    public function posts_orderby($SQL, WP_Query $wp_query)
1095
-    {
1096
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1097
-        return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * @deprecated
1103
-     * @since 4.4.0
1104
-     */
1105
-    public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC')
1106
-    {
1107
-        EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1108
-        return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1109
-    }
19
+	const EVENT_DETAILS_PRIORITY = 100;
20
+
21
+	const EVENT_DATETIMES_PRIORITY = 110;
22
+
23
+	const EVENT_TICKETS_PRIORITY = 120;
24
+
25
+	const EVENT_VENUES_PRIORITY = 130;
26
+
27
+
28
+	public static $espresso_event_list_ID = 0;
29
+
30
+	public static $espresso_grid_event_lists = array();
31
+
32
+	/**
33
+	 * @type bool $using_get_the_excerpt
34
+	 */
35
+	protected static $using_get_the_excerpt = false;
36
+
37
+	/**
38
+	 * Used to flag when the event list is being called from an external iframe.
39
+	 *
40
+	 * @var bool $iframe
41
+	 */
42
+	protected static $iframe = false;
43
+
44
+	/**
45
+	 * @var EventListIframeEmbedButton $_iframe_embed_button
46
+	 */
47
+	private static $_iframe_embed_button;
48
+
49
+	/**
50
+	 * @type EE_Template_Part_Manager $template_parts
51
+	 */
52
+	protected $template_parts;
53
+
54
+
55
+	/**
56
+	 * @return EED_Events_Archive
57
+	 */
58
+	public static function instance()
59
+	{
60
+		return parent::get_instance(__CLASS__);
61
+	}
62
+
63
+
64
+	/**
65
+	 * set_hooks - for hooking into EE Core, other modules, etc
66
+	 *
67
+	 * @return void
68
+	 * @throws InvalidArgumentException
69
+	 * @throws InvalidDataTypeException
70
+	 * @throws InvalidInterfaceException
71
+	 */
72
+	public static function set_hooks()
73
+	{
74
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_type_definitions */
75
+		$custom_post_type_definitions = LoaderFactory::getLoader()->getShared(
76
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
77
+		);
78
+		$custom_post_types = $custom_post_type_definitions->getDefinitions();
79
+		EE_Config::register_route(
80
+			$custom_post_types['espresso_events']['plural_slug'],
81
+			'Events_Archive',
82
+			'run'
83
+		);
84
+		EE_Config::register_route(
85
+			'event_list',
86
+			'Events_Archive',
87
+			'event_list'
88
+		);
89
+		EE_Config::register_route(
90
+			'iframe',
91
+			'Events_Archive',
92
+			'event_list_iframe',
93
+			'event_list'
94
+		);
95
+		add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
96
+	}
97
+
98
+
99
+	/**
100
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
101
+	 *
102
+	 * @access    public
103
+	 * @return    void
104
+	 */
105
+	public static function set_hooks_admin()
106
+	{
107
+		add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
108
+		// hook into the end of the \EE_Admin_Page::_load_page_dependencies()
109
+		// to load assets for "espresso_events" page on the "default" route (action)
110
+		add_action(
111
+			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
112
+			array('EED_Events_Archive', 'event_list_iframe_embed_button'),
113
+			10
114
+		);
115
+	}
116
+
117
+
118
+	/**
119
+	 *    set_definitions
120
+	 *
121
+	 * @access    public
122
+	 * @return    void
123
+	 */
124
+	public static function set_definitions()
125
+	{
126
+		define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
127
+		define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/');
128
+	}
129
+
130
+
131
+	/**
132
+	 * set up EE_Events_Archive_Config
133
+	 */
134
+	protected function set_config()
135
+	{
136
+		$this->set_config_section('template_settings');
137
+		$this->set_config_class('EE_Events_Archive_Config');
138
+		$this->set_config_name('EED_Events_Archive');
139
+	}
140
+
141
+
142
+	/**
143
+	 * @return EventListIframeEmbedButton
144
+	 */
145
+	public static function get_iframe_embed_button()
146
+	{
147
+		if (! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
148
+			self::$_iframe_embed_button = new EventListIframeEmbedButton();
149
+		}
150
+		return self::$_iframe_embed_button;
151
+	}
152
+
153
+
154
+	/**
155
+	 * event_list_iframe_embed_button
156
+	 *
157
+	 * @return    void
158
+	 * @throws EE_Error
159
+	 */
160
+	public static function event_list_iframe_embed_button()
161
+	{
162
+		$iframe_embed_button = EED_Events_Archive::get_iframe_embed_button();
163
+		$iframe_embed_button->addEmbedButton();
164
+	}
165
+
166
+
167
+	/**
168
+	 *    initialize_template_parts
169
+	 *
170
+	 * @access    public
171
+	 * @param EE_Events_Archive_Config $config
172
+	 * @return EE_Template_Part_Manager
173
+	 */
174
+	public function initialize_template_parts(EE_Events_Archive_Config $config = null)
175
+	{
176
+		$config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
177
+		EEH_Autoloader::instance()->register_template_part_autoloaders();
178
+		$template_parts = new EE_Template_Part_Manager();
179
+		$template_parts->add_template_part(
180
+			'tickets',
181
+			esc_html__('Ticket Selector', 'event_espresso'),
182
+			'content-espresso_events-tickets.php',
183
+			$config->display_order_tickets
184
+		);
185
+		$template_parts->add_template_part(
186
+			'datetimes',
187
+			esc_html__('Dates and Times', 'event_espresso'),
188
+			'content-espresso_events-datetimes.php',
189
+			$config->display_order_datetimes
190
+		);
191
+		$template_parts->add_template_part(
192
+			'event',
193
+			esc_html__('Event Description', 'event_espresso'),
194
+			'content-espresso_events-details.php',
195
+			$config->display_order_event
196
+		);
197
+		$template_parts->add_template_part(
198
+			'venue',
199
+			esc_html__('Venue Information', 'event_espresso'),
200
+			'content-espresso_events-venues.php',
201
+			$config->display_order_venue
202
+		);
203
+		do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
204
+		return $template_parts;
205
+	}
206
+
207
+
208
+	/**
209
+	 *    run - initial module setup - this gets called by the EE_Front_Controller if the module route is found in the
210
+	 *    incoming request
211
+	 *
212
+	 * @access    public
213
+	 * @param WP $WP
214
+	 * @return    void
215
+	 */
216
+	public function run($WP)
217
+	{
218
+		do_action('AHEE__EED_Events_Archive__before_run');
219
+		// ensure valid EE_Events_Archive_Config() object exists
220
+		$this->set_config();
221
+		/** @type EE_Events_Archive_Config $config */
222
+		$config = $this->config();
223
+		// load other required components
224
+		$this->load_event_list_assets();
225
+		// filter the WP posts_join, posts_where, and posts_orderby SQL clauses
226
+		// add query filters
227
+		EEH_Event_Query::add_query_filters();
228
+		// set params that will get used by the filters
229
+		EEH_Event_Query::set_query_params(
230
+			'',    // month
231
+			'',    // category
232
+			$config->display_expired_events,    // show_expired
233
+			'start_date',    // orderby
234
+			'ASC'    // sort
235
+		);
236
+		// check what template is loaded
237
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
238
+	}
239
+
240
+
241
+	/**
242
+	 * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
243
+	 *
244
+	 * @return    void
245
+	 */
246
+	public function event_list()
247
+	{
248
+		// ensure valid EE_Events_Archive_Config() object exists
249
+		$this->set_config();
250
+		// load other required components
251
+		$this->load_event_list_assets();
252
+	}
253
+
254
+
255
+	/**
256
+	 * @access    public
257
+	 * @return    void
258
+	 * @throws EE_Error
259
+	 * @throws DomainException
260
+	 */
261
+	public function event_list_iframe()
262
+	{
263
+		EED_Events_Archive::$iframe = true;
264
+		$event_list_iframe          = new EventsArchiveIframe($this);
265
+		$event_list_iframe->display();
266
+	}
267
+
268
+
269
+	/**
270
+	 * @access public
271
+	 * @return string
272
+	 */
273
+	public static function is_iframe()
274
+	{
275
+		return EED_Events_Archive::$iframe;
276
+	}
277
+
278
+
279
+	/**
280
+	 * @access public
281
+	 * @return string
282
+	 */
283
+	public static function link_target()
284
+	{
285
+		return EED_Events_Archive::$iframe ? ' target="_blank"' : '';
286
+	}
287
+
288
+
289
+	/**
290
+	 *    template_include
291
+	 *
292
+	 * @access    public
293
+	 * @param string $template
294
+	 * @return    string
295
+	 */
296
+	public function template_include($template = '')
297
+	{
298
+		// don't add content filter for dedicated EE child themes or private posts
299
+		if (! EEH_Template::is_espresso_theme()) {
300
+			/** @type EE_Events_Archive_Config $config */
301
+			$config = $this->config();
302
+			// add status banner ?
303
+			if ($config->display_status_banner) {
304
+				add_filter('the_title', array('EED_Events_Archive', 'the_title'), 100, 2);
305
+			}
306
+			// if NOT a custom template
307
+			if (
308
+				apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
309
+				|| EE_Registry::instance()
310
+							  ->load_core('Front_Controller')
311
+							  ->get_selected_template() !== 'archive-espresso_events.php'
312
+			) {
313
+				// don't display entry meta because the existing theme will take care of that
314
+				add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
315
+				// load functions.php file for the theme (loaded by WP if using child theme)
316
+				EEH_Template::load_espresso_theme_functions();
317
+				// because we don't know if the theme is using the_excerpt()
318
+				add_filter(
319
+					'the_excerpt',
320
+					array('EED_Events_Archive', 'event_details'),
321
+					EED_Events_Archive::EVENT_DETAILS_PRIORITY
322
+				);
323
+				// or the_content
324
+				add_filter(
325
+					'the_content',
326
+					array('EED_Events_Archive', 'event_details'),
327
+					EED_Events_Archive::EVENT_DETAILS_PRIORITY
328
+				);
329
+				// and just in case they are running get_the_excerpt() which DESTROYS things
330
+				add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
331
+				// don't display entry meta because the existing theme will take care of that
332
+				add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
333
+			}
334
+		}
335
+		return $template;
336
+	}
337
+
338
+
339
+	/**
340
+	 *    get_the_excerpt - kinda hacky, but if a theme is using get_the_excerpt(), then we need to remove our filters
341
+	 *    on the_content()
342
+	 *
343
+	 * @access    public
344
+	 * @param        string $excerpt
345
+	 * @return        string
346
+	 */
347
+	public static function get_the_excerpt($excerpt = '')
348
+	{
349
+		if (post_password_required()) {
350
+			return $excerpt;
351
+		}
352
+		if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
353
+			remove_filter(
354
+				'the_excerpt',
355
+				array('EED_Events_Archive', 'event_details'),
356
+				EED_Events_Archive::EVENT_DETAILS_PRIORITY
357
+			);
358
+			remove_filter(
359
+				'the_content',
360
+				array('EED_Events_Archive', 'event_details'),
361
+				EED_Events_Archive::EVENT_DETAILS_PRIORITY
362
+			);
363
+			$excerpt = EED_Events_Archive::event_details($excerpt);
364
+		} else {
365
+			EED_Events_Archive::$using_get_the_excerpt = true;
366
+			add_filter('wp_trim_excerpt', array('EED_Events_Archive', 'end_get_the_excerpt'), 999, 1);
367
+		}
368
+		return $excerpt;
369
+	}
370
+
371
+
372
+	/**
373
+	 * end_get_the_excerpt
374
+	 *
375
+	 * @access public
376
+	 * @param  string $text
377
+	 * @return string
378
+	 */
379
+	public static function end_get_the_excerpt($text = '')
380
+	{
381
+		EED_Events_Archive::$using_get_the_excerpt = false;
382
+		return $text;
383
+	}
384
+
385
+
386
+	/**
387
+	 *    the_title
388
+	 *
389
+	 * @access        public
390
+	 * @param        string $title
391
+	 * @param        string $id
392
+	 * @return        string
393
+	 */
394
+	public static function the_title($title = '', $id = '')
395
+	{
396
+		global $post;
397
+		if ($post instanceof WP_Post) {
398
+			return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID) . $title : $title;
399
+		}
400
+		return $title;
401
+	}
402
+
403
+
404
+	/**
405
+	 *    event_details
406
+	 *
407
+	 * @access    public
408
+	 * @param        string $content
409
+	 * @return        string
410
+	 */
411
+	public static function event_details($content)
412
+	{
413
+		global $post;
414
+		static $current_post_ID = 0;
415
+		if (
416
+			$current_post_ID !== $post->ID
417
+			&& $post->post_type === 'espresso_events'
418
+			&& ! EED_Events_Archive::$using_get_the_excerpt
419
+			&& ! post_password_required()
420
+			&& (
421
+				apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
422
+				|| ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
423
+			)
424
+		) {
425
+			// Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
426
+			// Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
427
+			// BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
428
+			// We want to allow those plugins to still do their thing and have access to our content, but depending on
429
+			// how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
430
+			// so the following allows this filter to be applied multiple times, but only once for real
431
+			$current_post_ID = did_action('loop_start') ? $post->ID : 0;
432
+			if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
433
+				$content = EED_Events_Archive::use_sortable_display_order();
434
+			} else {
435
+				$content = EED_Events_Archive::use_filterable_display_order();
436
+			}
437
+		}
438
+		return $content;
439
+	}
440
+
441
+
442
+	/**
443
+	 *    use_sortable_display_order
444
+	 *
445
+	 * @access    protected
446
+	 * @return string
447
+	 */
448
+	protected static function use_sortable_display_order()
449
+	{
450
+		// no further password checks required atm
451
+		add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
452
+		// we need to first remove this callback from being applied to the_content() or the_excerpt()
453
+		// (otherwise it will recurse and blow up the interweb)
454
+		remove_filter(
455
+			'the_excerpt',
456
+			array('EED_Events_Archive', 'event_details'),
457
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
458
+		);
459
+		remove_filter(
460
+			'the_content',
461
+			array('EED_Events_Archive', 'event_details'),
462
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
463
+		);
464
+		remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
465
+		// now add additional content depending on whether event is using the_excerpt() or the_content()
466
+		EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
467
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
468
+		$content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
469
+		// re-add our main filters (or else the next event won't have them)
470
+		add_filter(
471
+			'the_excerpt',
472
+			array('EED_Events_Archive', 'event_details'),
473
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
474
+		);
475
+		add_filter(
476
+			'the_content',
477
+			array('EED_Events_Archive', 'event_details'),
478
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
479
+		);
480
+		add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
481
+		remove_filter(
482
+			'FHEE__EED_Events_Archive__event_details__no_post_password_required',
483
+			'__return_true'
484
+		);
485
+		return $content;
486
+	}
487
+
488
+
489
+	/**
490
+	 *    use_filterable_display_order
491
+	 *
492
+	 * @access    protected
493
+	 * @return    string
494
+	 */
495
+	protected static function use_filterable_display_order()
496
+	{
497
+		// we need to first remove this callback from being applied to the_content()
498
+		// (otherwise it will recurse and blow up the interweb)
499
+		remove_filter(
500
+			'the_excerpt',
501
+			array('EED_Events_Archive', 'event_details'),
502
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
503
+		);
504
+		remove_filter(
505
+			'the_content',
506
+			array('EED_Events_Archive', 'event_details'),
507
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
508
+		);
509
+		remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
510
+		// now add additional content depending on whether event is using the_excerpt() or the_content()
511
+		EED_Events_Archive::_add_additional_excerpt_filters();
512
+		EED_Events_Archive::_add_additional_content_filters();
513
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
514
+		// now load our template
515
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
516
+		// re-add our main filters (or else the next event won't have them)
517
+		add_filter(
518
+			'the_excerpt',
519
+			array('EED_Events_Archive', 'event_details'),
520
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
521
+		);
522
+		add_filter(
523
+			'the_content',
524
+			array('EED_Events_Archive', 'event_details'),
525
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
526
+		);
527
+		add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
528
+		// but remove the other filters so that they don't get applied to the next post
529
+		EED_Events_Archive::_remove_additional_events_archive_filters();
530
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
531
+		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
532
+		// return ! empty( $template ) ? $template : $content;
533
+		return $content;
534
+	}
535
+
536
+
537
+	/**
538
+	 *    event_datetimes - adds datetimes ABOVE content
539
+	 *
540
+	 * @access    public
541
+	 * @param        string $content
542
+	 * @return        string
543
+	 */
544
+	public static function event_datetimes($content)
545
+	{
546
+		if (post_password_required()) {
547
+			return $content;
548
+		}
549
+		return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
550
+	}
551
+
552
+
553
+	/**
554
+	 *    event_tickets - adds tickets ABOVE content (which includes datetimes)
555
+	 *
556
+	 * @access    public
557
+	 * @param        string $content
558
+	 * @return        string
559
+	 */
560
+	public static function event_tickets($content)
561
+	{
562
+		if (post_password_required()) {
563
+			return $content;
564
+		}
565
+		return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
566
+	}
567
+
568
+
569
+	/**
570
+	 *    event_venues - adds venues BELOW content
571
+	 *
572
+	 * @access    public
573
+	 * @param    string $content
574
+	 * @return    string
575
+	 */
576
+	public static function event_venue($content)
577
+	{
578
+		return EED_Events_Archive::event_venues($content);
579
+	}
580
+
581
+
582
+	/**
583
+	 *    event_venues - adds venues BELOW content
584
+	 *
585
+	 * @access    public
586
+	 * @param        string $content
587
+	 * @return        string
588
+	 */
589
+	public static function event_venues($content)
590
+	{
591
+		if (post_password_required()) {
592
+			return $content;
593
+		}
594
+		return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
595
+	}
596
+
597
+
598
+	/**
599
+	 *    _add_additional_content_filters
600
+	 *
601
+	 * @access    private
602
+	 * @return        void
603
+	 */
604
+	private static function _add_additional_excerpt_filters()
605
+	{
606
+		add_filter(
607
+			'the_excerpt',
608
+			array('EED_Events_Archive', 'event_datetimes'),
609
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
610
+		);
611
+		add_filter(
612
+			'the_excerpt',
613
+			array('EED_Events_Archive', 'event_tickets'),
614
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
615
+		);
616
+		add_filter(
617
+			'the_excerpt',
618
+			array('EED_Events_Archive', 'event_venues'),
619
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
620
+		);
621
+	}
622
+
623
+
624
+	/**
625
+	 *    _add_additional_content_filters
626
+	 *
627
+	 * @access    private
628
+	 * @return        void
629
+	 */
630
+	private static function _add_additional_content_filters()
631
+	{
632
+		add_filter(
633
+			'the_content',
634
+			array('EED_Events_Archive', 'event_datetimes'),
635
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
636
+		);
637
+		add_filter(
638
+			'the_content',
639
+			array('EED_Events_Archive', 'event_tickets'),
640
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
641
+		);
642
+		add_filter(
643
+			'the_content',
644
+			array('EED_Events_Archive', 'event_venues'),
645
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
646
+		);
647
+	}
648
+
649
+
650
+	/**
651
+	 *    _remove_additional_events_archive_filters
652
+	 *
653
+	 * @access    private
654
+	 * @return        void
655
+	 */
656
+	private static function _remove_additional_events_archive_filters()
657
+	{
658
+		remove_filter(
659
+			'the_excerpt',
660
+			array('EED_Events_Archive', 'event_datetimes'),
661
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
662
+		);
663
+		remove_filter(
664
+			'the_excerpt',
665
+			array('EED_Events_Archive', 'event_tickets'),
666
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
667
+		);
668
+		remove_filter(
669
+			'the_excerpt',
670
+			array('EED_Events_Archive', 'event_venues'),
671
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
672
+		);
673
+		remove_filter(
674
+			'the_content',
675
+			array('EED_Events_Archive', 'event_datetimes'),
676
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
677
+		);
678
+		remove_filter(
679
+			'the_content',
680
+			array('EED_Events_Archive', 'event_tickets'),
681
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
682
+		);
683
+		remove_filter(
684
+			'the_content',
685
+			array('EED_Events_Archive', 'event_venues'),
686
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
687
+		);
688
+	}
689
+
690
+
691
+	/**
692
+	 *    remove_all_events_archive_filters
693
+	 *
694
+	 * @access    public
695
+	 * @return        void
696
+	 */
697
+	public static function remove_all_events_archive_filters()
698
+	{
699
+		// remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
700
+		remove_filter('the_title', array('EED_Events_Archive', 'the_title'), 1);
701
+		remove_filter(
702
+			'the_excerpt',
703
+			array('EED_Events_Archive', 'event_details'),
704
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
705
+		);
706
+		remove_filter(
707
+			'the_excerpt',
708
+			array('EED_Events_Archive', 'event_datetimes'),
709
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
710
+		);
711
+		remove_filter(
712
+			'the_excerpt',
713
+			array('EED_Events_Archive', 'event_tickets'),
714
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
715
+		);
716
+		remove_filter(
717
+			'the_excerpt',
718
+			array('EED_Events_Archive', 'event_venues'),
719
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
720
+		);
721
+		remove_filter(
722
+			'the_content',
723
+			array('EED_Events_Archive', 'event_details'),
724
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
725
+		);
726
+		remove_filter(
727
+			'the_content',
728
+			array('EED_Events_Archive', 'event_datetimes'),
729
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
730
+		);
731
+		remove_filter(
732
+			'the_content',
733
+			array('EED_Events_Archive', 'event_tickets'),
734
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
735
+		);
736
+		remove_filter(
737
+			'the_content',
738
+			array('EED_Events_Archive', 'event_venues'),
739
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
740
+		);
741
+		// don't display entry meta because the existing theme will take care of that
742
+		remove_filter(
743
+			'FHEE__content_espresso_events_details_template__display_entry_meta',
744
+			'__return_false'
745
+		);
746
+	}
747
+
748
+
749
+	/**
750
+	 *    load_event_list_assets
751
+	 *
752
+	 * @access    public
753
+	 * @return    void
754
+	 */
755
+	public function load_event_list_assets()
756
+	{
757
+		do_action('AHEE__EED_Events_Archive__before_load_assets');
758
+		add_filter('FHEE_load_EE_Session', '__return_true');
759
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
760
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
761
+		if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
762
+			add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
763
+		}
764
+	}
765
+
766
+
767
+	/**
768
+	 *    wp_enqueue_scripts
769
+	 *
770
+	 * @access    public
771
+	 * @return    void
772
+	 */
773
+	public function wp_enqueue_scripts()
774
+	{
775
+		// get some style
776
+		if (apply_filters('FHEE_enable_default_espresso_css', false)) {
777
+			// first check uploads folder
778
+			if (EEH_File::is_readable(get_stylesheet_directory() . $this->theme . '/style.css')) {
779
+				wp_register_style(
780
+					$this->theme,
781
+					get_stylesheet_directory_uri() . $this->theme . '/style.css',
782
+					array('dashicons', 'espresso_default')
783
+				);
784
+			} else {
785
+			}
786
+			wp_enqueue_style($this->theme);
787
+		}
788
+	}
789
+
790
+
791
+	/**
792
+	 *    template_settings_form
793
+	 *
794
+	 * @access    public
795
+	 * @static
796
+	 * @return    string
797
+	 */
798
+	public static function template_settings_form()
799
+	{
800
+		$template_settings = EE_Registry::instance()->CFG->template_settings;
801
+		$template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive)
802
+			? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
803
+		$template_settings->EED_Events_Archive = apply_filters(
804
+			'FHEE__EED_Events_Archive__template_settings_form__event_list_config',
805
+			$template_settings->EED_Events_Archive
806
+		);
807
+		$events_archive_settings = array(
808
+			'display_status_banner' => 0,
809
+			'display_description' => 1,
810
+			'display_ticket_selector' => 0,
811
+			'display_datetimes' => 1,
812
+			'display_venue' => 0,
813
+			'display_expired_events' => 0,
814
+		);
815
+		$events_archive_settings = array_merge(
816
+			$events_archive_settings,
817
+			(array) $template_settings->EED_Events_Archive
818
+		);
819
+		EEH_Template::display_template(
820
+			EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php',
821
+			$events_archive_settings
822
+		);
823
+	}
824
+
825
+
826
+	/**
827
+	 *    update_template_settings
828
+	 *
829
+	 * @access    public
830
+	 * @param    EE_Template_Config $CFG
831
+	 * @param    array $REQ
832
+	 * @return    EE_Template_Config
833
+	 */
834
+	public static function update_template_settings($CFG, $REQ)
835
+	{
836
+		$CFG->EED_Events_Archive = new EE_Events_Archive_Config();
837
+		// unless we are resetting the config...
838
+		if (
839
+			! isset($REQ['EED_Events_Archive_reset_event_list_settings'])
840
+			|| absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1
841
+		) {
842
+			$CFG->EED_Events_Archive->display_status_banner = isset($REQ['EED_Events_Archive_display_status_banner'])
843
+				? absint($REQ['EED_Events_Archive_display_status_banner']) : 0;
844
+			$CFG->EED_Events_Archive->display_description = isset($REQ['EED_Events_Archive_display_description'])
845
+				? absint($REQ['EED_Events_Archive_display_description']) : 1;
846
+			$CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector'])
847
+				? absint($REQ['EED_Events_Archive_display_ticket_selector']) : 0;
848
+			$CFG->EED_Events_Archive->display_datetimes = isset($REQ['EED_Events_Archive_display_datetimes']) ? absint(
849
+				$REQ['EED_Events_Archive_display_datetimes']
850
+			) : 1;
851
+			$CFG->EED_Events_Archive->display_venue = isset($REQ['EED_Events_Archive_display_venue']) ? absint(
852
+				$REQ['EED_Events_Archive_display_venue']
853
+			) : 0;
854
+			$CFG->EED_Events_Archive->display_expired_events = isset($REQ['EED_Events_Archive_display_expired_events'])
855
+				? absint($REQ['EED_Events_Archive_display_expired_events']) : 0;
856
+		}
857
+		return $CFG;
858
+	}
859
+
860
+
861
+	/**
862
+	 *    event_list_css
863
+	 *
864
+	 * @access    public
865
+	 * @param string $extra_class
866
+	 * @return    string
867
+	 */
868
+	public static function event_list_css($extra_class = '')
869
+	{
870
+		$event_list_css = ! empty($extra_class) ? array($extra_class) : array();
871
+		$event_list_css[] = 'espresso-event-list-event';
872
+		return implode(' ', $event_list_css);
873
+	}
874
+
875
+
876
+	/**
877
+	 *    event_categories
878
+	 *
879
+	 * @access    public
880
+	 * @return    array
881
+	 */
882
+	public static function event_categories()
883
+	{
884
+		return EE_Registry::instance()->load_model('Term')->get_all_ee_categories();
885
+	}
886
+
887
+
888
+	/**
889
+	 *    display_description
890
+	 *
891
+	 * @access    public
892
+	 * @param $value
893
+	 * @return    bool
894
+	 */
895
+	public static function display_description($value)
896
+	{
897
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
898
+		$display_description = isset($config->display_description) ? $config->display_description : 1;
899
+		return $display_description === $value ? true : false;
900
+	}
901
+
902
+
903
+	/**
904
+	 *    display_ticket_selector
905
+	 *
906
+	 * @access    public
907
+	 * @return    bool
908
+	 */
909
+	public static function display_ticket_selector()
910
+	{
911
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
912
+		return isset($config->display_ticket_selector) && $config->display_ticket_selector ? true : false;
913
+	}
914
+
915
+
916
+	/**
917
+	 *    display_venue
918
+	 *
919
+	 * @access    public
920
+	 * @return    bool
921
+	 */
922
+	public static function display_venue()
923
+	{
924
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
925
+		return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name() ? true : false;
926
+	}
927
+
928
+
929
+	/**
930
+	 *    display_datetimes
931
+	 *
932
+	 * @access    public
933
+	 * @return    bool
934
+	 */
935
+	public static function display_datetimes()
936
+	{
937
+		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
938
+		return isset($config->display_datetimes) && $config->display_datetimes ? true : false;
939
+	}
940
+
941
+
942
+	/**
943
+	 *    event_list_title
944
+	 *
945
+	 * @access    public
946
+	 * @return    string
947
+	 */
948
+	public static function event_list_title()
949
+	{
950
+		return apply_filters(
951
+			'FHEE__archive_espresso_events_template__upcoming_events_h1',
952
+			esc_html__('Upcoming Events', 'event_espresso')
953
+		);
954
+	}
955
+
956
+
957
+	// GRAVEYARD
958
+
959
+
960
+	/**
961
+	 * @since 4.4.0
962
+	 */
963
+	public static function _doing_it_wrong_notice($function = '')
964
+	{
965
+		EE_Error::doing_it_wrong(
966
+			__FUNCTION__,
967
+			sprintf(
968
+				esc_html__(
969
+					'EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s',
970
+					'event_espresso'
971
+				),
972
+				$function,
973
+				'<br />',
974
+				'4.6.0'
975
+			),
976
+			'4.4.0'
977
+		);
978
+	}
979
+
980
+
981
+	/**
982
+	 * @deprecated
983
+	 * @since 4.4.0
984
+	 */
985
+	public function get_post_data()
986
+	{
987
+		EEH_Event_Query::set_query_params();
988
+	}
989
+
990
+
991
+	/**
992
+	 * @deprecated
993
+	 * @since 4.4.0
994
+	 */
995
+	public function posts_fields($SQL, WP_Query $wp_query)
996
+	{
997
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
998
+		return EEH_Event_Query::posts_fields($SQL, $wp_query);
999
+	}
1000
+
1001
+
1002
+	/**
1003
+	 * @deprecated
1004
+	 * @since 4.4.0
1005
+	 */
1006
+	public static function posts_fields_sql_for_orderby($orderby_params = array())
1007
+	{
1008
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1009
+		return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
1010
+	}
1011
+
1012
+
1013
+	/**
1014
+	 * @deprecated
1015
+	 * @since 4.4.0
1016
+	 */
1017
+	public function posts_join($SQL, WP_Query $wp_query)
1018
+	{
1019
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1020
+		return EEH_Event_Query::posts_join($SQL, $wp_query);
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 * @deprecated
1026
+	 * @since 4.4.0
1027
+	 */
1028
+	public static function posts_join_sql_for_terms($join_terms = null)
1029
+	{
1030
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1031
+		return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
1032
+	}
1033
+
1034
+
1035
+	/**
1036
+	 * @deprecated
1037
+	 * @since 4.4.0
1038
+	 */
1039
+	public static function posts_join_for_orderby($orderby_params = array())
1040
+	{
1041
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1042
+		return EEH_Event_Query::posts_join_for_orderby($orderby_params);
1043
+	}
1044
+
1045
+
1046
+	/**
1047
+	 * @deprecated
1048
+	 * @since 4.4.0
1049
+	 */
1050
+	public function posts_where($SQL, WP_Query $wp_query)
1051
+	{
1052
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1053
+		return EEH_Event_Query::posts_where($SQL, $wp_query);
1054
+	}
1055
+
1056
+
1057
+	/**
1058
+	 * @deprecated
1059
+	 * @since 4.4.0
1060
+	 */
1061
+	public static function posts_where_sql_for_show_expired($show_expired = false)
1062
+	{
1063
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1064
+		return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * @deprecated
1070
+	 * @since 4.4.0
1071
+	 */
1072
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = null)
1073
+	{
1074
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1075
+		return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1076
+	}
1077
+
1078
+
1079
+	/**
1080
+	 * @deprecated
1081
+	 * @since 4.4.0
1082
+	 */
1083
+	public static function posts_where_sql_for_event_list_month($month = null)
1084
+	{
1085
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1086
+		return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1087
+	}
1088
+
1089
+
1090
+	/**
1091
+	 * @deprecated
1092
+	 * @since 4.4.0
1093
+	 */
1094
+	public function posts_orderby($SQL, WP_Query $wp_query)
1095
+	{
1096
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1097
+		return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * @deprecated
1103
+	 * @since 4.4.0
1104
+	 */
1105
+	public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC')
1106
+	{
1107
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1108
+		return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1109
+	}
1110 1110
 }
1111 1111
 
1112 1112
 
@@ -1115,9 +1115,9 @@  discard block
 block discarded – undo
1115 1115
  */
1116 1116
 function espresso_get_event_list_ID()
1117 1117
 {
1118
-    EED_Events_Archive::$espresso_event_list_ID++;
1119
-    EED_Events_Archive::$espresso_grid_event_lists[] = EED_Events_Archive::$espresso_event_list_ID;
1120
-    return EED_Events_Archive::$espresso_event_list_ID;
1118
+	EED_Events_Archive::$espresso_event_list_ID++;
1119
+	EED_Events_Archive::$espresso_grid_event_lists[] = EED_Events_Archive::$espresso_event_list_ID;
1120
+	return EED_Events_Archive::$espresso_event_list_ID;
1121 1121
 }
1122 1122
 
1123 1123
 /**
@@ -1125,7 +1125,7 @@  discard block
 block discarded – undo
1125 1125
  */
1126 1126
 function espresso_event_list_title()
1127 1127
 {
1128
-    return EED_Events_Archive::event_list_title();
1128
+	return EED_Events_Archive::event_list_title();
1129 1129
 }
1130 1130
 
1131 1131
 /**
@@ -1134,7 +1134,7 @@  discard block
 block discarded – undo
1134 1134
  */
1135 1135
 function espresso_event_list_css($extra_class = '')
1136 1136
 {
1137
-    return EED_Events_Archive::event_list_css($extra_class);
1137
+	return EED_Events_Archive::event_list_css($extra_class);
1138 1138
 }
1139 1139
 
1140 1140
 /**
@@ -1142,7 +1142,7 @@  discard block
 block discarded – undo
1142 1142
  */
1143 1143
 function espresso_get_event_categories()
1144 1144
 {
1145
-    return EED_Events_Archive::event_categories();
1145
+	return EED_Events_Archive::event_categories();
1146 1146
 }
1147 1147
 
1148 1148
 /**
@@ -1150,7 +1150,7 @@  discard block
 block discarded – undo
1150 1150
  */
1151 1151
 function espresso_display_full_description_in_event_list()
1152 1152
 {
1153
-    return EED_Events_Archive::display_description(2);
1153
+	return EED_Events_Archive::display_description(2);
1154 1154
 }
1155 1155
 
1156 1156
 /**
@@ -1158,7 +1158,7 @@  discard block
 block discarded – undo
1158 1158
  */
1159 1159
 function espresso_display_excerpt_in_event_list()
1160 1160
 {
1161
-    return EED_Events_Archive::display_description(1);
1161
+	return EED_Events_Archive::display_description(1);
1162 1162
 }
1163 1163
 
1164 1164
 /**
@@ -1166,7 +1166,7 @@  discard block
 block discarded – undo
1166 1166
  */
1167 1167
 function espresso_display_ticket_selector_in_event_list()
1168 1168
 {
1169
-    return EED_Events_Archive::display_ticket_selector();
1169
+	return EED_Events_Archive::display_ticket_selector();
1170 1170
 }
1171 1171
 
1172 1172
 /**
@@ -1174,7 +1174,7 @@  discard block
 block discarded – undo
1174 1174
  */
1175 1175
 function espresso_display_venue_in_event_list()
1176 1176
 {
1177
-    return EED_Events_Archive::display_venue();
1177
+	return EED_Events_Archive::display_venue();
1178 1178
 }
1179 1179
 
1180 1180
 /**
@@ -1182,5 +1182,5 @@  discard block
 block discarded – undo
1182 1182
  */
1183 1183
 function espresso_display_datetimes_in_event_list()
1184 1184
 {
1185
-    return EED_Events_Archive::display_datetimes();
1185
+	return EED_Events_Archive::display_datetimes();
1186 1186
 }
Please login to merge, or discard this patch.
core/EE_System.core.php 2 patches
Indentation   +1310 added lines, -1310 removed lines patch added patch discarded remove patch
@@ -27,1314 +27,1314 @@
 block discarded – undo
27 27
 final class EE_System implements ResettableInterface
28 28
 {
29 29
 
30
-    /**
31
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
-     */
34
-    const req_type_normal = 0;
35
-
36
-    /**
37
-     * Indicates this is a brand new installation of EE so we should install
38
-     * tables and default data etc
39
-     */
40
-    const req_type_new_activation = 1;
41
-
42
-    /**
43
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
-     * and we just exited maintenance mode). We MUST check the database is setup properly
45
-     * and that default data is setup too
46
-     */
47
-    const req_type_reactivation = 2;
48
-
49
-    /**
50
-     * indicates that EE has been upgraded since its previous request.
51
-     * We may have data migration scripts to call and will want to trigger maintenance mode
52
-     */
53
-    const req_type_upgrade = 3;
54
-
55
-    /**
56
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
-     */
58
-    const req_type_downgrade = 4;
59
-
60
-    /**
61
-     * @deprecated since version 4.6.0.dev.006
62
-     * Now whenever a new_activation is detected the request type is still just
63
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
-     * (Specifically, when the migration manager indicates migrations are finished
67
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
-     */
69
-    const req_type_activation_but_not_installed = 5;
70
-
71
-    /**
72
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
-     */
74
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
-
76
-    /**
77
-     * @var EE_System $_instance
78
-     */
79
-    private static $_instance;
80
-
81
-    /**
82
-     * @var EE_Registry $registry
83
-     */
84
-    private $registry;
85
-
86
-    /**
87
-     * @var LoaderInterface $loader
88
-     */
89
-    private $loader;
90
-
91
-    /**
92
-     * @var EE_Capabilities $capabilities
93
-     */
94
-    private $capabilities;
95
-
96
-    /**
97
-     * @var RequestInterface $request
98
-     */
99
-    private $request;
100
-
101
-    /**
102
-     * @var EE_Maintenance_Mode $maintenance_mode
103
-     */
104
-    private $maintenance_mode;
105
-
106
-    /**
107
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
-     *
110
-     * @var int $_req_type
111
-     */
112
-    private $_req_type;
113
-
114
-    /**
115
-     * Whether or not there was a non-micro version change in EE core version during this request
116
-     *
117
-     * @var boolean $_major_version_change
118
-     */
119
-    private $_major_version_change = false;
120
-
121
-    /**
122
-     * A Context DTO dedicated solely to identifying the current request type.
123
-     *
124
-     * @var RequestTypeContextCheckerInterface $request_type
125
-     */
126
-    private $request_type;
127
-
128
-
129
-    /**
130
-     * @singleton method used to instantiate class object
131
-     * @param EE_Registry|null         $registry
132
-     * @param LoaderInterface|null     $loader
133
-     * @param RequestInterface|null    $request
134
-     * @param EE_Maintenance_Mode|null $maintenance_mode
135
-     * @return EE_System
136
-     */
137
-    public static function instance(
138
-        EE_Registry $registry = null,
139
-        LoaderInterface $loader = null,
140
-        RequestInterface $request = null,
141
-        EE_Maintenance_Mode $maintenance_mode = null
142
-    ) {
143
-        // check if class object is instantiated
144
-        if (! self::$_instance instanceof EE_System) {
145
-            self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
146
-        }
147
-        return self::$_instance;
148
-    }
149
-
150
-
151
-    /**
152
-     * resets the instance and returns it
153
-     *
154
-     * @return EE_System
155
-     */
156
-    public static function reset()
157
-    {
158
-        self::$_instance->_req_type = null;
159
-        // make sure none of the old hooks are left hanging around
160
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
-        // we need to reset the migration manager in order for it to detect DMSs properly
162
-        EE_Data_Migration_Manager::reset();
163
-        self::instance()->detect_activations_or_upgrades();
164
-        self::instance()->perform_activations_upgrades_and_migrations();
165
-        return self::instance();
166
-    }
167
-
168
-
169
-    /**
170
-     * sets hooks for running rest of system
171
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
-     * starting EE Addons from any other point may lead to problems
173
-     *
174
-     * @param EE_Registry         $registry
175
-     * @param LoaderInterface     $loader
176
-     * @param RequestInterface    $request
177
-     * @param EE_Maintenance_Mode $maintenance_mode
178
-     */
179
-    private function __construct(
180
-        EE_Registry $registry,
181
-        LoaderInterface $loader,
182
-        RequestInterface $request,
183
-        EE_Maintenance_Mode $maintenance_mode
184
-    ) {
185
-        $this->registry = $registry;
186
-        $this->loader = $loader;
187
-        $this->request = $request;
188
-        $this->maintenance_mode = $maintenance_mode;
189
-        do_action('AHEE__EE_System__construct__begin', $this);
190
-        add_action(
191
-            'AHEE__EE_Bootstrap__load_espresso_addons',
192
-            array($this, 'loadCapabilities'),
193
-            5
194
-        );
195
-        add_action(
196
-            'AHEE__EE_Bootstrap__load_espresso_addons',
197
-            array($this, 'loadCommandBus'),
198
-            7
199
-        );
200
-        add_action(
201
-            'AHEE__EE_Bootstrap__load_espresso_addons',
202
-            array($this, 'loadPluginApi'),
203
-            9
204
-        );
205
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
206
-        add_action(
207
-            'AHEE__EE_Bootstrap__load_espresso_addons',
208
-            array($this, 'load_espresso_addons')
209
-        );
210
-        // when an ee addon is activated, we want to call the core hook(s) again
211
-        // because the newly-activated addon didn't get a chance to run at all
212
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
213
-        // detect whether install or upgrade
214
-        add_action(
215
-            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
216
-            array($this, 'detect_activations_or_upgrades'),
217
-            3
218
-        );
219
-        // load EE_Config, EE_Textdomain, etc
220
-        add_action(
221
-            'AHEE__EE_Bootstrap__load_core_configuration',
222
-            array($this, 'load_core_configuration'),
223
-            5
224
-        );
225
-        // load specifications for matching routes to current request
226
-        add_action(
227
-            'AHEE__EE_Bootstrap__load_core_configuration',
228
-            array($this, 'loadRouteMatchSpecifications')
229
-        );
230
-        // load EE_Config, EE_Textdomain, etc
231
-        add_action(
232
-            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
233
-            array($this, 'register_shortcodes_modules_and_widgets'),
234
-            7
235
-        );
236
-        // you wanna get going? I wanna get going... let's get going!
237
-        add_action(
238
-            'AHEE__EE_Bootstrap__brew_espresso',
239
-            array($this, 'brew_espresso'),
240
-            9
241
-        );
242
-        // other housekeeping
243
-        // exclude EE critical pages from wp_list_pages
244
-        add_filter(
245
-            'wp_list_pages_excludes',
246
-            array($this, 'remove_pages_from_wp_list_pages'),
247
-            10
248
-        );
249
-        // ALL EE Addons should use the following hook point to attach their initial setup too
250
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
251
-        do_action('AHEE__EE_System__construct__complete', $this);
252
-    }
253
-
254
-
255
-    /**
256
-     * load and setup EE_Capabilities
257
-     *
258
-     * @return void
259
-     * @throws EE_Error
260
-     */
261
-    public function loadCapabilities()
262
-    {
263
-        $this->capabilities = $this->loader->getShared('EE_Capabilities');
264
-        add_action(
265
-            'AHEE__EE_Capabilities__init_caps__before_initialization',
266
-            function () {
267
-                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
268
-            }
269
-        );
270
-    }
271
-
272
-
273
-    /**
274
-     * create and cache the CommandBus, and also add middleware
275
-     * The CapChecker middleware requires the use of EE_Capabilities
276
-     * which is why we need to load the CommandBus after Caps are set up
277
-     *
278
-     * @return void
279
-     * @throws EE_Error
280
-     */
281
-    public function loadCommandBus()
282
-    {
283
-        $this->loader->getShared(
284
-            'CommandBusInterface',
285
-            array(
286
-                null,
287
-                apply_filters(
288
-                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
289
-                    array(
290
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
291
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
292
-                    )
293
-                ),
294
-            )
295
-        );
296
-    }
297
-
298
-
299
-    /**
300
-     * @return void
301
-     * @throws EE_Error
302
-     */
303
-    public function loadPluginApi()
304
-    {
305
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
306
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
307
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
308
-    }
309
-
310
-
311
-    /**
312
-     * @param string $addon_name
313
-     * @param string $version_constant
314
-     * @param string $min_version_required
315
-     * @param string $load_callback
316
-     * @param string $plugin_file_constant
317
-     * @return void
318
-     */
319
-    private function deactivateIncompatibleAddon(
320
-        $addon_name,
321
-        $version_constant,
322
-        $min_version_required,
323
-        $load_callback,
324
-        $plugin_file_constant
325
-    ) {
326
-        if (! defined($version_constant)) {
327
-            return;
328
-        }
329
-        $addon_version = constant($version_constant);
330
-        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
331
-            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
332
-            if (! function_exists('deactivate_plugins')) {
333
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
334
-            }
335
-            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
336
-            $this->request->unSetRequestParams(['activate', 'activate-multi'], true);
337
-            EE_Error::add_error(
338
-                sprintf(
339
-                    esc_html__(
340
-                        'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
341
-                        'event_espresso'
342
-                    ),
343
-                    $addon_name,
344
-                    $min_version_required
345
-                ),
346
-                __FILE__,
347
-                __FUNCTION__ . "({$addon_name})",
348
-                __LINE__
349
-            );
350
-            EE_Error::get_notices(false, true);
351
-        }
352
-    }
353
-
354
-
355
-    /**
356
-     * load_espresso_addons
357
-     * allow addons to load first so that they can set hooks for running DMS's, etc
358
-     * this is hooked into both:
359
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
360
-     *        which runs during the WP 'plugins_loaded' action at priority 5
361
-     *    and the WP 'activate_plugin' hook point
362
-     *
363
-     * @access public
364
-     * @return void
365
-     */
366
-    public function load_espresso_addons()
367
-    {
368
-        $this->deactivateIncompatibleAddon(
369
-            'Wait Lists',
370
-            'EE_WAIT_LISTS_VERSION',
371
-            '1.0.0.beta.074',
372
-            'load_espresso_wait_lists',
373
-            'EE_WAIT_LISTS_PLUGIN_FILE'
374
-        );
375
-        $this->deactivateIncompatibleAddon(
376
-            'Automated Upcoming Event Notifications',
377
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
378
-            '1.0.0.beta.091',
379
-            'load_espresso_automated_upcoming_event_notification',
380
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
381
-        );
382
-        do_action('AHEE__EE_System__load_espresso_addons');
383
-        // if the WP API basic auth plugin isn't already loaded, load it now.
384
-        // We want it for mobile apps. Just include the entire plugin
385
-        // also, don't load the basic auth when a plugin is getting activated, because
386
-        // it could be the basic auth plugin, and it doesn't check if its methods are already defined
387
-        // and causes a fatal error
388
-        if (
389
-            ($this->request->isWordPressApi() || $this->request->isApi())
390
-            && $this->request->getRequestParam('activate') !== 'true'
391
-            && ! function_exists('json_basic_auth_handler')
392
-            && ! function_exists('json_basic_auth_error')
393
-            && ! in_array(
394
-                $this->request->getRequestParam('action'),
395
-                array('activate', 'activate-selected'),
396
-                true
397
-            )
398
-        ) {
399
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth/basic-auth.php';
400
-        }
401
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
402
-    }
403
-
404
-
405
-    /**
406
-     * detect_activations_or_upgrades
407
-     * Checks for activation or upgrade of core first;
408
-     * then also checks if any registered addons have been activated or upgraded
409
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
410
-     * which runs during the WP 'plugins_loaded' action at priority 3
411
-     *
412
-     * @access public
413
-     * @return void
414
-     */
415
-    public function detect_activations_or_upgrades()
416
-    {
417
-        // first off: let's make sure to handle core
418
-        $this->detect_if_activation_or_upgrade();
419
-        foreach ($this->registry->addons as $addon) {
420
-            if ($addon instanceof EE_Addon) {
421
-                // detect teh request type for that addon
422
-                $addon->detect_req_type();
423
-            }
424
-        }
425
-    }
426
-
427
-
428
-    /**
429
-     * detect_if_activation_or_upgrade
430
-     * Takes care of detecting whether this is a brand new install or code upgrade,
431
-     * and either setting up the DB or setting up maintenance mode etc.
432
-     *
433
-     * @access public
434
-     * @return void
435
-     */
436
-    public function detect_if_activation_or_upgrade()
437
-    {
438
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
439
-        // check if db has been updated, or if its a brand-new installation
440
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
441
-        $request_type = $this->detect_req_type($espresso_db_update);
442
-        // EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
443
-        switch ($request_type) {
444
-            case EE_System::req_type_new_activation:
445
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
446
-                $this->_handle_core_version_change($espresso_db_update);
447
-                break;
448
-            case EE_System::req_type_reactivation:
449
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
450
-                $this->_handle_core_version_change($espresso_db_update);
451
-                break;
452
-            case EE_System::req_type_upgrade:
453
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
454
-                // migrations may be required now that we've upgraded
455
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
456
-                $this->_handle_core_version_change($espresso_db_update);
457
-                break;
458
-            case EE_System::req_type_downgrade:
459
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
460
-                // its possible migrations are no longer required
461
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
462
-                $this->_handle_core_version_change($espresso_db_update);
463
-                break;
464
-            case EE_System::req_type_normal:
465
-            default:
466
-                break;
467
-        }
468
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
469
-    }
470
-
471
-
472
-    /**
473
-     * Updates the list of installed versions and sets hooks for
474
-     * initializing the database later during the request
475
-     *
476
-     * @param array $espresso_db_update
477
-     */
478
-    private function _handle_core_version_change($espresso_db_update)
479
-    {
480
-        $this->update_list_of_installed_versions($espresso_db_update);
481
-        // get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
482
-        add_action(
483
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
484
-            array($this, 'initialize_db_if_no_migrations_required')
485
-        );
486
-    }
487
-
488
-
489
-    /**
490
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
491
-     * information about what versions of EE have been installed and activated,
492
-     * NOT necessarily the state of the database
493
-     *
494
-     * @param mixed $espresso_db_update           the value of the WordPress option.
495
-     *                                            If not supplied, fetches it from the options table
496
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
497
-     */
498
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
499
-    {
500
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
501
-        if (! $espresso_db_update) {
502
-            $espresso_db_update = get_option('espresso_db_update');
503
-        }
504
-        // check that option is an array
505
-        if (! is_array($espresso_db_update)) {
506
-            // if option is FALSE, then it never existed
507
-            if ($espresso_db_update === false) {
508
-                // make $espresso_db_update an array and save option with autoload OFF
509
-                $espresso_db_update = array();
510
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
511
-            } else {
512
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
513
-                $espresso_db_update = array($espresso_db_update => array());
514
-                update_option('espresso_db_update', $espresso_db_update);
515
-            }
516
-        } else {
517
-            $corrected_db_update = array();
518
-            // if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
519
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
520
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
521
-                    // the key is an int, and the value IS NOT an array
522
-                    // so it must be numerically-indexed, where values are versions installed...
523
-                    // fix it!
524
-                    $version_string = $should_be_array;
525
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
526
-                } else {
527
-                    // ok it checks out
528
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
529
-                }
530
-            }
531
-            $espresso_db_update = $corrected_db_update;
532
-            update_option('espresso_db_update', $espresso_db_update);
533
-        }
534
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
535
-        return $espresso_db_update;
536
-    }
537
-
538
-
539
-    /**
540
-     * Does the traditional work of setting up the plugin's database and adding default data.
541
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
542
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
543
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
544
-     * so that it will be done when migrations are finished
545
-     *
546
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
547
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
548
-     *                                       This is a resource-intensive job
549
-     *                                       so we prefer to only do it when necessary
550
-     * @return void
551
-     * @throws EE_Error
552
-     */
553
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
554
-    {
555
-        $request_type = $this->detect_req_type();
556
-        // only initialize system if we're not in maintenance mode.
557
-        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
558
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
559
-            $rewrite_rules = $this->loader->getShared(
560
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
561
-            );
562
-            $rewrite_rules->flush();
563
-            if ($verify_schema) {
564
-                EEH_Activation::initialize_db_and_folders();
565
-            }
566
-            EEH_Activation::initialize_db_content();
567
-            EEH_Activation::system_initialization();
568
-            if ($initialize_addons_too) {
569
-                $this->initialize_addons();
570
-            }
571
-        } else {
572
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
573
-        }
574
-        if (
575
-            $request_type === EE_System::req_type_new_activation
576
-            || $request_type === EE_System::req_type_reactivation
577
-            || (
578
-                $request_type === EE_System::req_type_upgrade
579
-                && $this->is_major_version_change()
580
-            )
581
-        ) {
582
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
583
-        }
584
-    }
585
-
586
-
587
-    /**
588
-     * Initializes the db for all registered addons
589
-     *
590
-     * @throws EE_Error
591
-     */
592
-    public function initialize_addons()
593
-    {
594
-        // foreach registered addon, make sure its db is up-to-date too
595
-        foreach ($this->registry->addons as $addon) {
596
-            if ($addon instanceof EE_Addon) {
597
-                $addon->initialize_db_if_no_migrations_required();
598
-            }
599
-        }
600
-    }
601
-
602
-
603
-    /**
604
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
605
-     *
606
-     * @param    array  $version_history
607
-     * @param    string $current_version_to_add version to be added to the version history
608
-     * @return    boolean success as to whether or not this option was changed
609
-     */
610
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
611
-    {
612
-        if (! $version_history) {
613
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
614
-        }
615
-        if ($current_version_to_add === null) {
616
-            $current_version_to_add = espresso_version();
617
-        }
618
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
619
-        // re-save
620
-        return update_option('espresso_db_update', $version_history);
621
-    }
622
-
623
-
624
-    /**
625
-     * Detects if the current version indicated in the has existed in the list of
626
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
627
-     *
628
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
629
-     *                                  If not supplied, fetches it from the options table.
630
-     *                                  Also, caches its result so later parts of the code can also know whether
631
-     *                                  there's been an update or not. This way we can add the current version to
632
-     *                                  espresso_db_update, but still know if this is a new install or not
633
-     * @return int one of the constants on EE_System::req_type_
634
-     */
635
-    public function detect_req_type($espresso_db_update = null)
636
-    {
637
-        if ($this->_req_type === null) {
638
-            $espresso_db_update = ! empty($espresso_db_update)
639
-                ? $espresso_db_update
640
-                : $this->fix_espresso_db_upgrade_option();
641
-            $this->_req_type = EE_System::detect_req_type_given_activation_history(
642
-                $espresso_db_update,
643
-                'ee_espresso_activation',
644
-                espresso_version()
645
-            );
646
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
647
-            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
648
-        }
649
-        return $this->_req_type;
650
-    }
651
-
652
-
653
-    /**
654
-     * Returns whether or not there was a non-micro version change (ie, change in either
655
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
656
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
657
-     *
658
-     * @param $activation_history
659
-     * @return bool
660
-     */
661
-    private function _detect_major_version_change($activation_history)
662
-    {
663
-        $previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
664
-        $previous_version_parts = explode('.', $previous_version);
665
-        $current_version_parts = explode('.', espresso_version());
666
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
667
-               && ($previous_version_parts[0] !== $current_version_parts[0]
668
-                   || $previous_version_parts[1] !== $current_version_parts[1]
669
-               );
670
-    }
671
-
672
-
673
-    /**
674
-     * Returns true if either the major or minor version of EE changed during this request.
675
-     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
676
-     *
677
-     * @return bool
678
-     */
679
-    public function is_major_version_change()
680
-    {
681
-        return $this->_major_version_change;
682
-    }
683
-
684
-
685
-    /**
686
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
687
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
688
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
689
-     * just activated to (for core that will always be espresso_version())
690
-     *
691
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
692
-     *                                                 ee plugin. for core that's 'espresso_db_update'
693
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
694
-     *                                                 indicate that this plugin was just activated
695
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
696
-     *                                                 espresso_version())
697
-     * @return int one of the constants on EE_System::req_type_*
698
-     */
699
-    public static function detect_req_type_given_activation_history(
700
-        $activation_history_for_addon,
701
-        $activation_indicator_option_name,
702
-        $version_to_upgrade_to
703
-    ) {
704
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
705
-        if ($activation_history_for_addon) {
706
-            // it exists, so this isn't a completely new install
707
-            // check if this version already in that list of previously installed versions
708
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
709
-                // it a version we haven't seen before
710
-                if ($version_is_higher === 1) {
711
-                    $req_type = EE_System::req_type_upgrade;
712
-                } else {
713
-                    $req_type = EE_System::req_type_downgrade;
714
-                }
715
-                delete_option($activation_indicator_option_name);
716
-            } else {
717
-                // its not an update. maybe a reactivation?
718
-                if (get_option($activation_indicator_option_name, false)) {
719
-                    if ($version_is_higher === -1) {
720
-                        $req_type = EE_System::req_type_downgrade;
721
-                    } elseif ($version_is_higher === 0) {
722
-                        // we've seen this version before, but it's an activation. must be a reactivation
723
-                        $req_type = EE_System::req_type_reactivation;
724
-                    } else {// $version_is_higher === 1
725
-                        $req_type = EE_System::req_type_upgrade;
726
-                    }
727
-                    delete_option($activation_indicator_option_name);
728
-                } else {
729
-                    // we've seen this version before and the activation indicate doesn't show it was just activated
730
-                    if ($version_is_higher === -1) {
731
-                        $req_type = EE_System::req_type_downgrade;
732
-                    } elseif ($version_is_higher === 0) {
733
-                        // we've seen this version before and it's not an activation. its normal request
734
-                        $req_type = EE_System::req_type_normal;
735
-                    } else {// $version_is_higher === 1
736
-                        $req_type = EE_System::req_type_upgrade;
737
-                    }
738
-                }
739
-            }
740
-        } else {
741
-            // brand new install
742
-            $req_type = EE_System::req_type_new_activation;
743
-            delete_option($activation_indicator_option_name);
744
-        }
745
-        return $req_type;
746
-    }
747
-
748
-
749
-    /**
750
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
751
-     * the $activation_history_for_addon
752
-     *
753
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
754
-     *                                             sometimes containing 'unknown-date'
755
-     * @param string $version_to_upgrade_to        (current version)
756
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
757
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
758
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
759
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
760
-     */
761
-    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
762
-    {
763
-        // find the most recently-activated version
764
-        $most_recently_active_version =
765
-            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
766
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
767
-    }
768
-
769
-
770
-    /**
771
-     * Gets the most recently active version listed in the activation history,
772
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
773
-     *
774
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
775
-     *                                   sometimes containing 'unknown-date'
776
-     * @return string
777
-     */
778
-    private static function _get_most_recently_active_version_from_activation_history($activation_history)
779
-    {
780
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
781
-        $most_recently_active_version = '0.0.0.dev.000';
782
-        if (is_array($activation_history)) {
783
-            foreach ($activation_history as $version => $times_activated) {
784
-                // check there is a record of when this version was activated. Otherwise,
785
-                // mark it as unknown
786
-                if (! $times_activated) {
787
-                    $times_activated = array('unknown-date');
788
-                }
789
-                if (is_string($times_activated)) {
790
-                    $times_activated = array($times_activated);
791
-                }
792
-                foreach ($times_activated as $an_activation) {
793
-                    if (
794
-                        $an_activation !== 'unknown-date'
795
-                        && $an_activation
796
-                           > $most_recently_active_version_activation
797
-                    ) {
798
-                        $most_recently_active_version = $version;
799
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
800
-                            ? '1970-01-01 00:00:00'
801
-                            : $an_activation;
802
-                    }
803
-                }
804
-            }
805
-        }
806
-        return $most_recently_active_version;
807
-    }
808
-
809
-
810
-    /**
811
-     * This redirects to the about EE page after activation
812
-     *
813
-     * @return void
814
-     */
815
-    public function redirect_to_about_ee()
816
-    {
817
-        $notices = EE_Error::get_notices(false);
818
-        // if current user is an admin and it's not an ajax or rest request
819
-        if (
820
-            ! isset($notices['errors'])
821
-            && $this->request->isAdmin()
822
-            && apply_filters(
823
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
824
-                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
825
-            )
826
-        ) {
827
-            $query_params = array('page' => 'espresso_about');
828
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
829
-                $query_params['new_activation'] = true;
830
-            }
831
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
832
-                $query_params['reactivation'] = true;
833
-            }
834
-            $url = add_query_arg($query_params, admin_url('admin.php'));
835
-            wp_safe_redirect($url);
836
-            exit();
837
-        }
838
-    }
839
-
840
-
841
-    /**
842
-     * load_core_configuration
843
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
844
-     * which runs during the WP 'plugins_loaded' action at priority 5
845
-     *
846
-     * @return void
847
-     * @throws ReflectionException
848
-     * @throws Exception
849
-     */
850
-    public function load_core_configuration()
851
-    {
852
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
853
-        $this->loader->getShared('EE_Load_Textdomain');
854
-        // load textdomain
855
-        EE_Load_Textdomain::load_textdomain();
856
-        // load caf stuff a chance to play during the activation process too.
857
-        $this->_maybe_brew_regular();
858
-        // load and setup EE_Config and EE_Network_Config
859
-        $config = $this->loader->getShared('EE_Config');
860
-        $this->loader->getShared('EE_Network_Config');
861
-        // setup autoloaders
862
-        // enable logging?
863
-        if ($config->admin->use_remote_logging) {
864
-            $this->loader->getShared('EE_Log');
865
-        }
866
-        // check for activation errors
867
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
868
-        if ($activation_errors) {
869
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
870
-            update_option('ee_plugin_activation_errors', false);
871
-        }
872
-        // get model names
873
-        $this->_parse_model_names();
874
-        // configure custom post type definitions
875
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
876
-        $this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
877
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
878
-    }
879
-
880
-
881
-    /**
882
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
883
-     *
884
-     * @return void
885
-     * @throws ReflectionException
886
-     */
887
-    private function _parse_model_names()
888
-    {
889
-        // get all the files in the EE_MODELS folder that end in .model.php
890
-        $models = glob(EE_MODELS . '*.model.php');
891
-        $model_names = array();
892
-        $non_abstract_db_models = array();
893
-        foreach ($models as $model) {
894
-            // get model classname
895
-            $classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
896
-            $short_name = str_replace('EEM_', '', $classname);
897
-            $reflectionClass = new ReflectionClass($classname);
898
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
899
-                $non_abstract_db_models[ $short_name ] = $classname;
900
-            }
901
-            $model_names[ $short_name ] = $classname;
902
-        }
903
-        $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
904
-        $this->registry->non_abstract_db_models = apply_filters(
905
-            'FHEE__EE_System__parse_implemented_model_names',
906
-            $non_abstract_db_models
907
-        );
908
-    }
909
-
910
-
911
-    /**
912
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
913
-     * that need to be setup before our EE_System launches.
914
-     *
915
-     * @return void
916
-     * @throws DomainException
917
-     * @throws InvalidArgumentException
918
-     * @throws InvalidDataTypeException
919
-     * @throws InvalidInterfaceException
920
-     * @throws InvalidClassException
921
-     * @throws InvalidFilePathException
922
-     */
923
-    private function _maybe_brew_regular()
924
-    {
925
-        /** @var Domain $domain */
926
-        $domain = DomainFactory::getShared(
927
-            new FullyQualifiedName(
928
-                'EventEspresso\core\domain\Domain'
929
-            ),
930
-            array(
931
-                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
932
-                Version::fromString(espresso_version()),
933
-            )
934
-        );
935
-        if ($domain->isCaffeinated()) {
936
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
937
-        }
938
-    }
939
-
940
-
941
-    /**
942
-     * @since 4.9.71.p
943
-     * @throws Exception
944
-     */
945
-    public function loadRouteMatchSpecifications()
946
-    {
947
-        try {
948
-            $this->loader->getShared(
949
-                'EventEspresso\core\services\route_match\RouteMatchSpecificationManager'
950
-            );
951
-        } catch (Exception $exception) {
952
-            new ExceptionStackTraceDisplay($exception);
953
-        }
954
-        do_action('AHEE__EE_System__loadRouteMatchSpecifications');
955
-    }
956
-
957
-
958
-    /**
959
-     * register_shortcodes_modules_and_widgets
960
-     * generate lists of shortcodes and modules, then verify paths and classes
961
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
962
-     * which runs during the WP 'plugins_loaded' action at priority 7
963
-     *
964
-     * @access public
965
-     * @return void
966
-     * @throws Exception
967
-     */
968
-    public function register_shortcodes_modules_and_widgets()
969
-    {
970
-        if ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isAjax()) {
971
-            // load, register, and add shortcodes the new way
972
-            $this->loader->getShared('EventEspresso\core\services\shortcodes\ShortcodesManager');
973
-        }
974
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
975
-        // check for addons using old hook point
976
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
977
-            $this->_incompatible_addon_error();
978
-        }
979
-    }
980
-
981
-
982
-    /**
983
-     * _incompatible_addon_error
984
-     *
985
-     * @access public
986
-     * @return void
987
-     */
988
-    private function _incompatible_addon_error()
989
-    {
990
-        // get array of classes hooking into here
991
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
992
-            'AHEE__EE_System__register_shortcodes_modules_and_addons'
993
-        );
994
-        if (! empty($class_names)) {
995
-            $msg = esc_html__(
996
-                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
997
-                'event_espresso'
998
-            );
999
-            $msg .= '<ul>';
1000
-            foreach ($class_names as $class_name) {
1001
-                $msg .= '<li><b>Event Espresso - '
1002
-                        . str_replace(
1003
-                            array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
1004
-                            '',
1005
-                            $class_name
1006
-                        ) . '</b></li>';
1007
-            }
1008
-            $msg .= '</ul>';
1009
-            $msg .= esc_html__(
1010
-                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1011
-                'event_espresso'
1012
-            );
1013
-            // save list of incompatible addons to wp-options for later use
1014
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
1015
-            if (is_admin()) {
1016
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1017
-            }
1018
-        }
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * brew_espresso
1024
-     * begins the process of setting hooks for initializing EE in the correct order
1025
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1026
-     * which runs during the WP 'plugins_loaded' action at priority 9
1027
-     *
1028
-     * @return void
1029
-     */
1030
-    public function brew_espresso()
1031
-    {
1032
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1033
-        // load some final core systems
1034
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
1035
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1036
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1037
-        add_action('init', array($this, 'load_controllers'), 7);
1038
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1039
-        add_action('init', array($this, 'initialize'), 10);
1040
-        add_action('init', array($this, 'initialize_last'), 100);
1041
-        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1042
-            // pew pew pew
1043
-            $this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1044
-            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1045
-        }
1046
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1047
-    }
1048
-
1049
-
1050
-    /**
1051
-     *    set_hooks_for_core
1052
-     *
1053
-     * @access public
1054
-     * @return    void
1055
-     * @throws EE_Error
1056
-     */
1057
-    public function set_hooks_for_core()
1058
-    {
1059
-        $this->_deactivate_incompatible_addons();
1060
-        do_action('AHEE__EE_System__set_hooks_for_core');
1061
-        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1062
-        // caps need to be initialized on every request so that capability maps are set.
1063
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1064
-        $this->registry->CAP->init_caps();
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * Using the information gathered in EE_System::_incompatible_addon_error,
1070
-     * deactivates any addons considered incompatible with the current version of EE
1071
-     */
1072
-    private function _deactivate_incompatible_addons()
1073
-    {
1074
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
1075
-        if (! empty($incompatible_addons)) {
1076
-            $active_plugins = get_option('active_plugins', array());
1077
-            foreach ($active_plugins as $active_plugin) {
1078
-                foreach ($incompatible_addons as $incompatible_addon) {
1079
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1080
-                        $this->request->unSetRequestParams(['activate'], true);
1081
-                        espresso_deactivate_plugin($active_plugin);
1082
-                    }
1083
-                }
1084
-            }
1085
-        }
1086
-    }
1087
-
1088
-
1089
-    /**
1090
-     *    perform_activations_upgrades_and_migrations
1091
-     *
1092
-     * @access public
1093
-     * @return    void
1094
-     */
1095
-    public function perform_activations_upgrades_and_migrations()
1096
-    {
1097
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * @return void
1103
-     * @throws DomainException
1104
-     */
1105
-    public function load_CPTs_and_session()
1106
-    {
1107
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1108
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1109
-        $register_custom_taxonomies = $this->loader->getShared(
1110
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1111
-        );
1112
-        $register_custom_taxonomies->registerCustomTaxonomies();
1113
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1114
-        $register_custom_post_types = $this->loader->getShared(
1115
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1116
-        );
1117
-        $register_custom_post_types->registerCustomPostTypes();
1118
-        /** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1119
-        $register_custom_taxonomy_terms = $this->loader->getShared(
1120
-            'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1121
-        );
1122
-        $register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1123
-        // load legacy Custom Post Types and Taxonomies
1124
-        $this->loader->getShared('EE_Register_CPTs');
1125
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * load_controllers
1131
-     * this is the best place to load any additional controllers that needs access to EE core.
1132
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1133
-     * time
1134
-     *
1135
-     * @access public
1136
-     * @return void
1137
-     */
1138
-    public function load_controllers()
1139
-    {
1140
-        do_action('AHEE__EE_System__load_controllers__start');
1141
-        // let's get it started
1142
-        if (
1143
-            ! $this->maintenance_mode->level()
1144
-            && ($this->request->isFrontend() || $this->request->isFrontAjax())
1145
-        ) {
1146
-            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1147
-            $this->loader->getShared('EE_Front_Controller');
1148
-        } elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1149
-            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1150
-            $this->loader->getShared('EE_Admin');
1151
-        } elseif ($this->request->isWordPressHeartbeat()) {
1152
-            $this->loader->getShared('EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat');
1153
-        }
1154
-        do_action('AHEE__EE_System__load_controllers__complete');
1155
-    }
1156
-
1157
-
1158
-    /**
1159
-     * core_loaded_and_ready
1160
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1161
-     *
1162
-     * @access public
1163
-     * @return void
1164
-     * @throws Exception
1165
-     */
1166
-    public function core_loaded_and_ready()
1167
-    {
1168
-        if (
1169
-            $this->request->isAdmin()
1170
-            || $this->request->isFrontend()
1171
-            || $this->request->isIframe()
1172
-            || $this->request->isWordPressApi()
1173
-        ) {
1174
-            try {
1175
-                $this->loader->getShared('EventEspresso\core\services\assets\Registry');
1176
-                $this->loader->getShared('EventEspresso\core\domain\services\assets\CoreAssetManager');
1177
-                if ($this->canLoadBlocks()) {
1178
-                    $this->loader->getShared(
1179
-                        'EventEspresso\core\services\editor\BlockRegistrationManager'
1180
-                    );
1181
-                }
1182
-            } catch (Exception $exception) {
1183
-                new ExceptionStackTraceDisplay($exception);
1184
-            }
1185
-        }
1186
-        if (
1187
-            $this->request->isAdmin()
1188
-            || $this->request->isEeAjax()
1189
-            || $this->request->isFrontend()
1190
-        ) {
1191
-            $this->loader->getShared('EE_Session');
1192
-        }
1193
-        // integrate WP_Query with the EE models
1194
-        $this->loader->getShared('EE_CPT_Strategy');
1195
-        // load legacy EE_Request_Handler in case add-ons still need it
1196
-        $this->loader->getShared('EE_Request_Handler');
1197
-        do_action('AHEE__EE_System__core_loaded_and_ready');
1198
-        // always load template tags, because it's faster than checking if it's a front-end request, and many page
1199
-        // builders require these even on the front-end
1200
-        require_once EE_PUBLIC . 'template_tags.php';
1201
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1202
-    }
1203
-
1204
-
1205
-    /**
1206
-     * initialize
1207
-     * this is the best place to begin initializing client code
1208
-     *
1209
-     * @access public
1210
-     * @return void
1211
-     */
1212
-    public function initialize()
1213
-    {
1214
-        do_action('AHEE__EE_System__initialize');
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     * initialize_last
1220
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1221
-     * initialize has done so
1222
-     *
1223
-     * @access public
1224
-     * @return void
1225
-     */
1226
-    public function initialize_last()
1227
-    {
1228
-        do_action('AHEE__EE_System__initialize_last');
1229
-        /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1230
-        $rewrite_rules = $this->loader->getShared(
1231
-            'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1232
-        );
1233
-        $rewrite_rules->flushRewriteRules();
1234
-        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1235
-        if (
1236
-            ($this->request->isAjax() || $this->request->isAdmin())
1237
-            && $this->maintenance_mode->models_can_query()
1238
-        ) {
1239
-            $this->loader->getShared('EventEspresso\core\services\privacy\export\PersonalDataExporterManager');
1240
-            $this->loader->getShared('EventEspresso\core\services\privacy\erasure\PersonalDataEraserManager');
1241
-        }
1242
-    }
1243
-
1244
-
1245
-    /**
1246
-     * @return void
1247
-     * @throws EE_Error
1248
-     */
1249
-    public function addEspressoToolbar()
1250
-    {
1251
-        $this->loader->getShared(
1252
-            'EventEspresso\core\domain\services\admin\AdminToolBar',
1253
-            array($this->registry->CAP)
1254
-        );
1255
-    }
1256
-
1257
-
1258
-    /**
1259
-     * do_not_cache
1260
-     * sets no cache headers and defines no cache constants for WP plugins
1261
-     *
1262
-     * @access public
1263
-     * @return void
1264
-     */
1265
-    public static function do_not_cache()
1266
-    {
1267
-        // set no cache constants
1268
-        if (! defined('DONOTCACHEPAGE')) {
1269
-            define('DONOTCACHEPAGE', true);
1270
-        }
1271
-        if (! defined('DONOTCACHCEOBJECT')) {
1272
-            define('DONOTCACHCEOBJECT', true);
1273
-        }
1274
-        if (! defined('DONOTCACHEDB')) {
1275
-            define('DONOTCACHEDB', true);
1276
-        }
1277
-        // add no cache headers
1278
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1279
-        // plus a little extra for nginx and Google Chrome
1280
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1281
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1282
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1283
-    }
1284
-
1285
-
1286
-    /**
1287
-     *    extra_nocache_headers
1288
-     *
1289
-     * @access    public
1290
-     * @param $headers
1291
-     * @return    array
1292
-     */
1293
-    public static function extra_nocache_headers($headers)
1294
-    {
1295
-        // for NGINX
1296
-        $headers['X-Accel-Expires'] = 0;
1297
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1298
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1299
-        return $headers;
1300
-    }
1301
-
1302
-
1303
-    /**
1304
-     *    nocache_headers
1305
-     *
1306
-     * @access    public
1307
-     * @return    void
1308
-     */
1309
-    public static function nocache_headers()
1310
-    {
1311
-        nocache_headers();
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1317
-     * never returned with the function.
1318
-     *
1319
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1320
-     * @return array
1321
-     */
1322
-    public function remove_pages_from_wp_list_pages($exclude_array)
1323
-    {
1324
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Return whether blocks can be registered/loaded or not.
1330
-     * @return bool
1331
-     */
1332
-    private function canLoadBlocks()
1333
-    {
1334
-        return apply_filters('FHEE__EE_System__canLoadBlocks', true)
1335
-               && function_exists('register_block_type')
1336
-               // don't load blocks if in the Divi page builder editor context
1337
-               // @see https://github.com/eventespresso/event-espresso-core/issues/814
1338
-               && ! $this->request->getRequestParam('et_fb', false);
1339
-    }
30
+	/**
31
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
32
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
33
+	 */
34
+	const req_type_normal = 0;
35
+
36
+	/**
37
+	 * Indicates this is a brand new installation of EE so we should install
38
+	 * tables and default data etc
39
+	 */
40
+	const req_type_new_activation = 1;
41
+
42
+	/**
43
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
44
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
45
+	 * and that default data is setup too
46
+	 */
47
+	const req_type_reactivation = 2;
48
+
49
+	/**
50
+	 * indicates that EE has been upgraded since its previous request.
51
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
52
+	 */
53
+	const req_type_upgrade = 3;
54
+
55
+	/**
56
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
57
+	 */
58
+	const req_type_downgrade = 4;
59
+
60
+	/**
61
+	 * @deprecated since version 4.6.0.dev.006
62
+	 * Now whenever a new_activation is detected the request type is still just
63
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
64
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
65
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
66
+	 * (Specifically, when the migration manager indicates migrations are finished
67
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
68
+	 */
69
+	const req_type_activation_but_not_installed = 5;
70
+
71
+	/**
72
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
73
+	 */
74
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
75
+
76
+	/**
77
+	 * @var EE_System $_instance
78
+	 */
79
+	private static $_instance;
80
+
81
+	/**
82
+	 * @var EE_Registry $registry
83
+	 */
84
+	private $registry;
85
+
86
+	/**
87
+	 * @var LoaderInterface $loader
88
+	 */
89
+	private $loader;
90
+
91
+	/**
92
+	 * @var EE_Capabilities $capabilities
93
+	 */
94
+	private $capabilities;
95
+
96
+	/**
97
+	 * @var RequestInterface $request
98
+	 */
99
+	private $request;
100
+
101
+	/**
102
+	 * @var EE_Maintenance_Mode $maintenance_mode
103
+	 */
104
+	private $maintenance_mode;
105
+
106
+	/**
107
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
108
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
109
+	 *
110
+	 * @var int $_req_type
111
+	 */
112
+	private $_req_type;
113
+
114
+	/**
115
+	 * Whether or not there was a non-micro version change in EE core version during this request
116
+	 *
117
+	 * @var boolean $_major_version_change
118
+	 */
119
+	private $_major_version_change = false;
120
+
121
+	/**
122
+	 * A Context DTO dedicated solely to identifying the current request type.
123
+	 *
124
+	 * @var RequestTypeContextCheckerInterface $request_type
125
+	 */
126
+	private $request_type;
127
+
128
+
129
+	/**
130
+	 * @singleton method used to instantiate class object
131
+	 * @param EE_Registry|null         $registry
132
+	 * @param LoaderInterface|null     $loader
133
+	 * @param RequestInterface|null    $request
134
+	 * @param EE_Maintenance_Mode|null $maintenance_mode
135
+	 * @return EE_System
136
+	 */
137
+	public static function instance(
138
+		EE_Registry $registry = null,
139
+		LoaderInterface $loader = null,
140
+		RequestInterface $request = null,
141
+		EE_Maintenance_Mode $maintenance_mode = null
142
+	) {
143
+		// check if class object is instantiated
144
+		if (! self::$_instance instanceof EE_System) {
145
+			self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
146
+		}
147
+		return self::$_instance;
148
+	}
149
+
150
+
151
+	/**
152
+	 * resets the instance and returns it
153
+	 *
154
+	 * @return EE_System
155
+	 */
156
+	public static function reset()
157
+	{
158
+		self::$_instance->_req_type = null;
159
+		// make sure none of the old hooks are left hanging around
160
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
161
+		// we need to reset the migration manager in order for it to detect DMSs properly
162
+		EE_Data_Migration_Manager::reset();
163
+		self::instance()->detect_activations_or_upgrades();
164
+		self::instance()->perform_activations_upgrades_and_migrations();
165
+		return self::instance();
166
+	}
167
+
168
+
169
+	/**
170
+	 * sets hooks for running rest of system
171
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
172
+	 * starting EE Addons from any other point may lead to problems
173
+	 *
174
+	 * @param EE_Registry         $registry
175
+	 * @param LoaderInterface     $loader
176
+	 * @param RequestInterface    $request
177
+	 * @param EE_Maintenance_Mode $maintenance_mode
178
+	 */
179
+	private function __construct(
180
+		EE_Registry $registry,
181
+		LoaderInterface $loader,
182
+		RequestInterface $request,
183
+		EE_Maintenance_Mode $maintenance_mode
184
+	) {
185
+		$this->registry = $registry;
186
+		$this->loader = $loader;
187
+		$this->request = $request;
188
+		$this->maintenance_mode = $maintenance_mode;
189
+		do_action('AHEE__EE_System__construct__begin', $this);
190
+		add_action(
191
+			'AHEE__EE_Bootstrap__load_espresso_addons',
192
+			array($this, 'loadCapabilities'),
193
+			5
194
+		);
195
+		add_action(
196
+			'AHEE__EE_Bootstrap__load_espresso_addons',
197
+			array($this, 'loadCommandBus'),
198
+			7
199
+		);
200
+		add_action(
201
+			'AHEE__EE_Bootstrap__load_espresso_addons',
202
+			array($this, 'loadPluginApi'),
203
+			9
204
+		);
205
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
206
+		add_action(
207
+			'AHEE__EE_Bootstrap__load_espresso_addons',
208
+			array($this, 'load_espresso_addons')
209
+		);
210
+		// when an ee addon is activated, we want to call the core hook(s) again
211
+		// because the newly-activated addon didn't get a chance to run at all
212
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
213
+		// detect whether install or upgrade
214
+		add_action(
215
+			'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
216
+			array($this, 'detect_activations_or_upgrades'),
217
+			3
218
+		);
219
+		// load EE_Config, EE_Textdomain, etc
220
+		add_action(
221
+			'AHEE__EE_Bootstrap__load_core_configuration',
222
+			array($this, 'load_core_configuration'),
223
+			5
224
+		);
225
+		// load specifications for matching routes to current request
226
+		add_action(
227
+			'AHEE__EE_Bootstrap__load_core_configuration',
228
+			array($this, 'loadRouteMatchSpecifications')
229
+		);
230
+		// load EE_Config, EE_Textdomain, etc
231
+		add_action(
232
+			'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
233
+			array($this, 'register_shortcodes_modules_and_widgets'),
234
+			7
235
+		);
236
+		// you wanna get going? I wanna get going... let's get going!
237
+		add_action(
238
+			'AHEE__EE_Bootstrap__brew_espresso',
239
+			array($this, 'brew_espresso'),
240
+			9
241
+		);
242
+		// other housekeeping
243
+		// exclude EE critical pages from wp_list_pages
244
+		add_filter(
245
+			'wp_list_pages_excludes',
246
+			array($this, 'remove_pages_from_wp_list_pages'),
247
+			10
248
+		);
249
+		// ALL EE Addons should use the following hook point to attach their initial setup too
250
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
251
+		do_action('AHEE__EE_System__construct__complete', $this);
252
+	}
253
+
254
+
255
+	/**
256
+	 * load and setup EE_Capabilities
257
+	 *
258
+	 * @return void
259
+	 * @throws EE_Error
260
+	 */
261
+	public function loadCapabilities()
262
+	{
263
+		$this->capabilities = $this->loader->getShared('EE_Capabilities');
264
+		add_action(
265
+			'AHEE__EE_Capabilities__init_caps__before_initialization',
266
+			function () {
267
+				LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
268
+			}
269
+		);
270
+	}
271
+
272
+
273
+	/**
274
+	 * create and cache the CommandBus, and also add middleware
275
+	 * The CapChecker middleware requires the use of EE_Capabilities
276
+	 * which is why we need to load the CommandBus after Caps are set up
277
+	 *
278
+	 * @return void
279
+	 * @throws EE_Error
280
+	 */
281
+	public function loadCommandBus()
282
+	{
283
+		$this->loader->getShared(
284
+			'CommandBusInterface',
285
+			array(
286
+				null,
287
+				apply_filters(
288
+					'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
289
+					array(
290
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
291
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
292
+					)
293
+				),
294
+			)
295
+		);
296
+	}
297
+
298
+
299
+	/**
300
+	 * @return void
301
+	 * @throws EE_Error
302
+	 */
303
+	public function loadPluginApi()
304
+	{
305
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
306
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
307
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
308
+	}
309
+
310
+
311
+	/**
312
+	 * @param string $addon_name
313
+	 * @param string $version_constant
314
+	 * @param string $min_version_required
315
+	 * @param string $load_callback
316
+	 * @param string $plugin_file_constant
317
+	 * @return void
318
+	 */
319
+	private function deactivateIncompatibleAddon(
320
+		$addon_name,
321
+		$version_constant,
322
+		$min_version_required,
323
+		$load_callback,
324
+		$plugin_file_constant
325
+	) {
326
+		if (! defined($version_constant)) {
327
+			return;
328
+		}
329
+		$addon_version = constant($version_constant);
330
+		if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
331
+			remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
332
+			if (! function_exists('deactivate_plugins')) {
333
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
334
+			}
335
+			deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
336
+			$this->request->unSetRequestParams(['activate', 'activate-multi'], true);
337
+			EE_Error::add_error(
338
+				sprintf(
339
+					esc_html__(
340
+						'We\'re sorry, but the Event Espresso %1$s addon was deactivated because version %2$s or higher is required with this version of Event Espresso core.',
341
+						'event_espresso'
342
+					),
343
+					$addon_name,
344
+					$min_version_required
345
+				),
346
+				__FILE__,
347
+				__FUNCTION__ . "({$addon_name})",
348
+				__LINE__
349
+			);
350
+			EE_Error::get_notices(false, true);
351
+		}
352
+	}
353
+
354
+
355
+	/**
356
+	 * load_espresso_addons
357
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
358
+	 * this is hooked into both:
359
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
360
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
361
+	 *    and the WP 'activate_plugin' hook point
362
+	 *
363
+	 * @access public
364
+	 * @return void
365
+	 */
366
+	public function load_espresso_addons()
367
+	{
368
+		$this->deactivateIncompatibleAddon(
369
+			'Wait Lists',
370
+			'EE_WAIT_LISTS_VERSION',
371
+			'1.0.0.beta.074',
372
+			'load_espresso_wait_lists',
373
+			'EE_WAIT_LISTS_PLUGIN_FILE'
374
+		);
375
+		$this->deactivateIncompatibleAddon(
376
+			'Automated Upcoming Event Notifications',
377
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
378
+			'1.0.0.beta.091',
379
+			'load_espresso_automated_upcoming_event_notification',
380
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
381
+		);
382
+		do_action('AHEE__EE_System__load_espresso_addons');
383
+		// if the WP API basic auth plugin isn't already loaded, load it now.
384
+		// We want it for mobile apps. Just include the entire plugin
385
+		// also, don't load the basic auth when a plugin is getting activated, because
386
+		// it could be the basic auth plugin, and it doesn't check if its methods are already defined
387
+		// and causes a fatal error
388
+		if (
389
+			($this->request->isWordPressApi() || $this->request->isApi())
390
+			&& $this->request->getRequestParam('activate') !== 'true'
391
+			&& ! function_exists('json_basic_auth_handler')
392
+			&& ! function_exists('json_basic_auth_error')
393
+			&& ! in_array(
394
+				$this->request->getRequestParam('action'),
395
+				array('activate', 'activate-selected'),
396
+				true
397
+			)
398
+		) {
399
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth/basic-auth.php';
400
+		}
401
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
402
+	}
403
+
404
+
405
+	/**
406
+	 * detect_activations_or_upgrades
407
+	 * Checks for activation or upgrade of core first;
408
+	 * then also checks if any registered addons have been activated or upgraded
409
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
410
+	 * which runs during the WP 'plugins_loaded' action at priority 3
411
+	 *
412
+	 * @access public
413
+	 * @return void
414
+	 */
415
+	public function detect_activations_or_upgrades()
416
+	{
417
+		// first off: let's make sure to handle core
418
+		$this->detect_if_activation_or_upgrade();
419
+		foreach ($this->registry->addons as $addon) {
420
+			if ($addon instanceof EE_Addon) {
421
+				// detect teh request type for that addon
422
+				$addon->detect_req_type();
423
+			}
424
+		}
425
+	}
426
+
427
+
428
+	/**
429
+	 * detect_if_activation_or_upgrade
430
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
431
+	 * and either setting up the DB or setting up maintenance mode etc.
432
+	 *
433
+	 * @access public
434
+	 * @return void
435
+	 */
436
+	public function detect_if_activation_or_upgrade()
437
+	{
438
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
439
+		// check if db has been updated, or if its a brand-new installation
440
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
441
+		$request_type = $this->detect_req_type($espresso_db_update);
442
+		// EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
443
+		switch ($request_type) {
444
+			case EE_System::req_type_new_activation:
445
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
446
+				$this->_handle_core_version_change($espresso_db_update);
447
+				break;
448
+			case EE_System::req_type_reactivation:
449
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
450
+				$this->_handle_core_version_change($espresso_db_update);
451
+				break;
452
+			case EE_System::req_type_upgrade:
453
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
454
+				// migrations may be required now that we've upgraded
455
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
456
+				$this->_handle_core_version_change($espresso_db_update);
457
+				break;
458
+			case EE_System::req_type_downgrade:
459
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
460
+				// its possible migrations are no longer required
461
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
462
+				$this->_handle_core_version_change($espresso_db_update);
463
+				break;
464
+			case EE_System::req_type_normal:
465
+			default:
466
+				break;
467
+		}
468
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
469
+	}
470
+
471
+
472
+	/**
473
+	 * Updates the list of installed versions and sets hooks for
474
+	 * initializing the database later during the request
475
+	 *
476
+	 * @param array $espresso_db_update
477
+	 */
478
+	private function _handle_core_version_change($espresso_db_update)
479
+	{
480
+		$this->update_list_of_installed_versions($espresso_db_update);
481
+		// get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
482
+		add_action(
483
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
484
+			array($this, 'initialize_db_if_no_migrations_required')
485
+		);
486
+	}
487
+
488
+
489
+	/**
490
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
491
+	 * information about what versions of EE have been installed and activated,
492
+	 * NOT necessarily the state of the database
493
+	 *
494
+	 * @param mixed $espresso_db_update           the value of the WordPress option.
495
+	 *                                            If not supplied, fetches it from the options table
496
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
497
+	 */
498
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
499
+	{
500
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
501
+		if (! $espresso_db_update) {
502
+			$espresso_db_update = get_option('espresso_db_update');
503
+		}
504
+		// check that option is an array
505
+		if (! is_array($espresso_db_update)) {
506
+			// if option is FALSE, then it never existed
507
+			if ($espresso_db_update === false) {
508
+				// make $espresso_db_update an array and save option with autoload OFF
509
+				$espresso_db_update = array();
510
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
511
+			} else {
512
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
513
+				$espresso_db_update = array($espresso_db_update => array());
514
+				update_option('espresso_db_update', $espresso_db_update);
515
+			}
516
+		} else {
517
+			$corrected_db_update = array();
518
+			// if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
519
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
520
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
521
+					// the key is an int, and the value IS NOT an array
522
+					// so it must be numerically-indexed, where values are versions installed...
523
+					// fix it!
524
+					$version_string = $should_be_array;
525
+					$corrected_db_update[ $version_string ] = array('unknown-date');
526
+				} else {
527
+					// ok it checks out
528
+					$corrected_db_update[ $should_be_version_string ] = $should_be_array;
529
+				}
530
+			}
531
+			$espresso_db_update = $corrected_db_update;
532
+			update_option('espresso_db_update', $espresso_db_update);
533
+		}
534
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
535
+		return $espresso_db_update;
536
+	}
537
+
538
+
539
+	/**
540
+	 * Does the traditional work of setting up the plugin's database and adding default data.
541
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
542
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
543
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
544
+	 * so that it will be done when migrations are finished
545
+	 *
546
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
547
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
548
+	 *                                       This is a resource-intensive job
549
+	 *                                       so we prefer to only do it when necessary
550
+	 * @return void
551
+	 * @throws EE_Error
552
+	 */
553
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
554
+	{
555
+		$request_type = $this->detect_req_type();
556
+		// only initialize system if we're not in maintenance mode.
557
+		if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
558
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
559
+			$rewrite_rules = $this->loader->getShared(
560
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
561
+			);
562
+			$rewrite_rules->flush();
563
+			if ($verify_schema) {
564
+				EEH_Activation::initialize_db_and_folders();
565
+			}
566
+			EEH_Activation::initialize_db_content();
567
+			EEH_Activation::system_initialization();
568
+			if ($initialize_addons_too) {
569
+				$this->initialize_addons();
570
+			}
571
+		} else {
572
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
573
+		}
574
+		if (
575
+			$request_type === EE_System::req_type_new_activation
576
+			|| $request_type === EE_System::req_type_reactivation
577
+			|| (
578
+				$request_type === EE_System::req_type_upgrade
579
+				&& $this->is_major_version_change()
580
+			)
581
+		) {
582
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
583
+		}
584
+	}
585
+
586
+
587
+	/**
588
+	 * Initializes the db for all registered addons
589
+	 *
590
+	 * @throws EE_Error
591
+	 */
592
+	public function initialize_addons()
593
+	{
594
+		// foreach registered addon, make sure its db is up-to-date too
595
+		foreach ($this->registry->addons as $addon) {
596
+			if ($addon instanceof EE_Addon) {
597
+				$addon->initialize_db_if_no_migrations_required();
598
+			}
599
+		}
600
+	}
601
+
602
+
603
+	/**
604
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
605
+	 *
606
+	 * @param    array  $version_history
607
+	 * @param    string $current_version_to_add version to be added to the version history
608
+	 * @return    boolean success as to whether or not this option was changed
609
+	 */
610
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
611
+	{
612
+		if (! $version_history) {
613
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
614
+		}
615
+		if ($current_version_to_add === null) {
616
+			$current_version_to_add = espresso_version();
617
+		}
618
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
619
+		// re-save
620
+		return update_option('espresso_db_update', $version_history);
621
+	}
622
+
623
+
624
+	/**
625
+	 * Detects if the current version indicated in the has existed in the list of
626
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
627
+	 *
628
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
629
+	 *                                  If not supplied, fetches it from the options table.
630
+	 *                                  Also, caches its result so later parts of the code can also know whether
631
+	 *                                  there's been an update or not. This way we can add the current version to
632
+	 *                                  espresso_db_update, but still know if this is a new install or not
633
+	 * @return int one of the constants on EE_System::req_type_
634
+	 */
635
+	public function detect_req_type($espresso_db_update = null)
636
+	{
637
+		if ($this->_req_type === null) {
638
+			$espresso_db_update = ! empty($espresso_db_update)
639
+				? $espresso_db_update
640
+				: $this->fix_espresso_db_upgrade_option();
641
+			$this->_req_type = EE_System::detect_req_type_given_activation_history(
642
+				$espresso_db_update,
643
+				'ee_espresso_activation',
644
+				espresso_version()
645
+			);
646
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
647
+			$this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
648
+		}
649
+		return $this->_req_type;
650
+	}
651
+
652
+
653
+	/**
654
+	 * Returns whether or not there was a non-micro version change (ie, change in either
655
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
656
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
657
+	 *
658
+	 * @param $activation_history
659
+	 * @return bool
660
+	 */
661
+	private function _detect_major_version_change($activation_history)
662
+	{
663
+		$previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
664
+		$previous_version_parts = explode('.', $previous_version);
665
+		$current_version_parts = explode('.', espresso_version());
666
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
667
+			   && ($previous_version_parts[0] !== $current_version_parts[0]
668
+				   || $previous_version_parts[1] !== $current_version_parts[1]
669
+			   );
670
+	}
671
+
672
+
673
+	/**
674
+	 * Returns true if either the major or minor version of EE changed during this request.
675
+	 * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
676
+	 *
677
+	 * @return bool
678
+	 */
679
+	public function is_major_version_change()
680
+	{
681
+		return $this->_major_version_change;
682
+	}
683
+
684
+
685
+	/**
686
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
687
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
688
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
689
+	 * just activated to (for core that will always be espresso_version())
690
+	 *
691
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
692
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
693
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
694
+	 *                                                 indicate that this plugin was just activated
695
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
696
+	 *                                                 espresso_version())
697
+	 * @return int one of the constants on EE_System::req_type_*
698
+	 */
699
+	public static function detect_req_type_given_activation_history(
700
+		$activation_history_for_addon,
701
+		$activation_indicator_option_name,
702
+		$version_to_upgrade_to
703
+	) {
704
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
705
+		if ($activation_history_for_addon) {
706
+			// it exists, so this isn't a completely new install
707
+			// check if this version already in that list of previously installed versions
708
+			if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
709
+				// it a version we haven't seen before
710
+				if ($version_is_higher === 1) {
711
+					$req_type = EE_System::req_type_upgrade;
712
+				} else {
713
+					$req_type = EE_System::req_type_downgrade;
714
+				}
715
+				delete_option($activation_indicator_option_name);
716
+			} else {
717
+				// its not an update. maybe a reactivation?
718
+				if (get_option($activation_indicator_option_name, false)) {
719
+					if ($version_is_higher === -1) {
720
+						$req_type = EE_System::req_type_downgrade;
721
+					} elseif ($version_is_higher === 0) {
722
+						// we've seen this version before, but it's an activation. must be a reactivation
723
+						$req_type = EE_System::req_type_reactivation;
724
+					} else {// $version_is_higher === 1
725
+						$req_type = EE_System::req_type_upgrade;
726
+					}
727
+					delete_option($activation_indicator_option_name);
728
+				} else {
729
+					// we've seen this version before and the activation indicate doesn't show it was just activated
730
+					if ($version_is_higher === -1) {
731
+						$req_type = EE_System::req_type_downgrade;
732
+					} elseif ($version_is_higher === 0) {
733
+						// we've seen this version before and it's not an activation. its normal request
734
+						$req_type = EE_System::req_type_normal;
735
+					} else {// $version_is_higher === 1
736
+						$req_type = EE_System::req_type_upgrade;
737
+					}
738
+				}
739
+			}
740
+		} else {
741
+			// brand new install
742
+			$req_type = EE_System::req_type_new_activation;
743
+			delete_option($activation_indicator_option_name);
744
+		}
745
+		return $req_type;
746
+	}
747
+
748
+
749
+	/**
750
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
751
+	 * the $activation_history_for_addon
752
+	 *
753
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
754
+	 *                                             sometimes containing 'unknown-date'
755
+	 * @param string $version_to_upgrade_to        (current version)
756
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
757
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
758
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
759
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
760
+	 */
761
+	private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
762
+	{
763
+		// find the most recently-activated version
764
+		$most_recently_active_version =
765
+			EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
766
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
767
+	}
768
+
769
+
770
+	/**
771
+	 * Gets the most recently active version listed in the activation history,
772
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
773
+	 *
774
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
775
+	 *                                   sometimes containing 'unknown-date'
776
+	 * @return string
777
+	 */
778
+	private static function _get_most_recently_active_version_from_activation_history($activation_history)
779
+	{
780
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
781
+		$most_recently_active_version = '0.0.0.dev.000';
782
+		if (is_array($activation_history)) {
783
+			foreach ($activation_history as $version => $times_activated) {
784
+				// check there is a record of when this version was activated. Otherwise,
785
+				// mark it as unknown
786
+				if (! $times_activated) {
787
+					$times_activated = array('unknown-date');
788
+				}
789
+				if (is_string($times_activated)) {
790
+					$times_activated = array($times_activated);
791
+				}
792
+				foreach ($times_activated as $an_activation) {
793
+					if (
794
+						$an_activation !== 'unknown-date'
795
+						&& $an_activation
796
+						   > $most_recently_active_version_activation
797
+					) {
798
+						$most_recently_active_version = $version;
799
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
800
+							? '1970-01-01 00:00:00'
801
+							: $an_activation;
802
+					}
803
+				}
804
+			}
805
+		}
806
+		return $most_recently_active_version;
807
+	}
808
+
809
+
810
+	/**
811
+	 * This redirects to the about EE page after activation
812
+	 *
813
+	 * @return void
814
+	 */
815
+	public function redirect_to_about_ee()
816
+	{
817
+		$notices = EE_Error::get_notices(false);
818
+		// if current user is an admin and it's not an ajax or rest request
819
+		if (
820
+			! isset($notices['errors'])
821
+			&& $this->request->isAdmin()
822
+			&& apply_filters(
823
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
824
+				$this->capabilities->current_user_can('manage_options', 'espresso_about_default')
825
+			)
826
+		) {
827
+			$query_params = array('page' => 'espresso_about');
828
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
829
+				$query_params['new_activation'] = true;
830
+			}
831
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
832
+				$query_params['reactivation'] = true;
833
+			}
834
+			$url = add_query_arg($query_params, admin_url('admin.php'));
835
+			wp_safe_redirect($url);
836
+			exit();
837
+		}
838
+	}
839
+
840
+
841
+	/**
842
+	 * load_core_configuration
843
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
844
+	 * which runs during the WP 'plugins_loaded' action at priority 5
845
+	 *
846
+	 * @return void
847
+	 * @throws ReflectionException
848
+	 * @throws Exception
849
+	 */
850
+	public function load_core_configuration()
851
+	{
852
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
853
+		$this->loader->getShared('EE_Load_Textdomain');
854
+		// load textdomain
855
+		EE_Load_Textdomain::load_textdomain();
856
+		// load caf stuff a chance to play during the activation process too.
857
+		$this->_maybe_brew_regular();
858
+		// load and setup EE_Config and EE_Network_Config
859
+		$config = $this->loader->getShared('EE_Config');
860
+		$this->loader->getShared('EE_Network_Config');
861
+		// setup autoloaders
862
+		// enable logging?
863
+		if ($config->admin->use_remote_logging) {
864
+			$this->loader->getShared('EE_Log');
865
+		}
866
+		// check for activation errors
867
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
868
+		if ($activation_errors) {
869
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
870
+			update_option('ee_plugin_activation_errors', false);
871
+		}
872
+		// get model names
873
+		$this->_parse_model_names();
874
+		// configure custom post type definitions
875
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions');
876
+		$this->loader->getShared('EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions');
877
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
878
+	}
879
+
880
+
881
+	/**
882
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
883
+	 *
884
+	 * @return void
885
+	 * @throws ReflectionException
886
+	 */
887
+	private function _parse_model_names()
888
+	{
889
+		// get all the files in the EE_MODELS folder that end in .model.php
890
+		$models = glob(EE_MODELS . '*.model.php');
891
+		$model_names = array();
892
+		$non_abstract_db_models = array();
893
+		foreach ($models as $model) {
894
+			// get model classname
895
+			$classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
896
+			$short_name = str_replace('EEM_', '', $classname);
897
+			$reflectionClass = new ReflectionClass($classname);
898
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
899
+				$non_abstract_db_models[ $short_name ] = $classname;
900
+			}
901
+			$model_names[ $short_name ] = $classname;
902
+		}
903
+		$this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
904
+		$this->registry->non_abstract_db_models = apply_filters(
905
+			'FHEE__EE_System__parse_implemented_model_names',
906
+			$non_abstract_db_models
907
+		);
908
+	}
909
+
910
+
911
+	/**
912
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
913
+	 * that need to be setup before our EE_System launches.
914
+	 *
915
+	 * @return void
916
+	 * @throws DomainException
917
+	 * @throws InvalidArgumentException
918
+	 * @throws InvalidDataTypeException
919
+	 * @throws InvalidInterfaceException
920
+	 * @throws InvalidClassException
921
+	 * @throws InvalidFilePathException
922
+	 */
923
+	private function _maybe_brew_regular()
924
+	{
925
+		/** @var Domain $domain */
926
+		$domain = DomainFactory::getShared(
927
+			new FullyQualifiedName(
928
+				'EventEspresso\core\domain\Domain'
929
+			),
930
+			array(
931
+				new FilePath(EVENT_ESPRESSO_MAIN_FILE),
932
+				Version::fromString(espresso_version()),
933
+			)
934
+		);
935
+		if ($domain->isCaffeinated()) {
936
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
937
+		}
938
+	}
939
+
940
+
941
+	/**
942
+	 * @since 4.9.71.p
943
+	 * @throws Exception
944
+	 */
945
+	public function loadRouteMatchSpecifications()
946
+	{
947
+		try {
948
+			$this->loader->getShared(
949
+				'EventEspresso\core\services\route_match\RouteMatchSpecificationManager'
950
+			);
951
+		} catch (Exception $exception) {
952
+			new ExceptionStackTraceDisplay($exception);
953
+		}
954
+		do_action('AHEE__EE_System__loadRouteMatchSpecifications');
955
+	}
956
+
957
+
958
+	/**
959
+	 * register_shortcodes_modules_and_widgets
960
+	 * generate lists of shortcodes and modules, then verify paths and classes
961
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
962
+	 * which runs during the WP 'plugins_loaded' action at priority 7
963
+	 *
964
+	 * @access public
965
+	 * @return void
966
+	 * @throws Exception
967
+	 */
968
+	public function register_shortcodes_modules_and_widgets()
969
+	{
970
+		if ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isAjax()) {
971
+			// load, register, and add shortcodes the new way
972
+			$this->loader->getShared('EventEspresso\core\services\shortcodes\ShortcodesManager');
973
+		}
974
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
975
+		// check for addons using old hook point
976
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
977
+			$this->_incompatible_addon_error();
978
+		}
979
+	}
980
+
981
+
982
+	/**
983
+	 * _incompatible_addon_error
984
+	 *
985
+	 * @access public
986
+	 * @return void
987
+	 */
988
+	private function _incompatible_addon_error()
989
+	{
990
+		// get array of classes hooking into here
991
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
992
+			'AHEE__EE_System__register_shortcodes_modules_and_addons'
993
+		);
994
+		if (! empty($class_names)) {
995
+			$msg = esc_html__(
996
+				'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
997
+				'event_espresso'
998
+			);
999
+			$msg .= '<ul>';
1000
+			foreach ($class_names as $class_name) {
1001
+				$msg .= '<li><b>Event Espresso - '
1002
+						. str_replace(
1003
+							array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
1004
+							'',
1005
+							$class_name
1006
+						) . '</b></li>';
1007
+			}
1008
+			$msg .= '</ul>';
1009
+			$msg .= esc_html__(
1010
+				'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1011
+				'event_espresso'
1012
+			);
1013
+			// save list of incompatible addons to wp-options for later use
1014
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
1015
+			if (is_admin()) {
1016
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1017
+			}
1018
+		}
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * brew_espresso
1024
+	 * begins the process of setting hooks for initializing EE in the correct order
1025
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1026
+	 * which runs during the WP 'plugins_loaded' action at priority 9
1027
+	 *
1028
+	 * @return void
1029
+	 */
1030
+	public function brew_espresso()
1031
+	{
1032
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
1033
+		// load some final core systems
1034
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
1035
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1036
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
1037
+		add_action('init', array($this, 'load_controllers'), 7);
1038
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
1039
+		add_action('init', array($this, 'initialize'), 10);
1040
+		add_action('init', array($this, 'initialize_last'), 100);
1041
+		if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1042
+			// pew pew pew
1043
+			$this->loader->getShared('EventEspresso\core\services\licensing\LicenseService');
1044
+			do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1045
+		}
1046
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
1047
+	}
1048
+
1049
+
1050
+	/**
1051
+	 *    set_hooks_for_core
1052
+	 *
1053
+	 * @access public
1054
+	 * @return    void
1055
+	 * @throws EE_Error
1056
+	 */
1057
+	public function set_hooks_for_core()
1058
+	{
1059
+		$this->_deactivate_incompatible_addons();
1060
+		do_action('AHEE__EE_System__set_hooks_for_core');
1061
+		$this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1062
+		// caps need to be initialized on every request so that capability maps are set.
1063
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1064
+		$this->registry->CAP->init_caps();
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
1070
+	 * deactivates any addons considered incompatible with the current version of EE
1071
+	 */
1072
+	private function _deactivate_incompatible_addons()
1073
+	{
1074
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
1075
+		if (! empty($incompatible_addons)) {
1076
+			$active_plugins = get_option('active_plugins', array());
1077
+			foreach ($active_plugins as $active_plugin) {
1078
+				foreach ($incompatible_addons as $incompatible_addon) {
1079
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
1080
+						$this->request->unSetRequestParams(['activate'], true);
1081
+						espresso_deactivate_plugin($active_plugin);
1082
+					}
1083
+				}
1084
+			}
1085
+		}
1086
+	}
1087
+
1088
+
1089
+	/**
1090
+	 *    perform_activations_upgrades_and_migrations
1091
+	 *
1092
+	 * @access public
1093
+	 * @return    void
1094
+	 */
1095
+	public function perform_activations_upgrades_and_migrations()
1096
+	{
1097
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * @return void
1103
+	 * @throws DomainException
1104
+	 */
1105
+	public function load_CPTs_and_session()
1106
+	{
1107
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
1108
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies $register_custom_taxonomies */
1109
+		$register_custom_taxonomies = $this->loader->getShared(
1110
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomies'
1111
+		);
1112
+		$register_custom_taxonomies->registerCustomTaxonomies();
1113
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes $register_custom_post_types */
1114
+		$register_custom_post_types = $this->loader->getShared(
1115
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomPostTypes'
1116
+		);
1117
+		$register_custom_post_types->registerCustomPostTypes();
1118
+		/** @var EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms */
1119
+		$register_custom_taxonomy_terms = $this->loader->getShared(
1120
+			'EventEspresso\core\domain\services\custom_post_types\RegisterCustomTaxonomyTerms'
1121
+		);
1122
+		$register_custom_taxonomy_terms->registerCustomTaxonomyTerms();
1123
+		// load legacy Custom Post Types and Taxonomies
1124
+		$this->loader->getShared('EE_Register_CPTs');
1125
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * load_controllers
1131
+	 * this is the best place to load any additional controllers that needs access to EE core.
1132
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1133
+	 * time
1134
+	 *
1135
+	 * @access public
1136
+	 * @return void
1137
+	 */
1138
+	public function load_controllers()
1139
+	{
1140
+		do_action('AHEE__EE_System__load_controllers__start');
1141
+		// let's get it started
1142
+		if (
1143
+			! $this->maintenance_mode->level()
1144
+			&& ($this->request->isFrontend() || $this->request->isFrontAjax())
1145
+		) {
1146
+			do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1147
+			$this->loader->getShared('EE_Front_Controller');
1148
+		} elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1149
+			do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1150
+			$this->loader->getShared('EE_Admin');
1151
+		} elseif ($this->request->isWordPressHeartbeat()) {
1152
+			$this->loader->getShared('EventEspresso\core\domain\services\admin\ajax\WordpressHeartbeat');
1153
+		}
1154
+		do_action('AHEE__EE_System__load_controllers__complete');
1155
+	}
1156
+
1157
+
1158
+	/**
1159
+	 * core_loaded_and_ready
1160
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1161
+	 *
1162
+	 * @access public
1163
+	 * @return void
1164
+	 * @throws Exception
1165
+	 */
1166
+	public function core_loaded_and_ready()
1167
+	{
1168
+		if (
1169
+			$this->request->isAdmin()
1170
+			|| $this->request->isFrontend()
1171
+			|| $this->request->isIframe()
1172
+			|| $this->request->isWordPressApi()
1173
+		) {
1174
+			try {
1175
+				$this->loader->getShared('EventEspresso\core\services\assets\Registry');
1176
+				$this->loader->getShared('EventEspresso\core\domain\services\assets\CoreAssetManager');
1177
+				if ($this->canLoadBlocks()) {
1178
+					$this->loader->getShared(
1179
+						'EventEspresso\core\services\editor\BlockRegistrationManager'
1180
+					);
1181
+				}
1182
+			} catch (Exception $exception) {
1183
+				new ExceptionStackTraceDisplay($exception);
1184
+			}
1185
+		}
1186
+		if (
1187
+			$this->request->isAdmin()
1188
+			|| $this->request->isEeAjax()
1189
+			|| $this->request->isFrontend()
1190
+		) {
1191
+			$this->loader->getShared('EE_Session');
1192
+		}
1193
+		// integrate WP_Query with the EE models
1194
+		$this->loader->getShared('EE_CPT_Strategy');
1195
+		// load legacy EE_Request_Handler in case add-ons still need it
1196
+		$this->loader->getShared('EE_Request_Handler');
1197
+		do_action('AHEE__EE_System__core_loaded_and_ready');
1198
+		// always load template tags, because it's faster than checking if it's a front-end request, and many page
1199
+		// builders require these even on the front-end
1200
+		require_once EE_PUBLIC . 'template_tags.php';
1201
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1202
+	}
1203
+
1204
+
1205
+	/**
1206
+	 * initialize
1207
+	 * this is the best place to begin initializing client code
1208
+	 *
1209
+	 * @access public
1210
+	 * @return void
1211
+	 */
1212
+	public function initialize()
1213
+	{
1214
+		do_action('AHEE__EE_System__initialize');
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 * initialize_last
1220
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1221
+	 * initialize has done so
1222
+	 *
1223
+	 * @access public
1224
+	 * @return void
1225
+	 */
1226
+	public function initialize_last()
1227
+	{
1228
+		do_action('AHEE__EE_System__initialize_last');
1229
+		/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
1230
+		$rewrite_rules = $this->loader->getShared(
1231
+			'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
1232
+		);
1233
+		$rewrite_rules->flushRewriteRules();
1234
+		add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1235
+		if (
1236
+			($this->request->isAjax() || $this->request->isAdmin())
1237
+			&& $this->maintenance_mode->models_can_query()
1238
+		) {
1239
+			$this->loader->getShared('EventEspresso\core\services\privacy\export\PersonalDataExporterManager');
1240
+			$this->loader->getShared('EventEspresso\core\services\privacy\erasure\PersonalDataEraserManager');
1241
+		}
1242
+	}
1243
+
1244
+
1245
+	/**
1246
+	 * @return void
1247
+	 * @throws EE_Error
1248
+	 */
1249
+	public function addEspressoToolbar()
1250
+	{
1251
+		$this->loader->getShared(
1252
+			'EventEspresso\core\domain\services\admin\AdminToolBar',
1253
+			array($this->registry->CAP)
1254
+		);
1255
+	}
1256
+
1257
+
1258
+	/**
1259
+	 * do_not_cache
1260
+	 * sets no cache headers and defines no cache constants for WP plugins
1261
+	 *
1262
+	 * @access public
1263
+	 * @return void
1264
+	 */
1265
+	public static function do_not_cache()
1266
+	{
1267
+		// set no cache constants
1268
+		if (! defined('DONOTCACHEPAGE')) {
1269
+			define('DONOTCACHEPAGE', true);
1270
+		}
1271
+		if (! defined('DONOTCACHCEOBJECT')) {
1272
+			define('DONOTCACHCEOBJECT', true);
1273
+		}
1274
+		if (! defined('DONOTCACHEDB')) {
1275
+			define('DONOTCACHEDB', true);
1276
+		}
1277
+		// add no cache headers
1278
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1279
+		// plus a little extra for nginx and Google Chrome
1280
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1281
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1282
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1283
+	}
1284
+
1285
+
1286
+	/**
1287
+	 *    extra_nocache_headers
1288
+	 *
1289
+	 * @access    public
1290
+	 * @param $headers
1291
+	 * @return    array
1292
+	 */
1293
+	public static function extra_nocache_headers($headers)
1294
+	{
1295
+		// for NGINX
1296
+		$headers['X-Accel-Expires'] = 0;
1297
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1298
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1299
+		return $headers;
1300
+	}
1301
+
1302
+
1303
+	/**
1304
+	 *    nocache_headers
1305
+	 *
1306
+	 * @access    public
1307
+	 * @return    void
1308
+	 */
1309
+	public static function nocache_headers()
1310
+	{
1311
+		nocache_headers();
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1317
+	 * never returned with the function.
1318
+	 *
1319
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1320
+	 * @return array
1321
+	 */
1322
+	public function remove_pages_from_wp_list_pages($exclude_array)
1323
+	{
1324
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Return whether blocks can be registered/loaded or not.
1330
+	 * @return bool
1331
+	 */
1332
+	private function canLoadBlocks()
1333
+	{
1334
+		return apply_filters('FHEE__EE_System__canLoadBlocks', true)
1335
+			   && function_exists('register_block_type')
1336
+			   // don't load blocks if in the Divi page builder editor context
1337
+			   // @see https://github.com/eventespresso/event-espresso-core/issues/814
1338
+			   && ! $this->request->getRequestParam('et_fb', false);
1339
+	}
1340 1340
 }
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
         EE_Maintenance_Mode $maintenance_mode = null
142 142
     ) {
143 143
         // check if class object is instantiated
144
-        if (! self::$_instance instanceof EE_System) {
144
+        if ( ! self::$_instance instanceof EE_System) {
145 145
             self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
146 146
         }
147 147
         return self::$_instance;
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
         $this->capabilities = $this->loader->getShared('EE_Capabilities');
264 264
         add_action(
265 265
             'AHEE__EE_Capabilities__init_caps__before_initialization',
266
-            function () {
266
+            function() {
267 267
                 LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
268 268
             }
269 269
         );
@@ -304,7 +304,7 @@  discard block
 block discarded – undo
304 304
     {
305 305
         // set autoloaders for all of the classes implementing EEI_Plugin_API
306 306
         // which provide helpers for EE plugin authors to more easily register certain components with EE.
307
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
307
+        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES.'plugin_api');
308 308
     }
309 309
 
310 310
 
@@ -323,14 +323,14 @@  discard block
 block discarded – undo
323 323
         $load_callback,
324 324
         $plugin_file_constant
325 325
     ) {
326
-        if (! defined($version_constant)) {
326
+        if ( ! defined($version_constant)) {
327 327
             return;
328 328
         }
329 329
         $addon_version = constant($version_constant);
330 330
         if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
331 331
             remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
332
-            if (! function_exists('deactivate_plugins')) {
333
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
332
+            if ( ! function_exists('deactivate_plugins')) {
333
+                require_once ABSPATH.'wp-admin/includes/plugin.php';
334 334
             }
335 335
             deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
336 336
             $this->request->unSetRequestParams(['activate', 'activate-multi'], true);
@@ -344,7 +344,7 @@  discard block
 block discarded – undo
344 344
                     $min_version_required
345 345
                 ),
346 346
                 __FILE__,
347
-                __FUNCTION__ . "({$addon_name})",
347
+                __FUNCTION__."({$addon_name})",
348 348
                 __LINE__
349 349
             );
350 350
             EE_Error::get_notices(false, true);
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
                 true
397 397
             )
398 398
         ) {
399
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth/basic-auth.php';
399
+            include_once EE_THIRD_PARTY.'wp-api-basic-auth/basic-auth.php';
400 400
         }
401 401
         do_action('AHEE__EE_System__load_espresso_addons__complete');
402 402
     }
@@ -498,11 +498,11 @@  discard block
 block discarded – undo
498 498
     private function fix_espresso_db_upgrade_option($espresso_db_update = null)
499 499
     {
500 500
         do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
501
-        if (! $espresso_db_update) {
501
+        if ( ! $espresso_db_update) {
502 502
             $espresso_db_update = get_option('espresso_db_update');
503 503
         }
504 504
         // check that option is an array
505
-        if (! is_array($espresso_db_update)) {
505
+        if ( ! is_array($espresso_db_update)) {
506 506
             // if option is FALSE, then it never existed
507 507
             if ($espresso_db_update === false) {
508 508
                 // make $espresso_db_update an array and save option with autoload OFF
@@ -522,10 +522,10 @@  discard block
 block discarded – undo
522 522
                     // so it must be numerically-indexed, where values are versions installed...
523 523
                     // fix it!
524 524
                     $version_string = $should_be_array;
525
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
525
+                    $corrected_db_update[$version_string] = array('unknown-date');
526 526
                 } else {
527 527
                     // ok it checks out
528
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
528
+                    $corrected_db_update[$should_be_version_string] = $should_be_array;
529 529
                 }
530 530
             }
531 531
             $espresso_db_update = $corrected_db_update;
@@ -609,13 +609,13 @@  discard block
 block discarded – undo
609 609
      */
610 610
     public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
611 611
     {
612
-        if (! $version_history) {
612
+        if ( ! $version_history) {
613 613
             $version_history = $this->fix_espresso_db_upgrade_option($version_history);
614 614
         }
615 615
         if ($current_version_to_add === null) {
616 616
             $current_version_to_add = espresso_version();
617 617
         }
618
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
618
+        $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
619 619
         // re-save
620 620
         return update_option('espresso_db_update', $version_history);
621 621
     }
@@ -705,7 +705,7 @@  discard block
 block discarded – undo
705 705
         if ($activation_history_for_addon) {
706 706
             // it exists, so this isn't a completely new install
707 707
             // check if this version already in that list of previously installed versions
708
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
708
+            if ( ! isset($activation_history_for_addon[$version_to_upgrade_to])) {
709 709
                 // it a version we haven't seen before
710 710
                 if ($version_is_higher === 1) {
711 711
                     $req_type = EE_System::req_type_upgrade;
@@ -783,7 +783,7 @@  discard block
 block discarded – undo
783 783
             foreach ($activation_history as $version => $times_activated) {
784 784
                 // check there is a record of when this version was activated. Otherwise,
785 785
                 // mark it as unknown
786
-                if (! $times_activated) {
786
+                if ( ! $times_activated) {
787 787
                     $times_activated = array('unknown-date');
788 788
                 }
789 789
                 if (is_string($times_activated)) {
@@ -887,7 +887,7 @@  discard block
 block discarded – undo
887 887
     private function _parse_model_names()
888 888
     {
889 889
         // get all the files in the EE_MODELS folder that end in .model.php
890
-        $models = glob(EE_MODELS . '*.model.php');
890
+        $models = glob(EE_MODELS.'*.model.php');
891 891
         $model_names = array();
892 892
         $non_abstract_db_models = array();
893 893
         foreach ($models as $model) {
@@ -896,9 +896,9 @@  discard block
 block discarded – undo
896 896
             $short_name = str_replace('EEM_', '', $classname);
897 897
             $reflectionClass = new ReflectionClass($classname);
898 898
             if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
899
-                $non_abstract_db_models[ $short_name ] = $classname;
899
+                $non_abstract_db_models[$short_name] = $classname;
900 900
             }
901
-            $model_names[ $short_name ] = $classname;
901
+            $model_names[$short_name] = $classname;
902 902
         }
903 903
         $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
904 904
         $this->registry->non_abstract_db_models = apply_filters(
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
             )
934 934
         );
935 935
         if ($domain->isCaffeinated()) {
936
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
936
+            require_once EE_CAFF_PATH.'brewing_regular.php';
937 937
         }
938 938
     }
939 939
 
@@ -991,7 +991,7 @@  discard block
 block discarded – undo
991 991
         $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
992 992
             'AHEE__EE_System__register_shortcodes_modules_and_addons'
993 993
         );
994
-        if (! empty($class_names)) {
994
+        if ( ! empty($class_names)) {
995 995
             $msg = esc_html__(
996 996
                 'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
997 997
                 'event_espresso'
@@ -1003,7 +1003,7 @@  discard block
 block discarded – undo
1003 1003
                             array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'),
1004 1004
                             '',
1005 1005
                             $class_name
1006
-                        ) . '</b></li>';
1006
+                        ).'</b></li>';
1007 1007
             }
1008 1008
             $msg .= '</ul>';
1009 1009
             $msg .= esc_html__(
@@ -1072,7 +1072,7 @@  discard block
 block discarded – undo
1072 1072
     private function _deactivate_incompatible_addons()
1073 1073
     {
1074 1074
         $incompatible_addons = get_option('ee_incompatible_addons', array());
1075
-        if (! empty($incompatible_addons)) {
1075
+        if ( ! empty($incompatible_addons)) {
1076 1076
             $active_plugins = get_option('active_plugins', array());
1077 1077
             foreach ($active_plugins as $active_plugin) {
1078 1078
                 foreach ($incompatible_addons as $incompatible_addon) {
@@ -1197,7 +1197,7 @@  discard block
 block discarded – undo
1197 1197
         do_action('AHEE__EE_System__core_loaded_and_ready');
1198 1198
         // always load template tags, because it's faster than checking if it's a front-end request, and many page
1199 1199
         // builders require these even on the front-end
1200
-        require_once EE_PUBLIC . 'template_tags.php';
1200
+        require_once EE_PUBLIC.'template_tags.php';
1201 1201
         do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1202 1202
     }
1203 1203
 
@@ -1265,13 +1265,13 @@  discard block
 block discarded – undo
1265 1265
     public static function do_not_cache()
1266 1266
     {
1267 1267
         // set no cache constants
1268
-        if (! defined('DONOTCACHEPAGE')) {
1268
+        if ( ! defined('DONOTCACHEPAGE')) {
1269 1269
             define('DONOTCACHEPAGE', true);
1270 1270
         }
1271
-        if (! defined('DONOTCACHCEOBJECT')) {
1271
+        if ( ! defined('DONOTCACHCEOBJECT')) {
1272 1272
             define('DONOTCACHCEOBJECT', true);
1273 1273
         }
1274
-        if (! defined('DONOTCACHEDB')) {
1274
+        if ( ! defined('DONOTCACHEDB')) {
1275 1275
             define('DONOTCACHEDB', true);
1276 1276
         }
1277 1277
         // add no cache headers
Please login to merge, or discard this patch.
core/EE_Registry.core.php 2 patches
Indentation   +1689 added lines, -1689 removed lines patch added patch discarded remove patch
@@ -23,1697 +23,1697 @@
 block discarded – undo
23 23
 class EE_Registry implements ResettableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Registry $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var EE_Dependency_Map $_dependency_map
33
-     */
34
-    protected $_dependency_map;
35
-
36
-    /**
37
-     * @var Mirror
38
-     */
39
-    private $mirror;
40
-
41
-    /**
42
-     * @var ClassInterfaceCache $class_cache
43
-     */
44
-    private $class_cache;
45
-
46
-    /**
47
-     * @var array $_class_abbreviations
48
-     */
49
-    protected $_class_abbreviations = array();
50
-
51
-    /**
52
-     * @var CommandBusInterface $BUS
53
-     */
54
-    public $BUS;
55
-
56
-    /**
57
-     * @var EE_Cart $CART
58
-     */
59
-    public $CART;
60
-
61
-    /**
62
-     * @var EE_Config $CFG
63
-     */
64
-    public $CFG;
65
-
66
-    /**
67
-     * @var EE_Network_Config $NET_CFG
68
-     */
69
-    public $NET_CFG;
70
-
71
-    /**
72
-     * RegistryContainer for storing library classes in
73
-     *
74
-     * @var RegistryContainer $LIB
75
-     */
76
-    public $LIB;
77
-
78
-    /**
79
-     * @var EE_Request_Handler $REQ
80
-     * @deprecated 4.10.14.p
81
-     */
82
-    public $REQ;
83
-
84
-    /**
85
-     * @var EE_Session $SSN
86
-     */
87
-    public $SSN;
88
-
89
-    /**
90
-     * @since 4.5.0
91
-     * @var EE_Capabilities $CAP
92
-     */
93
-    public $CAP;
94
-
95
-    /**
96
-     * @since 4.9.0
97
-     * @var EE_Message_Resource_Manager $MRM
98
-     */
99
-    public $MRM;
100
-
101
-    /**
102
-     * @var Registry $AssetsRegistry
103
-     */
104
-    public $AssetsRegistry;
105
-
106
-    /**
107
-     * RegistryContainer for holding addons which have registered themselves to work with EE core
108
-     *
109
-     * @var EE_Addon[] $addons
110
-     */
111
-    public $addons;
112
-
113
-    /**
114
-     * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
115
-     *
116
-     * @var EEM_Base[] $models
117
-     */
118
-    public $models = array();
119
-
120
-    /**
121
-     * @var EED_Module[] $modules
122
-     */
123
-    public $modules;
124
-
125
-    /**
126
-     * @var EES_Shortcode[] $shortcodes
127
-     */
128
-    public $shortcodes;
129
-
130
-    /**
131
-     * @var WP_Widget[] $widgets
132
-     */
133
-    public $widgets;
134
-
135
-    /**
136
-     * this is an array of all implemented model names (i.e. not the parent abstract models, or models
137
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
138
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
139
-     * classnames (eg "EEM_Event")
140
-     *
141
-     * @var array $non_abstract_db_models
142
-     */
143
-    public $non_abstract_db_models = array();
144
-
145
-    /**
146
-     * internationalization for JS strings
147
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
148
-     *    in js file:  var translatedString = eei18n.string_key;
149
-     *
150
-     * @var array $i18n_js_strings
151
-     */
152
-    public static $i18n_js_strings = array();
153
-
154
-    /**
155
-     * $main_file - path to espresso.php
156
-     *
157
-     * @var array $main_file
158
-     */
159
-    public $main_file;
160
-
161
-    /**
162
-     * array of ReflectionClass objects where the key is the class name
163
-     *
164
-     * @deprecated 4.9.62.p
165
-     * @var ReflectionClass[] $_reflectors
166
-     */
167
-    public $_reflectors;
168
-
169
-    /**
170
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
171
-     *
172
-     * @var boolean $_cache_on
173
-     */
174
-    protected $_cache_on = true;
175
-
176
-    /**
177
-     * @var ObjectIdentifier
178
-     */
179
-    private $object_identifier;
180
-
181
-
182
-    /**
183
-     * @singleton method used to instantiate class object
184
-     * @param EE_Dependency_Map|null   $dependency_map
185
-     * @param Mirror|null              $mirror
186
-     * @param ClassInterfaceCache|null $class_cache
187
-     * @param ObjectIdentifier|null    $object_identifier
188
-     * @return EE_Registry instance
189
-     */
190
-    public static function instance(
191
-        EE_Dependency_Map $dependency_map = null,
192
-        Mirror $mirror = null,
193
-        ClassInterfaceCache $class_cache = null,
194
-        ObjectIdentifier $object_identifier = null
195
-    ) {
196
-        // check if class object is instantiated
197
-        if (
198
-            ! self::$_instance instanceof EE_Registry
199
-            && $dependency_map instanceof EE_Dependency_Map
200
-            && $mirror instanceof Mirror
201
-            && $class_cache instanceof ClassInterfaceCache
202
-            && $object_identifier instanceof ObjectIdentifier
203
-        ) {
204
-            self::$_instance = new self(
205
-                $dependency_map,
206
-                $mirror,
207
-                $class_cache,
208
-                $object_identifier
209
-            );
210
-        }
211
-        return self::$_instance;
212
-    }
213
-
214
-
215
-    /**
216
-     * protected constructor to prevent direct creation
217
-     *
218
-     * @Constructor
219
-     * @param  EE_Dependency_Map  $dependency_map
220
-     * @param Mirror              $mirror
221
-     * @param ClassInterfaceCache $class_cache
222
-     * @param ObjectIdentifier    $object_identifier
223
-     */
224
-    protected function __construct(
225
-        EE_Dependency_Map $dependency_map,
226
-        Mirror $mirror,
227
-        ClassInterfaceCache $class_cache,
228
-        ObjectIdentifier $object_identifier
229
-    ) {
230
-        $this->_dependency_map = $dependency_map;
231
-        $this->mirror = $mirror;
232
-        $this->class_cache = $class_cache;
233
-        $this->object_identifier = $object_identifier;
234
-        // $registry_container = new RegistryContainer();
235
-        $this->LIB = new RegistryContainer();
236
-        $this->addons = new RegistryContainer();
237
-        $this->modules = new RegistryContainer();
238
-        $this->shortcodes = new RegistryContainer();
239
-        $this->widgets = new RegistryContainer();
240
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
241
-    }
242
-
243
-
244
-    /**
245
-     * initialize
246
-     *
247
-     * @throws OutOfBoundsException
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidInterfaceException
250
-     * @throws InvalidDataTypeException
251
-     * @throws EE_Error
252
-     * @throws ReflectionException
253
-     */
254
-    public function initialize()
255
-    {
256
-        $this->_class_abbreviations = apply_filters(
257
-            'FHEE__EE_Registry____construct___class_abbreviations',
258
-            array(
259
-                'EE_Config'                                       => 'CFG',
260
-                'EE_Session'                                      => 'SSN',
261
-                'EE_Capabilities'                                 => 'CAP',
262
-                'EE_Cart'                                         => 'CART',
263
-                'EE_Network_Config'                               => 'NET_CFG',
264
-                'EE_Request_Handler'                              => 'REQ',
265
-                'EE_Message_Resource_Manager'                     => 'MRM',
266
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
267
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
268
-            )
269
-        );
270
-        $this->load_core('Base', array(), true);
271
-        // add our request and response objects to the cache
272
-        $request_loader = $this->_dependency_map->class_loader(
273
-            'EventEspresso\core\services\request\Request'
274
-        );
275
-        $this->_set_cached_class(
276
-            $request_loader(),
277
-            'EventEspresso\core\services\request\Request'
278
-        );
279
-        $response_loader = $this->_dependency_map->class_loader(
280
-            'EventEspresso\core\services\request\Response'
281
-        );
282
-        $this->_set_cached_class(
283
-            $response_loader(),
284
-            'EventEspresso\core\services\request\Response'
285
-        );
286
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
287
-    }
288
-
289
-
290
-    /**
291
-     * @return void
292
-     */
293
-    public function init()
294
-    {
295
-        // Get current page protocol
296
-        $protocol = is_ssl() ? 'https://' : 'http://';
297
-        // Output admin-ajax.php URL with same protocol as current page
298
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
299
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
300
-    }
301
-
302
-
303
-    /**
304
-     * @return array
305
-     */
306
-    public static function sanitize_i18n_js_strings()
307
-    {
308
-        $i18n_js_strings = (array) self::$i18n_js_strings;
309
-        foreach ($i18n_js_strings as $key => $value) {
310
-            if (is_scalar($value)) {
311
-                $decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
-                $i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
313
-            }
314
-        }
315
-        return $i18n_js_strings;
316
-    }
317
-
318
-
319
-    /**
320
-     * localize_i18n_js_strings
321
-     *
322
-     * @return string
323
-     */
324
-    public static function localize_i18n_js_strings()
325
-    {
326
-        $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
327
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
328
-    }
329
-
330
-
331
-    /**
332
-     * @param mixed string | EED_Module $module
333
-     * @throws OutOfBoundsException
334
-     * @throws InvalidArgumentException
335
-     * @throws InvalidInterfaceException
336
-     * @throws InvalidDataTypeException
337
-     * @throws EE_Error
338
-     * @throws ReflectionException
339
-     */
340
-    public function add_module($module)
341
-    {
342
-        if ($module instanceof EED_Module) {
343
-            $module_class = get_class($module);
344
-            $this->modules->add($module_class, $module);
345
-        } else {
346
-            if (! class_exists('EE_Module_Request_Router', false)) {
347
-                $this->load_core('Module_Request_Router');
348
-            }
349
-            EE_Module_Request_Router::module_factory($module);
350
-        }
351
-    }
352
-
353
-
354
-    /**
355
-     * @param string $module_name
356
-     * @return mixed EED_Module | NULL
357
-     */
358
-    public function get_module($module_name = '')
359
-    {
360
-        return $this->modules->get($module_name);
361
-    }
362
-
363
-
364
-    /**
365
-     * loads core classes - must be singletons
366
-     *
367
-     * @param string $class_name - simple class name ie: session
368
-     * @param mixed  $arguments
369
-     * @param bool   $load_only
370
-     * @return mixed
371
-     * @throws InvalidInterfaceException
372
-     * @throws InvalidDataTypeException
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     * @throws InvalidArgumentException
376
-     */
377
-    public function load_core($class_name, $arguments = array(), $load_only = false)
378
-    {
379
-        $core_paths = apply_filters(
380
-            'FHEE__EE_Registry__load_core__core_paths',
381
-            array(
382
-                EE_CORE,
383
-                EE_ADMIN,
384
-                EE_CPTS,
385
-                EE_CORE . 'CPTs/',
386
-                EE_CORE . 'data_migration_scripts/',
387
-                EE_CORE . 'request_stack/',
388
-                EE_CORE . 'middleware/',
389
-            )
390
-        );
391
-        // retrieve instantiated class
392
-        return $this->_load(
393
-            $core_paths,
394
-            'EE_',
395
-            $class_name,
396
-            'core',
397
-            $arguments,
398
-            false,
399
-            true,
400
-            $load_only
401
-        );
402
-    }
403
-
404
-
405
-    /**
406
-     * loads service classes
407
-     *
408
-     * @param string $class_name - simple class name ie: session
409
-     * @param mixed  $arguments
410
-     * @param bool   $load_only
411
-     * @return mixed
412
-     * @throws InvalidInterfaceException
413
-     * @throws InvalidDataTypeException
414
-     * @throws EE_Error
415
-     * @throws ReflectionException
416
-     * @throws InvalidArgumentException
417
-     */
418
-    public function load_service($class_name, $arguments = array(), $load_only = false)
419
-    {
420
-        $service_paths = apply_filters(
421
-            'FHEE__EE_Registry__load_service__service_paths',
422
-            array(
423
-                EE_CORE . 'services/',
424
-            )
425
-        );
426
-        // retrieve instantiated class
427
-        return $this->_load(
428
-            $service_paths,
429
-            'EE_',
430
-            $class_name,
431
-            'class',
432
-            $arguments,
433
-            false,
434
-            true,
435
-            $load_only
436
-        );
437
-    }
438
-
439
-
440
-    /**
441
-     * loads data_migration_scripts
442
-     *
443
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
444
-     * @param mixed  $arguments
445
-     * @return EE_Data_Migration_Script_Base|mixed
446
-     * @throws InvalidInterfaceException
447
-     * @throws InvalidDataTypeException
448
-     * @throws EE_Error
449
-     * @throws ReflectionException
450
-     * @throws InvalidArgumentException
451
-     */
452
-    public function load_dms($class_name, $arguments = array())
453
-    {
454
-        // retrieve instantiated class
455
-        return $this->_load(
456
-            EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
457
-            'EE_DMS_',
458
-            $class_name,
459
-            'dms',
460
-            $arguments,
461
-            false,
462
-            false
463
-        );
464
-    }
465
-
466
-
467
-    /**
468
-     * loads object creating classes - must be singletons
469
-     *
470
-     * @param string $class_name - simple class name ie: attendee
471
-     * @param mixed  $arguments  - an array of arguments to pass to the class
472
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
473
-     *                           instantiate
474
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
475
-     *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
476
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
477
-     *                           (default)
478
-     * @return EE_Base_Class | bool
479
-     * @throws InvalidInterfaceException
480
-     * @throws InvalidDataTypeException
481
-     * @throws EE_Error
482
-     * @throws ReflectionException
483
-     * @throws InvalidArgumentException
484
-     */
485
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
486
-    {
487
-        $paths = apply_filters(
488
-            'FHEE__EE_Registry__load_class__paths',
489
-            array(
490
-                EE_CORE,
491
-                EE_CLASSES,
492
-                EE_BUSINESS,
493
-            )
494
-        );
495
-        // retrieve instantiated class
496
-        return $this->_load(
497
-            $paths,
498
-            'EE_',
499
-            $class_name,
500
-            'class',
501
-            $arguments,
502
-            $from_db,
503
-            $cache,
504
-            $load_only
505
-        );
506
-    }
507
-
508
-
509
-    /**
510
-     * loads helper classes - must be singletons
511
-     *
512
-     * @param string $class_name - simple class name ie: price
513
-     * @param mixed  $arguments
514
-     * @param bool   $load_only
515
-     * @return EEH_Base | bool
516
-     * @throws InvalidInterfaceException
517
-     * @throws InvalidDataTypeException
518
-     * @throws EE_Error
519
-     * @throws ReflectionException
520
-     * @throws InvalidArgumentException
521
-     */
522
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
523
-    {
524
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
525
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
526
-        // retrieve instantiated class
527
-        return $this->_load(
528
-            $helper_paths,
529
-            'EEH_',
530
-            $class_name,
531
-            'helper',
532
-            $arguments,
533
-            false,
534
-            true,
535
-            $load_only
536
-        );
537
-    }
538
-
539
-
540
-    /**
541
-     * loads core classes - must be singletons
542
-     *
543
-     * @param string $class_name - simple class name ie: session
544
-     * @param mixed  $arguments
545
-     * @param bool   $load_only
546
-     * @param bool   $cache      whether to cache the object or not.
547
-     * @return mixed
548
-     * @throws InvalidInterfaceException
549
-     * @throws InvalidDataTypeException
550
-     * @throws EE_Error
551
-     * @throws ReflectionException
552
-     * @throws InvalidArgumentException
553
-     */
554
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
555
-    {
556
-        $paths = array(
557
-            EE_LIBRARIES,
558
-            EE_LIBRARIES . 'messages/',
559
-            EE_LIBRARIES . 'shortcodes/',
560
-            EE_LIBRARIES . 'qtips/',
561
-            EE_LIBRARIES . 'payment_methods/',
562
-        );
563
-        // retrieve instantiated class
564
-        return $this->_load(
565
-            $paths,
566
-            'EE_',
567
-            $class_name,
568
-            'lib',
569
-            $arguments,
570
-            false,
571
-            $cache,
572
-            $load_only
573
-        );
574
-    }
575
-
576
-
577
-    /**
578
-     * loads model classes - must be singletons
579
-     *
580
-     * @param string $class_name - simple class name ie: price
581
-     * @param mixed  $arguments
582
-     * @param bool   $load_only
583
-     * @return EEM_Base | bool
584
-     * @throws InvalidInterfaceException
585
-     * @throws InvalidDataTypeException
586
-     * @throws EE_Error
587
-     * @throws ReflectionException
588
-     * @throws InvalidArgumentException
589
-     */
590
-    public function load_model($class_name, $arguments = array(), $load_only = false)
591
-    {
592
-        $paths = apply_filters(
593
-            'FHEE__EE_Registry__load_model__paths',
594
-            array(
595
-                EE_MODELS,
596
-                EE_CORE,
597
-            )
598
-        );
599
-        // retrieve instantiated class
600
-        return $this->_load(
601
-            $paths,
602
-            'EEM_',
603
-            $class_name,
604
-            'model',
605
-            $arguments,
606
-            false,
607
-            true,
608
-            $load_only
609
-        );
610
-    }
611
-
612
-
613
-    /**
614
-     * loads model classes - must be singletons
615
-     *
616
-     * @param string $class_name - simple class name ie: price
617
-     * @param mixed  $arguments
618
-     * @param bool   $load_only
619
-     * @return mixed | bool
620
-     * @throws InvalidInterfaceException
621
-     * @throws InvalidDataTypeException
622
-     * @throws EE_Error
623
-     * @throws ReflectionException
624
-     * @throws InvalidArgumentException
625
-     */
626
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
627
-    {
628
-        $paths = array(
629
-            EE_MODELS . 'fields/',
630
-            EE_MODELS . 'helpers/',
631
-            EE_MODELS . 'relations/',
632
-            EE_MODELS . 'strategies/',
633
-        );
634
-        // retrieve instantiated class
635
-        return $this->_load(
636
-            $paths,
637
-            'EE_',
638
-            $class_name,
639
-            '',
640
-            $arguments,
641
-            false,
642
-            true,
643
-            $load_only
644
-        );
645
-    }
646
-
647
-
648
-    /**
649
-     * Determines if $model_name is the name of an actual EE model.
650
-     *
651
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
652
-     * @return boolean
653
-     */
654
-    public function is_model_name($model_name)
655
-    {
656
-        return isset($this->models[ $model_name ]);
657
-    }
658
-
659
-
660
-    /**
661
-     * generic class loader
662
-     *
663
-     * @param string $path_to_file - directory path to file location, not including filename
664
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
665
-     * @param string $type         - file type - core? class? helper? model?
666
-     * @param mixed  $arguments
667
-     * @param bool   $load_only
668
-     * @return mixed
669
-     * @throws InvalidInterfaceException
670
-     * @throws InvalidDataTypeException
671
-     * @throws EE_Error
672
-     * @throws ReflectionException
673
-     * @throws InvalidArgumentException
674
-     */
675
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
676
-    {
677
-        // retrieve instantiated class
678
-        return $this->_load(
679
-            $path_to_file,
680
-            '',
681
-            $file_name,
682
-            $type,
683
-            $arguments,
684
-            false,
685
-            true,
686
-            $load_only
687
-        );
688
-    }
689
-
690
-
691
-    /**
692
-     * @param string $path_to_file - directory path to file location, not including filename
693
-     * @param string $class_name   - full class name  ie:  My_Class
694
-     * @param string $type         - file type - core? class? helper? model?
695
-     * @param mixed  $arguments
696
-     * @param bool   $load_only
697
-     * @return bool|EE_Addon|object
698
-     * @throws InvalidInterfaceException
699
-     * @throws InvalidDataTypeException
700
-     * @throws EE_Error
701
-     * @throws ReflectionException
702
-     * @throws InvalidArgumentException
703
-     */
704
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
705
-    {
706
-        // retrieve instantiated class
707
-        return $this->_load(
708
-            $path_to_file,
709
-            'addon',
710
-            $class_name,
711
-            $type,
712
-            $arguments,
713
-            false,
714
-            true,
715
-            $load_only
716
-        );
717
-    }
718
-
719
-
720
-    /**
721
-     * instantiates, caches, and automatically resolves dependencies
722
-     * for classes that use a Fully Qualified Class Name.
723
-     * if the class is not capable of being loaded using PSR-4 autoloading,
724
-     * then you need to use one of the existing load_*() methods
725
-     * which can resolve the classname and filepath from the passed arguments
726
-     *
727
-     * @param bool|string $class_name   Fully Qualified Class Name
728
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
729
-     * @param bool        $cache        whether to cache the instantiated object for reuse
730
-     * @param bool        $from_db      some classes are instantiated from the db
731
-     *                                  and thus call a different method to instantiate
732
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
733
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
734
-     * @return bool|null|mixed          null = failure to load or instantiate class object.
735
-     *                                  object = class loaded and instantiated successfully.
736
-     *                                  bool = fail or success when $load_only is true
737
-     * @throws InvalidInterfaceException
738
-     * @throws InvalidDataTypeException
739
-     * @throws EE_Error
740
-     * @throws ReflectionException
741
-     * @throws InvalidArgumentException
742
-     */
743
-    public function create(
744
-        $class_name = false,
745
-        $arguments = array(),
746
-        $cache = false,
747
-        $from_db = false,
748
-        $load_only = false,
749
-        $addon = false
750
-    ) {
751
-        $class_name = ltrim($class_name, '\\');
752
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
753
-        $class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
754
-        // if a non-FQCN was passed, then
755
-        // verifyClassExists() might return an object
756
-        // or it could return null if the class just could not be found anywhere
757
-        if ($class_exists instanceof $class_name || $class_exists === null) {
758
-            // either way, return the results
759
-            return $class_exists;
760
-        }
761
-        $class_name = $class_exists;
762
-        // if we're only loading the class and it already exists, then let's just return true immediately
763
-        if ($load_only) {
764
-            return true;
765
-        }
766
-        $addon = $addon ? 'addon' : '';
767
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
768
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
769
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
770
-        if ($this->_cache_on && $cache && ! $load_only) {
771
-            // return object if it's already cached
772
-            $cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
773
-            if ($cached_class !== null) {
774
-                return $cached_class;
775
-            }
776
-        }// obtain the loader method from the dependency map
777
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
778
-        if ($loader instanceof Closure) {
779
-            $class_obj = $loader($arguments);
780
-        } else {
781
-            if ($loader && method_exists($this, $loader)) {
782
-                $class_obj = $this->{$loader}($class_name, $arguments);
783
-            } else {
784
-                $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
785
-            }
786
-        }
787
-        if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
788
-            // save it for later... kinda like gum  { : $
789
-            $this->_set_cached_class(
790
-                $class_obj,
791
-                $class_name,
792
-                $addon,
793
-                $from_db,
794
-                $arguments
795
-            );
796
-        }
797
-        $this->_cache_on = true;
798
-        return $class_obj;
799
-    }
800
-
801
-
802
-    /**
803
-     * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
804
-     *
805
-     * @param string|object $class_name
806
-     * @param array         $arguments
807
-     * @param int           $attempt
808
-     * @return mixed
809
-     */
810
-    private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
811
-    {
812
-        if (is_object($class_name) || class_exists($class_name)) {
813
-            return $class_name;
814
-        }
815
-        switch ($attempt) {
816
-            case 1:
817
-                // if it's a FQCN then maybe the class is registered with a preceding \
818
-                $class_name = strpos($class_name, '\\') !== false
819
-                    ? '\\' . ltrim($class_name, '\\')
820
-                    : $class_name;
821
-                break;
822
-            case 2:
823
-                //
824
-                $loader = $this->_dependency_map->class_loader($class_name);
825
-                if ($loader && method_exists($this, $loader)) {
826
-                    return $this->{$loader}($class_name, $arguments);
827
-                }
828
-                break;
829
-            case 3:
830
-            default:
831
-                return null;
832
-        }
833
-        $attempt++;
834
-        return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
835
-    }
836
-
837
-
838
-    /**
839
-     * instantiates, caches, and injects dependencies for classes
840
-     *
841
-     * @param array       $file_paths   an array of paths to folders to look in
842
-     * @param string      $class_prefix EE  or EEM or... ???
843
-     * @param bool|string $class_name   $class name
844
-     * @param string      $type         file type - core? class? helper? model?
845
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
846
-     * @param bool        $from_db      some classes are instantiated from the db
847
-     *                                  and thus call a different method to instantiate
848
-     * @param bool        $cache        whether to cache the instantiated object for reuse
849
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
850
-     * @return bool|null|object null = failure to load or instantiate class object.
851
-     *                                  object = class loaded and instantiated successfully.
852
-     *                                  bool = fail or success when $load_only is true
853
-     * @throws EE_Error
854
-     * @throws ReflectionException
855
-     * @throws InvalidInterfaceException
856
-     * @throws InvalidDataTypeException
857
-     * @throws InvalidArgumentException
858
-     */
859
-    protected function _load(
860
-        $file_paths = array(),
861
-        $class_prefix = 'EE_',
862
-        $class_name = false,
863
-        $type = 'class',
864
-        $arguments = array(),
865
-        $from_db = false,
866
-        $cache = true,
867
-        $load_only = false
868
-    ) {
869
-        $class_name = ltrim($class_name, '\\');
870
-        // strip php file extension
871
-        $class_name = str_replace('.php', '', trim($class_name));
872
-        // does the class have a prefix ?
873
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
874
-            // make sure $class_prefix is uppercase
875
-            $class_prefix = strtoupper(trim($class_prefix));
876
-            // add class prefix ONCE!!!
877
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
878
-        }
879
-        $class_name = $this->class_cache->getFqnForAlias($class_name);
880
-        $class_exists = class_exists($class_name, false);
881
-        // if we're only loading the class and it already exists, then let's just return true immediately
882
-        if ($load_only && $class_exists) {
883
-            return true;
884
-        }
885
-        $arguments = is_array($arguments) ? $arguments : array($arguments);
886
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
887
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
888
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
889
-        if ($this->_cache_on && $cache && ! $load_only) {
890
-            // return object if it's already cached
891
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
892
-            if ($cached_class !== null) {
893
-                return $cached_class;
894
-            }
895
-        }
896
-        // if the class doesn't already exist.. then we need to try and find the file and load it
897
-        if (! $class_exists) {
898
-            // get full path to file
899
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
900
-            // load the file
901
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
902
-            // if we are only loading a file but NOT instantiating an object
903
-            // then return boolean for whether class was loaded or not
904
-            if ($load_only) {
905
-                return $loaded;
906
-            }
907
-            // if an object was expected but loading failed, then return nothing
908
-            if (! $loaded) {
909
-                return null;
910
-            }
911
-        }
912
-        // instantiate the requested object
913
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
914
-        if ($this->_cache_on && $cache) {
915
-            // save it for later... kinda like gum  { : $
916
-            $this->_set_cached_class(
917
-                $class_obj,
918
-                $class_name,
919
-                $class_prefix,
920
-                $from_db,
921
-                $arguments
922
-            );
923
-        }
924
-        $this->_cache_on = true;
925
-        return $class_obj;
926
-    }
927
-
928
-
929
-    /**
930
-     * @param string $class_name
931
-     * @param string $default have to specify something, but not anything that will conflict
932
-     * @return mixed|string
933
-     */
934
-    protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
935
-    {
936
-        return isset($this->_class_abbreviations[ $class_name ])
937
-            ? $this->_class_abbreviations[ $class_name ]
938
-            : $default;
939
-    }
940
-
941
-
942
-    /**
943
-     * attempts to find a cached version of the requested class
944
-     * by looking in the following places:
945
-     *        $this->{$class_abbreviation}            ie:    $this->CART
946
-     *        $this->{$class_name}                        ie:    $this->Some_Class
947
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
948
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
949
-     *
950
-     * @param string $class_name
951
-     * @param string $class_prefix
952
-     * @param array  $arguments
953
-     * @return mixed
954
-     */
955
-    protected function _get_cached_class(
956
-        $class_name,
957
-        $class_prefix = '',
958
-        $arguments = array()
959
-    ) {
960
-        if ($class_name === 'EE_Registry') {
961
-            return $this;
962
-        }
963
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
964
-        // check if class has already been loaded, and return it if it has been
965
-        if (isset($this->{$class_abbreviation})) {
966
-            return $this->{$class_abbreviation};
967
-        }
968
-        $class_name = str_replace('\\', '_', $class_name);
969
-        if (isset($this->{$class_name})) {
970
-            return $this->{$class_name};
971
-        }
972
-        if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
973
-            return $this->addons->get($class_name);
974
-        }
975
-        $object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
976
-        if ($this->LIB->has($object_identifier)) {
977
-            return $this->LIB->get($object_identifier);
978
-        }
979
-        foreach ($this->LIB as $key => $object) {
980
-            if (
26
+	/**
27
+	 * @var EE_Registry $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var EE_Dependency_Map $_dependency_map
33
+	 */
34
+	protected $_dependency_map;
35
+
36
+	/**
37
+	 * @var Mirror
38
+	 */
39
+	private $mirror;
40
+
41
+	/**
42
+	 * @var ClassInterfaceCache $class_cache
43
+	 */
44
+	private $class_cache;
45
+
46
+	/**
47
+	 * @var array $_class_abbreviations
48
+	 */
49
+	protected $_class_abbreviations = array();
50
+
51
+	/**
52
+	 * @var CommandBusInterface $BUS
53
+	 */
54
+	public $BUS;
55
+
56
+	/**
57
+	 * @var EE_Cart $CART
58
+	 */
59
+	public $CART;
60
+
61
+	/**
62
+	 * @var EE_Config $CFG
63
+	 */
64
+	public $CFG;
65
+
66
+	/**
67
+	 * @var EE_Network_Config $NET_CFG
68
+	 */
69
+	public $NET_CFG;
70
+
71
+	/**
72
+	 * RegistryContainer for storing library classes in
73
+	 *
74
+	 * @var RegistryContainer $LIB
75
+	 */
76
+	public $LIB;
77
+
78
+	/**
79
+	 * @var EE_Request_Handler $REQ
80
+	 * @deprecated 4.10.14.p
81
+	 */
82
+	public $REQ;
83
+
84
+	/**
85
+	 * @var EE_Session $SSN
86
+	 */
87
+	public $SSN;
88
+
89
+	/**
90
+	 * @since 4.5.0
91
+	 * @var EE_Capabilities $CAP
92
+	 */
93
+	public $CAP;
94
+
95
+	/**
96
+	 * @since 4.9.0
97
+	 * @var EE_Message_Resource_Manager $MRM
98
+	 */
99
+	public $MRM;
100
+
101
+	/**
102
+	 * @var Registry $AssetsRegistry
103
+	 */
104
+	public $AssetsRegistry;
105
+
106
+	/**
107
+	 * RegistryContainer for holding addons which have registered themselves to work with EE core
108
+	 *
109
+	 * @var EE_Addon[] $addons
110
+	 */
111
+	public $addons;
112
+
113
+	/**
114
+	 * keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
115
+	 *
116
+	 * @var EEM_Base[] $models
117
+	 */
118
+	public $models = array();
119
+
120
+	/**
121
+	 * @var EED_Module[] $modules
122
+	 */
123
+	public $modules;
124
+
125
+	/**
126
+	 * @var EES_Shortcode[] $shortcodes
127
+	 */
128
+	public $shortcodes;
129
+
130
+	/**
131
+	 * @var WP_Widget[] $widgets
132
+	 */
133
+	public $widgets;
134
+
135
+	/**
136
+	 * this is an array of all implemented model names (i.e. not the parent abstract models, or models
137
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
138
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
139
+	 * classnames (eg "EEM_Event")
140
+	 *
141
+	 * @var array $non_abstract_db_models
142
+	 */
143
+	public $non_abstract_db_models = array();
144
+
145
+	/**
146
+	 * internationalization for JS strings
147
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = esc_html__( 'string to translate.', 'event_espresso' );
148
+	 *    in js file:  var translatedString = eei18n.string_key;
149
+	 *
150
+	 * @var array $i18n_js_strings
151
+	 */
152
+	public static $i18n_js_strings = array();
153
+
154
+	/**
155
+	 * $main_file - path to espresso.php
156
+	 *
157
+	 * @var array $main_file
158
+	 */
159
+	public $main_file;
160
+
161
+	/**
162
+	 * array of ReflectionClass objects where the key is the class name
163
+	 *
164
+	 * @deprecated 4.9.62.p
165
+	 * @var ReflectionClass[] $_reflectors
166
+	 */
167
+	public $_reflectors;
168
+
169
+	/**
170
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
171
+	 *
172
+	 * @var boolean $_cache_on
173
+	 */
174
+	protected $_cache_on = true;
175
+
176
+	/**
177
+	 * @var ObjectIdentifier
178
+	 */
179
+	private $object_identifier;
180
+
181
+
182
+	/**
183
+	 * @singleton method used to instantiate class object
184
+	 * @param EE_Dependency_Map|null   $dependency_map
185
+	 * @param Mirror|null              $mirror
186
+	 * @param ClassInterfaceCache|null $class_cache
187
+	 * @param ObjectIdentifier|null    $object_identifier
188
+	 * @return EE_Registry instance
189
+	 */
190
+	public static function instance(
191
+		EE_Dependency_Map $dependency_map = null,
192
+		Mirror $mirror = null,
193
+		ClassInterfaceCache $class_cache = null,
194
+		ObjectIdentifier $object_identifier = null
195
+	) {
196
+		// check if class object is instantiated
197
+		if (
198
+			! self::$_instance instanceof EE_Registry
199
+			&& $dependency_map instanceof EE_Dependency_Map
200
+			&& $mirror instanceof Mirror
201
+			&& $class_cache instanceof ClassInterfaceCache
202
+			&& $object_identifier instanceof ObjectIdentifier
203
+		) {
204
+			self::$_instance = new self(
205
+				$dependency_map,
206
+				$mirror,
207
+				$class_cache,
208
+				$object_identifier
209
+			);
210
+		}
211
+		return self::$_instance;
212
+	}
213
+
214
+
215
+	/**
216
+	 * protected constructor to prevent direct creation
217
+	 *
218
+	 * @Constructor
219
+	 * @param  EE_Dependency_Map  $dependency_map
220
+	 * @param Mirror              $mirror
221
+	 * @param ClassInterfaceCache $class_cache
222
+	 * @param ObjectIdentifier    $object_identifier
223
+	 */
224
+	protected function __construct(
225
+		EE_Dependency_Map $dependency_map,
226
+		Mirror $mirror,
227
+		ClassInterfaceCache $class_cache,
228
+		ObjectIdentifier $object_identifier
229
+	) {
230
+		$this->_dependency_map = $dependency_map;
231
+		$this->mirror = $mirror;
232
+		$this->class_cache = $class_cache;
233
+		$this->object_identifier = $object_identifier;
234
+		// $registry_container = new RegistryContainer();
235
+		$this->LIB = new RegistryContainer();
236
+		$this->addons = new RegistryContainer();
237
+		$this->modules = new RegistryContainer();
238
+		$this->shortcodes = new RegistryContainer();
239
+		$this->widgets = new RegistryContainer();
240
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
241
+	}
242
+
243
+
244
+	/**
245
+	 * initialize
246
+	 *
247
+	 * @throws OutOfBoundsException
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidInterfaceException
250
+	 * @throws InvalidDataTypeException
251
+	 * @throws EE_Error
252
+	 * @throws ReflectionException
253
+	 */
254
+	public function initialize()
255
+	{
256
+		$this->_class_abbreviations = apply_filters(
257
+			'FHEE__EE_Registry____construct___class_abbreviations',
258
+			array(
259
+				'EE_Config'                                       => 'CFG',
260
+				'EE_Session'                                      => 'SSN',
261
+				'EE_Capabilities'                                 => 'CAP',
262
+				'EE_Cart'                                         => 'CART',
263
+				'EE_Network_Config'                               => 'NET_CFG',
264
+				'EE_Request_Handler'                              => 'REQ',
265
+				'EE_Message_Resource_Manager'                     => 'MRM',
266
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
267
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
268
+			)
269
+		);
270
+		$this->load_core('Base', array(), true);
271
+		// add our request and response objects to the cache
272
+		$request_loader = $this->_dependency_map->class_loader(
273
+			'EventEspresso\core\services\request\Request'
274
+		);
275
+		$this->_set_cached_class(
276
+			$request_loader(),
277
+			'EventEspresso\core\services\request\Request'
278
+		);
279
+		$response_loader = $this->_dependency_map->class_loader(
280
+			'EventEspresso\core\services\request\Response'
281
+		);
282
+		$this->_set_cached_class(
283
+			$response_loader(),
284
+			'EventEspresso\core\services\request\Response'
285
+		);
286
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
287
+	}
288
+
289
+
290
+	/**
291
+	 * @return void
292
+	 */
293
+	public function init()
294
+	{
295
+		// Get current page protocol
296
+		$protocol = is_ssl() ? 'https://' : 'http://';
297
+		// Output admin-ajax.php URL with same protocol as current page
298
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
299
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') && WP_DEBUG;
300
+	}
301
+
302
+
303
+	/**
304
+	 * @return array
305
+	 */
306
+	public static function sanitize_i18n_js_strings()
307
+	{
308
+		$i18n_js_strings = (array) self::$i18n_js_strings;
309
+		foreach ($i18n_js_strings as $key => $value) {
310
+			if (is_scalar($value)) {
311
+				$decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
+				$i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
313
+			}
314
+		}
315
+		return $i18n_js_strings;
316
+	}
317
+
318
+
319
+	/**
320
+	 * localize_i18n_js_strings
321
+	 *
322
+	 * @return string
323
+	 */
324
+	public static function localize_i18n_js_strings()
325
+	{
326
+		$i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
327
+		return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
328
+	}
329
+
330
+
331
+	/**
332
+	 * @param mixed string | EED_Module $module
333
+	 * @throws OutOfBoundsException
334
+	 * @throws InvalidArgumentException
335
+	 * @throws InvalidInterfaceException
336
+	 * @throws InvalidDataTypeException
337
+	 * @throws EE_Error
338
+	 * @throws ReflectionException
339
+	 */
340
+	public function add_module($module)
341
+	{
342
+		if ($module instanceof EED_Module) {
343
+			$module_class = get_class($module);
344
+			$this->modules->add($module_class, $module);
345
+		} else {
346
+			if (! class_exists('EE_Module_Request_Router', false)) {
347
+				$this->load_core('Module_Request_Router');
348
+			}
349
+			EE_Module_Request_Router::module_factory($module);
350
+		}
351
+	}
352
+
353
+
354
+	/**
355
+	 * @param string $module_name
356
+	 * @return mixed EED_Module | NULL
357
+	 */
358
+	public function get_module($module_name = '')
359
+	{
360
+		return $this->modules->get($module_name);
361
+	}
362
+
363
+
364
+	/**
365
+	 * loads core classes - must be singletons
366
+	 *
367
+	 * @param string $class_name - simple class name ie: session
368
+	 * @param mixed  $arguments
369
+	 * @param bool   $load_only
370
+	 * @return mixed
371
+	 * @throws InvalidInterfaceException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 * @throws InvalidArgumentException
376
+	 */
377
+	public function load_core($class_name, $arguments = array(), $load_only = false)
378
+	{
379
+		$core_paths = apply_filters(
380
+			'FHEE__EE_Registry__load_core__core_paths',
381
+			array(
382
+				EE_CORE,
383
+				EE_ADMIN,
384
+				EE_CPTS,
385
+				EE_CORE . 'CPTs/',
386
+				EE_CORE . 'data_migration_scripts/',
387
+				EE_CORE . 'request_stack/',
388
+				EE_CORE . 'middleware/',
389
+			)
390
+		);
391
+		// retrieve instantiated class
392
+		return $this->_load(
393
+			$core_paths,
394
+			'EE_',
395
+			$class_name,
396
+			'core',
397
+			$arguments,
398
+			false,
399
+			true,
400
+			$load_only
401
+		);
402
+	}
403
+
404
+
405
+	/**
406
+	 * loads service classes
407
+	 *
408
+	 * @param string $class_name - simple class name ie: session
409
+	 * @param mixed  $arguments
410
+	 * @param bool   $load_only
411
+	 * @return mixed
412
+	 * @throws InvalidInterfaceException
413
+	 * @throws InvalidDataTypeException
414
+	 * @throws EE_Error
415
+	 * @throws ReflectionException
416
+	 * @throws InvalidArgumentException
417
+	 */
418
+	public function load_service($class_name, $arguments = array(), $load_only = false)
419
+	{
420
+		$service_paths = apply_filters(
421
+			'FHEE__EE_Registry__load_service__service_paths',
422
+			array(
423
+				EE_CORE . 'services/',
424
+			)
425
+		);
426
+		// retrieve instantiated class
427
+		return $this->_load(
428
+			$service_paths,
429
+			'EE_',
430
+			$class_name,
431
+			'class',
432
+			$arguments,
433
+			false,
434
+			true,
435
+			$load_only
436
+		);
437
+	}
438
+
439
+
440
+	/**
441
+	 * loads data_migration_scripts
442
+	 *
443
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
444
+	 * @param mixed  $arguments
445
+	 * @return EE_Data_Migration_Script_Base|mixed
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws EE_Error
449
+	 * @throws ReflectionException
450
+	 * @throws InvalidArgumentException
451
+	 */
452
+	public function load_dms($class_name, $arguments = array())
453
+	{
454
+		// retrieve instantiated class
455
+		return $this->_load(
456
+			EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(),
457
+			'EE_DMS_',
458
+			$class_name,
459
+			'dms',
460
+			$arguments,
461
+			false,
462
+			false
463
+		);
464
+	}
465
+
466
+
467
+	/**
468
+	 * loads object creating classes - must be singletons
469
+	 *
470
+	 * @param string $class_name - simple class name ie: attendee
471
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
472
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to
473
+	 *                           instantiate
474
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then
475
+	 *                           set this to FALSE (ie. when instantiating model objects from client in a loop)
476
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate
477
+	 *                           (default)
478
+	 * @return EE_Base_Class | bool
479
+	 * @throws InvalidInterfaceException
480
+	 * @throws InvalidDataTypeException
481
+	 * @throws EE_Error
482
+	 * @throws ReflectionException
483
+	 * @throws InvalidArgumentException
484
+	 */
485
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
486
+	{
487
+		$paths = apply_filters(
488
+			'FHEE__EE_Registry__load_class__paths',
489
+			array(
490
+				EE_CORE,
491
+				EE_CLASSES,
492
+				EE_BUSINESS,
493
+			)
494
+		);
495
+		// retrieve instantiated class
496
+		return $this->_load(
497
+			$paths,
498
+			'EE_',
499
+			$class_name,
500
+			'class',
501
+			$arguments,
502
+			$from_db,
503
+			$cache,
504
+			$load_only
505
+		);
506
+	}
507
+
508
+
509
+	/**
510
+	 * loads helper classes - must be singletons
511
+	 *
512
+	 * @param string $class_name - simple class name ie: price
513
+	 * @param mixed  $arguments
514
+	 * @param bool   $load_only
515
+	 * @return EEH_Base | bool
516
+	 * @throws InvalidInterfaceException
517
+	 * @throws InvalidDataTypeException
518
+	 * @throws EE_Error
519
+	 * @throws ReflectionException
520
+	 * @throws InvalidArgumentException
521
+	 */
522
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
523
+	{
524
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
525
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
526
+		// retrieve instantiated class
527
+		return $this->_load(
528
+			$helper_paths,
529
+			'EEH_',
530
+			$class_name,
531
+			'helper',
532
+			$arguments,
533
+			false,
534
+			true,
535
+			$load_only
536
+		);
537
+	}
538
+
539
+
540
+	/**
541
+	 * loads core classes - must be singletons
542
+	 *
543
+	 * @param string $class_name - simple class name ie: session
544
+	 * @param mixed  $arguments
545
+	 * @param bool   $load_only
546
+	 * @param bool   $cache      whether to cache the object or not.
547
+	 * @return mixed
548
+	 * @throws InvalidInterfaceException
549
+	 * @throws InvalidDataTypeException
550
+	 * @throws EE_Error
551
+	 * @throws ReflectionException
552
+	 * @throws InvalidArgumentException
553
+	 */
554
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
555
+	{
556
+		$paths = array(
557
+			EE_LIBRARIES,
558
+			EE_LIBRARIES . 'messages/',
559
+			EE_LIBRARIES . 'shortcodes/',
560
+			EE_LIBRARIES . 'qtips/',
561
+			EE_LIBRARIES . 'payment_methods/',
562
+		);
563
+		// retrieve instantiated class
564
+		return $this->_load(
565
+			$paths,
566
+			'EE_',
567
+			$class_name,
568
+			'lib',
569
+			$arguments,
570
+			false,
571
+			$cache,
572
+			$load_only
573
+		);
574
+	}
575
+
576
+
577
+	/**
578
+	 * loads model classes - must be singletons
579
+	 *
580
+	 * @param string $class_name - simple class name ie: price
581
+	 * @param mixed  $arguments
582
+	 * @param bool   $load_only
583
+	 * @return EEM_Base | bool
584
+	 * @throws InvalidInterfaceException
585
+	 * @throws InvalidDataTypeException
586
+	 * @throws EE_Error
587
+	 * @throws ReflectionException
588
+	 * @throws InvalidArgumentException
589
+	 */
590
+	public function load_model($class_name, $arguments = array(), $load_only = false)
591
+	{
592
+		$paths = apply_filters(
593
+			'FHEE__EE_Registry__load_model__paths',
594
+			array(
595
+				EE_MODELS,
596
+				EE_CORE,
597
+			)
598
+		);
599
+		// retrieve instantiated class
600
+		return $this->_load(
601
+			$paths,
602
+			'EEM_',
603
+			$class_name,
604
+			'model',
605
+			$arguments,
606
+			false,
607
+			true,
608
+			$load_only
609
+		);
610
+	}
611
+
612
+
613
+	/**
614
+	 * loads model classes - must be singletons
615
+	 *
616
+	 * @param string $class_name - simple class name ie: price
617
+	 * @param mixed  $arguments
618
+	 * @param bool   $load_only
619
+	 * @return mixed | bool
620
+	 * @throws InvalidInterfaceException
621
+	 * @throws InvalidDataTypeException
622
+	 * @throws EE_Error
623
+	 * @throws ReflectionException
624
+	 * @throws InvalidArgumentException
625
+	 */
626
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
627
+	{
628
+		$paths = array(
629
+			EE_MODELS . 'fields/',
630
+			EE_MODELS . 'helpers/',
631
+			EE_MODELS . 'relations/',
632
+			EE_MODELS . 'strategies/',
633
+		);
634
+		// retrieve instantiated class
635
+		return $this->_load(
636
+			$paths,
637
+			'EE_',
638
+			$class_name,
639
+			'',
640
+			$arguments,
641
+			false,
642
+			true,
643
+			$load_only
644
+		);
645
+	}
646
+
647
+
648
+	/**
649
+	 * Determines if $model_name is the name of an actual EE model.
650
+	 *
651
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
652
+	 * @return boolean
653
+	 */
654
+	public function is_model_name($model_name)
655
+	{
656
+		return isset($this->models[ $model_name ]);
657
+	}
658
+
659
+
660
+	/**
661
+	 * generic class loader
662
+	 *
663
+	 * @param string $path_to_file - directory path to file location, not including filename
664
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
665
+	 * @param string $type         - file type - core? class? helper? model?
666
+	 * @param mixed  $arguments
667
+	 * @param bool   $load_only
668
+	 * @return mixed
669
+	 * @throws InvalidInterfaceException
670
+	 * @throws InvalidDataTypeException
671
+	 * @throws EE_Error
672
+	 * @throws ReflectionException
673
+	 * @throws InvalidArgumentException
674
+	 */
675
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
676
+	{
677
+		// retrieve instantiated class
678
+		return $this->_load(
679
+			$path_to_file,
680
+			'',
681
+			$file_name,
682
+			$type,
683
+			$arguments,
684
+			false,
685
+			true,
686
+			$load_only
687
+		);
688
+	}
689
+
690
+
691
+	/**
692
+	 * @param string $path_to_file - directory path to file location, not including filename
693
+	 * @param string $class_name   - full class name  ie:  My_Class
694
+	 * @param string $type         - file type - core? class? helper? model?
695
+	 * @param mixed  $arguments
696
+	 * @param bool   $load_only
697
+	 * @return bool|EE_Addon|object
698
+	 * @throws InvalidInterfaceException
699
+	 * @throws InvalidDataTypeException
700
+	 * @throws EE_Error
701
+	 * @throws ReflectionException
702
+	 * @throws InvalidArgumentException
703
+	 */
704
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
705
+	{
706
+		// retrieve instantiated class
707
+		return $this->_load(
708
+			$path_to_file,
709
+			'addon',
710
+			$class_name,
711
+			$type,
712
+			$arguments,
713
+			false,
714
+			true,
715
+			$load_only
716
+		);
717
+	}
718
+
719
+
720
+	/**
721
+	 * instantiates, caches, and automatically resolves dependencies
722
+	 * for classes that use a Fully Qualified Class Name.
723
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
724
+	 * then you need to use one of the existing load_*() methods
725
+	 * which can resolve the classname and filepath from the passed arguments
726
+	 *
727
+	 * @param bool|string $class_name   Fully Qualified Class Name
728
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
729
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
730
+	 * @param bool        $from_db      some classes are instantiated from the db
731
+	 *                                  and thus call a different method to instantiate
732
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
733
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
734
+	 * @return bool|null|mixed          null = failure to load or instantiate class object.
735
+	 *                                  object = class loaded and instantiated successfully.
736
+	 *                                  bool = fail or success when $load_only is true
737
+	 * @throws InvalidInterfaceException
738
+	 * @throws InvalidDataTypeException
739
+	 * @throws EE_Error
740
+	 * @throws ReflectionException
741
+	 * @throws InvalidArgumentException
742
+	 */
743
+	public function create(
744
+		$class_name = false,
745
+		$arguments = array(),
746
+		$cache = false,
747
+		$from_db = false,
748
+		$load_only = false,
749
+		$addon = false
750
+	) {
751
+		$class_name = ltrim($class_name, '\\');
752
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
753
+		$class_exists = $this->loadOrVerifyClassExists($class_name, $arguments);
754
+		// if a non-FQCN was passed, then
755
+		// verifyClassExists() might return an object
756
+		// or it could return null if the class just could not be found anywhere
757
+		if ($class_exists instanceof $class_name || $class_exists === null) {
758
+			// either way, return the results
759
+			return $class_exists;
760
+		}
761
+		$class_name = $class_exists;
762
+		// if we're only loading the class and it already exists, then let's just return true immediately
763
+		if ($load_only) {
764
+			return true;
765
+		}
766
+		$addon = $addon ? 'addon' : '';
767
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
768
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
769
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
770
+		if ($this->_cache_on && $cache && ! $load_only) {
771
+			// return object if it's already cached
772
+			$cached_class = $this->_get_cached_class($class_name, $addon, $arguments);
773
+			if ($cached_class !== null) {
774
+				return $cached_class;
775
+			}
776
+		}// obtain the loader method from the dependency map
777
+		$loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
778
+		if ($loader instanceof Closure) {
779
+			$class_obj = $loader($arguments);
780
+		} else {
781
+			if ($loader && method_exists($this, $loader)) {
782
+				$class_obj = $this->{$loader}($class_name, $arguments);
783
+			} else {
784
+				$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
785
+			}
786
+		}
787
+		if (($this->_cache_on && $cache) || $this->get_class_abbreviation($class_name, '')) {
788
+			// save it for later... kinda like gum  { : $
789
+			$this->_set_cached_class(
790
+				$class_obj,
791
+				$class_name,
792
+				$addon,
793
+				$from_db,
794
+				$arguments
795
+			);
796
+		}
797
+		$this->_cache_on = true;
798
+		return $class_obj;
799
+	}
800
+
801
+
802
+	/**
803
+	 * Recursively checks that a class exists and potentially attempts to load classes with non-FQCNs
804
+	 *
805
+	 * @param string|object $class_name
806
+	 * @param array         $arguments
807
+	 * @param int           $attempt
808
+	 * @return mixed
809
+	 */
810
+	private function loadOrVerifyClassExists($class_name, array $arguments, $attempt = 1)
811
+	{
812
+		if (is_object($class_name) || class_exists($class_name)) {
813
+			return $class_name;
814
+		}
815
+		switch ($attempt) {
816
+			case 1:
817
+				// if it's a FQCN then maybe the class is registered with a preceding \
818
+				$class_name = strpos($class_name, '\\') !== false
819
+					? '\\' . ltrim($class_name, '\\')
820
+					: $class_name;
821
+				break;
822
+			case 2:
823
+				//
824
+				$loader = $this->_dependency_map->class_loader($class_name);
825
+				if ($loader && method_exists($this, $loader)) {
826
+					return $this->{$loader}($class_name, $arguments);
827
+				}
828
+				break;
829
+			case 3:
830
+			default:
831
+				return null;
832
+		}
833
+		$attempt++;
834
+		return $this->loadOrVerifyClassExists($class_name, $arguments, $attempt);
835
+	}
836
+
837
+
838
+	/**
839
+	 * instantiates, caches, and injects dependencies for classes
840
+	 *
841
+	 * @param array       $file_paths   an array of paths to folders to look in
842
+	 * @param string      $class_prefix EE  or EEM or... ???
843
+	 * @param bool|string $class_name   $class name
844
+	 * @param string      $type         file type - core? class? helper? model?
845
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
846
+	 * @param bool        $from_db      some classes are instantiated from the db
847
+	 *                                  and thus call a different method to instantiate
848
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
849
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
850
+	 * @return bool|null|object null = failure to load or instantiate class object.
851
+	 *                                  object = class loaded and instantiated successfully.
852
+	 *                                  bool = fail or success when $load_only is true
853
+	 * @throws EE_Error
854
+	 * @throws ReflectionException
855
+	 * @throws InvalidInterfaceException
856
+	 * @throws InvalidDataTypeException
857
+	 * @throws InvalidArgumentException
858
+	 */
859
+	protected function _load(
860
+		$file_paths = array(),
861
+		$class_prefix = 'EE_',
862
+		$class_name = false,
863
+		$type = 'class',
864
+		$arguments = array(),
865
+		$from_db = false,
866
+		$cache = true,
867
+		$load_only = false
868
+	) {
869
+		$class_name = ltrim($class_name, '\\');
870
+		// strip php file extension
871
+		$class_name = str_replace('.php', '', trim($class_name));
872
+		// does the class have a prefix ?
873
+		if (! empty($class_prefix) && $class_prefix !== 'addon') {
874
+			// make sure $class_prefix is uppercase
875
+			$class_prefix = strtoupper(trim($class_prefix));
876
+			// add class prefix ONCE!!!
877
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
878
+		}
879
+		$class_name = $this->class_cache->getFqnForAlias($class_name);
880
+		$class_exists = class_exists($class_name, false);
881
+		// if we're only loading the class and it already exists, then let's just return true immediately
882
+		if ($load_only && $class_exists) {
883
+			return true;
884
+		}
885
+		$arguments = is_array($arguments) ? $arguments : array($arguments);
886
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
887
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
888
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
889
+		if ($this->_cache_on && $cache && ! $load_only) {
890
+			// return object if it's already cached
891
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix, $arguments);
892
+			if ($cached_class !== null) {
893
+				return $cached_class;
894
+			}
895
+		}
896
+		// if the class doesn't already exist.. then we need to try and find the file and load it
897
+		if (! $class_exists) {
898
+			// get full path to file
899
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
900
+			// load the file
901
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
902
+			// if we are only loading a file but NOT instantiating an object
903
+			// then return boolean for whether class was loaded or not
904
+			if ($load_only) {
905
+				return $loaded;
906
+			}
907
+			// if an object was expected but loading failed, then return nothing
908
+			if (! $loaded) {
909
+				return null;
910
+			}
911
+		}
912
+		// instantiate the requested object
913
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
914
+		if ($this->_cache_on && $cache) {
915
+			// save it for later... kinda like gum  { : $
916
+			$this->_set_cached_class(
917
+				$class_obj,
918
+				$class_name,
919
+				$class_prefix,
920
+				$from_db,
921
+				$arguments
922
+			);
923
+		}
924
+		$this->_cache_on = true;
925
+		return $class_obj;
926
+	}
927
+
928
+
929
+	/**
930
+	 * @param string $class_name
931
+	 * @param string $default have to specify something, but not anything that will conflict
932
+	 * @return mixed|string
933
+	 */
934
+	protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
935
+	{
936
+		return isset($this->_class_abbreviations[ $class_name ])
937
+			? $this->_class_abbreviations[ $class_name ]
938
+			: $default;
939
+	}
940
+
941
+
942
+	/**
943
+	 * attempts to find a cached version of the requested class
944
+	 * by looking in the following places:
945
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
946
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
947
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
948
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
949
+	 *
950
+	 * @param string $class_name
951
+	 * @param string $class_prefix
952
+	 * @param array  $arguments
953
+	 * @return mixed
954
+	 */
955
+	protected function _get_cached_class(
956
+		$class_name,
957
+		$class_prefix = '',
958
+		$arguments = array()
959
+	) {
960
+		if ($class_name === 'EE_Registry') {
961
+			return $this;
962
+		}
963
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
964
+		// check if class has already been loaded, and return it if it has been
965
+		if (isset($this->{$class_abbreviation})) {
966
+			return $this->{$class_abbreviation};
967
+		}
968
+		$class_name = str_replace('\\', '_', $class_name);
969
+		if (isset($this->{$class_name})) {
970
+			return $this->{$class_name};
971
+		}
972
+		if ($class_prefix === 'addon' && $this->addons->has($class_name)) {
973
+			return $this->addons->get($class_name);
974
+		}
975
+		$object_identifier = $this->object_identifier->getIdentifier($class_name, $arguments);
976
+		if ($this->LIB->has($object_identifier)) {
977
+			return $this->LIB->get($object_identifier);
978
+		}
979
+		foreach ($this->LIB as $key => $object) {
980
+			if (
981 981
 // request does not contain new arguments and therefore no args identifier
982
-                ! $this->object_identifier->hasArguments($object_identifier)
983
-                // but previously cached class with args was found
984
-                && $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
985
-            ) {
986
-                return $object;
987
-            }
988
-        }
989
-        return null;
990
-    }
991
-
992
-
993
-    /**
994
-     * removes a cached version of the requested class
995
-     *
996
-     * @param string  $class_name
997
-     * @param boolean $addon
998
-     * @param array   $arguments
999
-     * @return boolean
1000
-     */
1001
-    public function clear_cached_class(
1002
-        $class_name,
1003
-        $addon = false,
1004
-        $arguments = array()
1005
-    ) {
1006
-        $class_abbreviation = $this->get_class_abbreviation($class_name);
1007
-        // check if class has already been loaded, and return it if it has been
1008
-        if (isset($this->{$class_abbreviation})) {
1009
-            $this->{$class_abbreviation} = null;
1010
-            return true;
1011
-        }
1012
-        $class_name = str_replace('\\', '_', $class_name);
1013
-        if (isset($this->{$class_name})) {
1014
-            $this->{$class_name} = null;
1015
-            return true;
1016
-        }
1017
-        if ($addon && $this->addons->has($class_name)) {
1018
-            $this->addons->remove($class_name);
1019
-            return true;
1020
-        }
1021
-        $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1022
-        if ($this->LIB->has($class_name)) {
1023
-            $this->LIB->remove($class_name);
1024
-            return true;
1025
-        }
1026
-        return false;
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * _set_cached_class
1032
-     * attempts to cache the instantiated class locally
1033
-     * in one of the following places, in the following order:
1034
-     *        $this->{class_abbreviation}   ie:    $this->CART
1035
-     *        $this->{$class_name}          ie:    $this->Some_Class
1036
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1037
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1038
-     *
1039
-     * @param object $class_obj
1040
-     * @param string $class_name
1041
-     * @param string $class_prefix
1042
-     * @param bool   $from_db
1043
-     * @param array  $arguments
1044
-     * @return void
1045
-     */
1046
-    protected function _set_cached_class(
1047
-        $class_obj,
1048
-        $class_name,
1049
-        $class_prefix = '',
1050
-        $from_db = false,
1051
-        $arguments = array()
1052
-    ) {
1053
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1054
-            return;
1055
-        }
1056
-        // return newly instantiated class
1057
-        $class_abbreviation = $this->get_class_abbreviation($class_name, '');
1058
-        if ($class_abbreviation) {
1059
-            $this->{$class_abbreviation} = $class_obj;
1060
-            return;
1061
-        }
1062
-        $class_name = str_replace('\\', '_', $class_name);
1063
-        if (property_exists($this, $class_name)) {
1064
-            $this->{$class_name} = $class_obj;
1065
-            return;
1066
-        }
1067
-        if ($class_prefix === 'addon') {
1068
-            $this->addons->add($class_name, $class_obj);
1069
-            return;
1070
-        }
1071
-        if (! $from_db) {
1072
-            $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1073
-            $this->LIB->add($class_name, $class_obj);
1074
-        }
1075
-    }
1076
-
1077
-
1078
-    /**
1079
-     * attempts to find a full valid filepath for the requested class.
1080
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1081
-     * then returns that path if the target file has been found and is readable
1082
-     *
1083
-     * @param string $class_name
1084
-     * @param string $type
1085
-     * @param array  $file_paths
1086
-     * @return string | bool
1087
-     */
1088
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
1089
-    {
1090
-        // make sure $file_paths is an array
1091
-        $file_paths = is_array($file_paths)
1092
-            ? $file_paths
1093
-            : array($file_paths);
1094
-        // cycle thru paths
1095
-        foreach ($file_paths as $key => $file_path) {
1096
-            // convert all separators to proper /, if no filepath, then use EE_CLASSES
1097
-            $file_path = $file_path
1098
-                ? str_replace(array('/', '\\'), '/', $file_path)
1099
-                : EE_CLASSES;
1100
-            // prep file type
1101
-            $type = ! empty($type)
1102
-                ? trim($type, '.') . '.'
1103
-                : '';
1104
-            // build full file path
1105
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1106
-            // does the file exist and can be read ?
1107
-            if (is_readable($file_paths[ $key ])) {
1108
-                return $file_paths[ $key ];
1109
-            }
1110
-        }
1111
-        return false;
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * basically just performs a require_once()
1117
-     * but with some error handling
1118
-     *
1119
-     * @param  string $path
1120
-     * @param  string $class_name
1121
-     * @param  string $type
1122
-     * @param  array  $file_paths
1123
-     * @return bool
1124
-     * @throws EE_Error
1125
-     * @throws ReflectionException
1126
-     */
1127
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1128
-    {
1129
-        $this->resolve_legacy_class_parent($class_name);
1130
-        // don't give up! you gotta...
1131
-        try {
1132
-            // does the file exist and can it be read ?
1133
-            if (! $path) {
1134
-                // just in case the file has already been autoloaded,
1135
-                // but discrepancies in the naming schema are preventing it from
1136
-                // being loaded via one of the EE_Registry::load_*() methods,
1137
-                // then let's try one last hail mary before throwing an exception
1138
-                // and call class_exists() again, but with autoloading turned ON
1139
-                if (class_exists($class_name)) {
1140
-                    return true;
1141
-                }
1142
-                // so sorry, can't find the file
1143
-                throw new EE_Error(
1144
-                    sprintf(
1145
-                        esc_html__(
1146
-                            'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1147
-                            'event_espresso'
1148
-                        ),
1149
-                        trim($type, '.'),
1150
-                        $class_name,
1151
-                        '<br />' . implode(',<br />', $file_paths)
1152
-                    )
1153
-                );
1154
-            }
1155
-            // get the file
1156
-            require_once($path);
1157
-            // if the class isn't already declared somewhere
1158
-            if (class_exists($class_name, false) === false) {
1159
-                // so sorry, not a class
1160
-                throw new EE_Error(
1161
-                    sprintf(
1162
-                        esc_html__(
1163
-                            'The %s file %s does not appear to contain the %s Class.',
1164
-                            'event_espresso'
1165
-                        ),
1166
-                        $type,
1167
-                        $path,
1168
-                        $class_name
1169
-                    )
1170
-                );
1171
-            }
1172
-        } catch (EE_Error $e) {
1173
-            $e->get_error();
1174
-            return false;
1175
-        }
1176
-        return true;
1177
-    }
1178
-
1179
-
1180
-    /**
1181
-     * Some of our legacy classes that extended a parent class would simply use a require() statement
1182
-     * before their class declaration in order to ensure that the parent class was loaded.
1183
-     * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1184
-     * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1185
-     *
1186
-     * @param string $class_name
1187
-     */
1188
-    protected function resolve_legacy_class_parent($class_name = '')
1189
-    {
1190
-        try {
1191
-            $legacy_parent_class_map = array(
1192
-                'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1193
-            );
1194
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1195
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1196
-            }
1197
-        } catch (Exception $exception) {
1198
-        }
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * _create_object
1204
-     * Attempts to instantiate the requested class via any of the
1205
-     * commonly used instantiation methods employed throughout EE.
1206
-     * The priority for instantiation is as follows:
1207
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1208
-     *        - model objects via their 'new_instance_from_db' method
1209
-     *        - model objects via their 'new_instance' method
1210
-     *        - "singleton" classes" via their 'instance' method
1211
-     *    - standard instantiable classes via their __constructor
1212
-     * Prior to instantiation, if the classname exists in the dependency_map,
1213
-     * then the constructor for the requested class will be examined to determine
1214
-     * if any dependencies exist, and if they can be injected.
1215
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1216
-     *
1217
-     * @param string $class_name
1218
-     * @param array  $arguments
1219
-     * @param string $type
1220
-     * @param bool   $from_db
1221
-     * @return null|object|bool
1222
-     * @throws InvalidArgumentException
1223
-     * @throws InvalidInterfaceException
1224
-     * @throws EE_Error
1225
-     * @throws ReflectionException
1226
-     * @throws InvalidDataTypeException
1227
-     */
1228
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1229
-    {
1230
-        // create reflection
1231
-        $reflector = $this->mirror->getReflectionClass($class_name);
1232
-        // make sure arguments are an array
1233
-        $arguments = is_array($arguments)
1234
-            ? $arguments
1235
-            : array($arguments);
1236
-        // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1237
-        // else wrap it in an additional array so that it doesn't get split into multiple parameters
1238
-        $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1239
-            ? $arguments
1240
-            : array($arguments);
1241
-        // attempt to inject dependencies ?
1242
-        if ($this->_dependency_map->has($class_name)) {
1243
-            $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1244
-        }
1245
-        // instantiate the class if possible
1246
-        if ($reflector->isAbstract()) {
1247
-            // nothing to instantiate, loading file was enough
1248
-            // does not throw an exception so $instantiation_mode is unused
1249
-            // $instantiation_mode = "1) no constructor abstract class";
1250
-            return true;
1251
-        }
1252
-        if (
1253
-            empty($arguments)
1254
-            && $this->mirror->getConstructorFromReflection($reflector) === null
1255
-            && $reflector->isInstantiable()
1256
-        ) {
1257
-            // no constructor = static methods only... nothing to instantiate, loading file was enough
1258
-            // $instantiation_mode = "2) no constructor but instantiable";
1259
-            return $reflector->newInstance();
1260
-        }
1261
-        if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1262
-            // $instantiation_mode = "3) new_instance_from_db()";
1263
-            return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1264
-        }
1265
-        if (method_exists($class_name, 'new_instance')) {
1266
-            // $instantiation_mode = "4) new_instance()";
1267
-            return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1268
-        }
1269
-        if (method_exists($class_name, 'instance')) {
1270
-            // $instantiation_mode = "5) instance()";
1271
-            return call_user_func_array(array($class_name, 'instance'), $arguments);
1272
-        }
1273
-        if ($reflector->isInstantiable()) {
1274
-            // $instantiation_mode = "6) constructor";
1275
-            return $reflector->newInstanceArgs($arguments);
1276
-        }
1277
-        // heh ? something's not right !
1278
-        throw new EE_Error(
1279
-            sprintf(
1280
-                esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1281
-                $type,
1282
-                $class_name
1283
-            )
1284
-        );
1285
-    }
1286
-
1287
-
1288
-    /**
1289
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1290
-     * @param array $array
1291
-     * @return bool
1292
-     */
1293
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
1294
-    {
1295
-        return ! empty($array)
1296
-            ? array_keys($array) === range(0, count($array) - 1)
1297
-            : true;
1298
-    }
1299
-
1300
-
1301
-    /**
1302
-     * _resolve_dependencies
1303
-     * examines the constructor for the requested class to determine
1304
-     * if any dependencies exist, and if they can be injected.
1305
-     * If so, then those classes will be added to the array of arguments passed to the constructor
1306
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1307
-     * For example:
1308
-     *        if attempting to load a class "Foo" with the following constructor:
1309
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1310
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1311
-     *        but only IF they are NOT already present in the incoming arguments array,
1312
-     *        and the correct classes can be loaded
1313
-     *
1314
-     * @param ReflectionClass $reflector
1315
-     * @param string          $class_name
1316
-     * @param array           $arguments
1317
-     * @return array
1318
-     * @throws InvalidArgumentException
1319
-     * @throws InvalidDataTypeException
1320
-     * @throws InvalidInterfaceException
1321
-     * @throws ReflectionException
1322
-     */
1323
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1324
-    {
1325
-        // let's examine the constructor
1326
-        $constructor = $this->mirror->getConstructorFromReflection($reflector);
1327
-        // whu? huh? nothing?
1328
-        if (! $constructor) {
1329
-            return $arguments;
1330
-        }
1331
-        // get constructor parameters
1332
-        $params = $this->mirror->getParametersFromReflection($reflector);
1333
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1334
-        $argument_keys = array_keys($arguments);
1335
-        // now loop thru all of the constructors expected parameters
1336
-        foreach ($params as $index => $param) {
1337
-            try {
1338
-                // is this a dependency for a specific class ?
1339
-                $param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1340
-            } catch (ReflectionException $exception) {
1341
-                // uh-oh... most likely a legacy class that has not been autoloaded
1342
-                // let's try to derive the classname from what we have now
1343
-                // and hope that the property var name is close to the class name
1344
-                $param_class = $param->getName();
1345
-                $param_class = str_replace('_', ' ', $param_class);
1346
-                $param_class = ucwords($param_class);
1347
-                $param_class = str_replace(' ', '_', $param_class);
1348
-            }
1349
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1350
-            $param_class = $this->class_cache->isAlias($param_class, $class_name)
1351
-                ? $this->class_cache->getFqnForAlias($param_class, $class_name)
1352
-                : $param_class;
1353
-            if (
982
+				! $this->object_identifier->hasArguments($object_identifier)
983
+				// but previously cached class with args was found
984
+				&& $this->object_identifier->fqcnMatchesObjectIdentifier($class_name, $key)
985
+			) {
986
+				return $object;
987
+			}
988
+		}
989
+		return null;
990
+	}
991
+
992
+
993
+	/**
994
+	 * removes a cached version of the requested class
995
+	 *
996
+	 * @param string  $class_name
997
+	 * @param boolean $addon
998
+	 * @param array   $arguments
999
+	 * @return boolean
1000
+	 */
1001
+	public function clear_cached_class(
1002
+		$class_name,
1003
+		$addon = false,
1004
+		$arguments = array()
1005
+	) {
1006
+		$class_abbreviation = $this->get_class_abbreviation($class_name);
1007
+		// check if class has already been loaded, and return it if it has been
1008
+		if (isset($this->{$class_abbreviation})) {
1009
+			$this->{$class_abbreviation} = null;
1010
+			return true;
1011
+		}
1012
+		$class_name = str_replace('\\', '_', $class_name);
1013
+		if (isset($this->{$class_name})) {
1014
+			$this->{$class_name} = null;
1015
+			return true;
1016
+		}
1017
+		if ($addon && $this->addons->has($class_name)) {
1018
+			$this->addons->remove($class_name);
1019
+			return true;
1020
+		}
1021
+		$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1022
+		if ($this->LIB->has($class_name)) {
1023
+			$this->LIB->remove($class_name);
1024
+			return true;
1025
+		}
1026
+		return false;
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * _set_cached_class
1032
+	 * attempts to cache the instantiated class locally
1033
+	 * in one of the following places, in the following order:
1034
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1035
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1036
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1037
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1038
+	 *
1039
+	 * @param object $class_obj
1040
+	 * @param string $class_name
1041
+	 * @param string $class_prefix
1042
+	 * @param bool   $from_db
1043
+	 * @param array  $arguments
1044
+	 * @return void
1045
+	 */
1046
+	protected function _set_cached_class(
1047
+		$class_obj,
1048
+		$class_name,
1049
+		$class_prefix = '',
1050
+		$from_db = false,
1051
+		$arguments = array()
1052
+	) {
1053
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1054
+			return;
1055
+		}
1056
+		// return newly instantiated class
1057
+		$class_abbreviation = $this->get_class_abbreviation($class_name, '');
1058
+		if ($class_abbreviation) {
1059
+			$this->{$class_abbreviation} = $class_obj;
1060
+			return;
1061
+		}
1062
+		$class_name = str_replace('\\', '_', $class_name);
1063
+		if (property_exists($this, $class_name)) {
1064
+			$this->{$class_name} = $class_obj;
1065
+			return;
1066
+		}
1067
+		if ($class_prefix === 'addon') {
1068
+			$this->addons->add($class_name, $class_obj);
1069
+			return;
1070
+		}
1071
+		if (! $from_db) {
1072
+			$class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1073
+			$this->LIB->add($class_name, $class_obj);
1074
+		}
1075
+	}
1076
+
1077
+
1078
+	/**
1079
+	 * attempts to find a full valid filepath for the requested class.
1080
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
1081
+	 * then returns that path if the target file has been found and is readable
1082
+	 *
1083
+	 * @param string $class_name
1084
+	 * @param string $type
1085
+	 * @param array  $file_paths
1086
+	 * @return string | bool
1087
+	 */
1088
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
1089
+	{
1090
+		// make sure $file_paths is an array
1091
+		$file_paths = is_array($file_paths)
1092
+			? $file_paths
1093
+			: array($file_paths);
1094
+		// cycle thru paths
1095
+		foreach ($file_paths as $key => $file_path) {
1096
+			// convert all separators to proper /, if no filepath, then use EE_CLASSES
1097
+			$file_path = $file_path
1098
+				? str_replace(array('/', '\\'), '/', $file_path)
1099
+				: EE_CLASSES;
1100
+			// prep file type
1101
+			$type = ! empty($type)
1102
+				? trim($type, '.') . '.'
1103
+				: '';
1104
+			// build full file path
1105
+			$file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1106
+			// does the file exist and can be read ?
1107
+			if (is_readable($file_paths[ $key ])) {
1108
+				return $file_paths[ $key ];
1109
+			}
1110
+		}
1111
+		return false;
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * basically just performs a require_once()
1117
+	 * but with some error handling
1118
+	 *
1119
+	 * @param  string $path
1120
+	 * @param  string $class_name
1121
+	 * @param  string $type
1122
+	 * @param  array  $file_paths
1123
+	 * @return bool
1124
+	 * @throws EE_Error
1125
+	 * @throws ReflectionException
1126
+	 */
1127
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
1128
+	{
1129
+		$this->resolve_legacy_class_parent($class_name);
1130
+		// don't give up! you gotta...
1131
+		try {
1132
+			// does the file exist and can it be read ?
1133
+			if (! $path) {
1134
+				// just in case the file has already been autoloaded,
1135
+				// but discrepancies in the naming schema are preventing it from
1136
+				// being loaded via one of the EE_Registry::load_*() methods,
1137
+				// then let's try one last hail mary before throwing an exception
1138
+				// and call class_exists() again, but with autoloading turned ON
1139
+				if (class_exists($class_name)) {
1140
+					return true;
1141
+				}
1142
+				// so sorry, can't find the file
1143
+				throw new EE_Error(
1144
+					sprintf(
1145
+						esc_html__(
1146
+							'The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s',
1147
+							'event_espresso'
1148
+						),
1149
+						trim($type, '.'),
1150
+						$class_name,
1151
+						'<br />' . implode(',<br />', $file_paths)
1152
+					)
1153
+				);
1154
+			}
1155
+			// get the file
1156
+			require_once($path);
1157
+			// if the class isn't already declared somewhere
1158
+			if (class_exists($class_name, false) === false) {
1159
+				// so sorry, not a class
1160
+				throw new EE_Error(
1161
+					sprintf(
1162
+						esc_html__(
1163
+							'The %s file %s does not appear to contain the %s Class.',
1164
+							'event_espresso'
1165
+						),
1166
+						$type,
1167
+						$path,
1168
+						$class_name
1169
+					)
1170
+				);
1171
+			}
1172
+		} catch (EE_Error $e) {
1173
+			$e->get_error();
1174
+			return false;
1175
+		}
1176
+		return true;
1177
+	}
1178
+
1179
+
1180
+	/**
1181
+	 * Some of our legacy classes that extended a parent class would simply use a require() statement
1182
+	 * before their class declaration in order to ensure that the parent class was loaded.
1183
+	 * This is not ideal, but it's nearly impossible to determine the parent class of a non-namespaced class,
1184
+	 * without triggering a fatal error because the parent class has yet to be loaded and therefore doesn't exist.
1185
+	 *
1186
+	 * @param string $class_name
1187
+	 */
1188
+	protected function resolve_legacy_class_parent($class_name = '')
1189
+	{
1190
+		try {
1191
+			$legacy_parent_class_map = array(
1192
+				'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1193
+			);
1194
+			if (isset($legacy_parent_class_map[ $class_name ])) {
1195
+				require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1196
+			}
1197
+		} catch (Exception $exception) {
1198
+		}
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * _create_object
1204
+	 * Attempts to instantiate the requested class via any of the
1205
+	 * commonly used instantiation methods employed throughout EE.
1206
+	 * The priority for instantiation is as follows:
1207
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
1208
+	 *        - model objects via their 'new_instance_from_db' method
1209
+	 *        - model objects via their 'new_instance' method
1210
+	 *        - "singleton" classes" via their 'instance' method
1211
+	 *    - standard instantiable classes via their __constructor
1212
+	 * Prior to instantiation, if the classname exists in the dependency_map,
1213
+	 * then the constructor for the requested class will be examined to determine
1214
+	 * if any dependencies exist, and if they can be injected.
1215
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1216
+	 *
1217
+	 * @param string $class_name
1218
+	 * @param array  $arguments
1219
+	 * @param string $type
1220
+	 * @param bool   $from_db
1221
+	 * @return null|object|bool
1222
+	 * @throws InvalidArgumentException
1223
+	 * @throws InvalidInterfaceException
1224
+	 * @throws EE_Error
1225
+	 * @throws ReflectionException
1226
+	 * @throws InvalidDataTypeException
1227
+	 */
1228
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
1229
+	{
1230
+		// create reflection
1231
+		$reflector = $this->mirror->getReflectionClass($class_name);
1232
+		// make sure arguments are an array
1233
+		$arguments = is_array($arguments)
1234
+			? $arguments
1235
+			: array($arguments);
1236
+		// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
1237
+		// else wrap it in an additional array so that it doesn't get split into multiple parameters
1238
+		$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
1239
+			? $arguments
1240
+			: array($arguments);
1241
+		// attempt to inject dependencies ?
1242
+		if ($this->_dependency_map->has($class_name)) {
1243
+			$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
1244
+		}
1245
+		// instantiate the class if possible
1246
+		if ($reflector->isAbstract()) {
1247
+			// nothing to instantiate, loading file was enough
1248
+			// does not throw an exception so $instantiation_mode is unused
1249
+			// $instantiation_mode = "1) no constructor abstract class";
1250
+			return true;
1251
+		}
1252
+		if (
1253
+			empty($arguments)
1254
+			&& $this->mirror->getConstructorFromReflection($reflector) === null
1255
+			&& $reflector->isInstantiable()
1256
+		) {
1257
+			// no constructor = static methods only... nothing to instantiate, loading file was enough
1258
+			// $instantiation_mode = "2) no constructor but instantiable";
1259
+			return $reflector->newInstance();
1260
+		}
1261
+		if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
1262
+			// $instantiation_mode = "3) new_instance_from_db()";
1263
+			return call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
1264
+		}
1265
+		if (method_exists($class_name, 'new_instance')) {
1266
+			// $instantiation_mode = "4) new_instance()";
1267
+			return call_user_func_array(array($class_name, 'new_instance'), $arguments);
1268
+		}
1269
+		if (method_exists($class_name, 'instance')) {
1270
+			// $instantiation_mode = "5) instance()";
1271
+			return call_user_func_array(array($class_name, 'instance'), $arguments);
1272
+		}
1273
+		if ($reflector->isInstantiable()) {
1274
+			// $instantiation_mode = "6) constructor";
1275
+			return $reflector->newInstanceArgs($arguments);
1276
+		}
1277
+		// heh ? something's not right !
1278
+		throw new EE_Error(
1279
+			sprintf(
1280
+				esc_html__('The %s file %s could not be instantiated.', 'event_espresso'),
1281
+				$type,
1282
+				$class_name
1283
+			)
1284
+		);
1285
+	}
1286
+
1287
+
1288
+	/**
1289
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
1290
+	 * @param array $array
1291
+	 * @return bool
1292
+	 */
1293
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
1294
+	{
1295
+		return ! empty($array)
1296
+			? array_keys($array) === range(0, count($array) - 1)
1297
+			: true;
1298
+	}
1299
+
1300
+
1301
+	/**
1302
+	 * _resolve_dependencies
1303
+	 * examines the constructor for the requested class to determine
1304
+	 * if any dependencies exist, and if they can be injected.
1305
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
1306
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1307
+	 * For example:
1308
+	 *        if attempting to load a class "Foo" with the following constructor:
1309
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1310
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1311
+	 *        but only IF they are NOT already present in the incoming arguments array,
1312
+	 *        and the correct classes can be loaded
1313
+	 *
1314
+	 * @param ReflectionClass $reflector
1315
+	 * @param string          $class_name
1316
+	 * @param array           $arguments
1317
+	 * @return array
1318
+	 * @throws InvalidArgumentException
1319
+	 * @throws InvalidDataTypeException
1320
+	 * @throws InvalidInterfaceException
1321
+	 * @throws ReflectionException
1322
+	 */
1323
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, array $arguments = array())
1324
+	{
1325
+		// let's examine the constructor
1326
+		$constructor = $this->mirror->getConstructorFromReflection($reflector);
1327
+		// whu? huh? nothing?
1328
+		if (! $constructor) {
1329
+			return $arguments;
1330
+		}
1331
+		// get constructor parameters
1332
+		$params = $this->mirror->getParametersFromReflection($reflector);
1333
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1334
+		$argument_keys = array_keys($arguments);
1335
+		// now loop thru all of the constructors expected parameters
1336
+		foreach ($params as $index => $param) {
1337
+			try {
1338
+				// is this a dependency for a specific class ?
1339
+				$param_class = $this->mirror->getParameterClassName($param, $class_name, $index);
1340
+			} catch (ReflectionException $exception) {
1341
+				// uh-oh... most likely a legacy class that has not been autoloaded
1342
+				// let's try to derive the classname from what we have now
1343
+				// and hope that the property var name is close to the class name
1344
+				$param_class = $param->getName();
1345
+				$param_class = str_replace('_', ' ', $param_class);
1346
+				$param_class = ucwords($param_class);
1347
+				$param_class = str_replace(' ', '_', $param_class);
1348
+			}
1349
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1350
+			$param_class = $this->class_cache->isAlias($param_class, $class_name)
1351
+				? $this->class_cache->getFqnForAlias($param_class, $class_name)
1352
+				: $param_class;
1353
+			if (
1354 1354
 // param is not even a class
1355
-                $param_class === null
1356
-                // and something already exists in the incoming arguments for this param
1357
-                && array_key_exists($index, $argument_keys)
1358
-                && array_key_exists($argument_keys[ $index ], $arguments)
1359
-            ) {
1360
-                // so let's skip this argument and move on to the next
1361
-                continue;
1362
-            }
1363
-            if (
1355
+				$param_class === null
1356
+				// and something already exists in the incoming arguments for this param
1357
+				&& array_key_exists($index, $argument_keys)
1358
+				&& array_key_exists($argument_keys[ $index ], $arguments)
1359
+			) {
1360
+				// so let's skip this argument and move on to the next
1361
+				continue;
1362
+			}
1363
+			if (
1364 1364
 // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1365
-                $param_class !== null
1366
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1367
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1368
-            ) {
1369
-                // skip this argument and move on to the next
1370
-                continue;
1371
-            }
1372
-            if (
1365
+				$param_class !== null
1366
+				&& isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1367
+				&& $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1368
+			) {
1369
+				// skip this argument and move on to the next
1370
+				continue;
1371
+			}
1372
+			if (
1373 1373
 // parameter is type hinted as a class, and should be injected
1374
-                $param_class !== null
1375
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1376
-            ) {
1377
-                $arguments = $this->_resolve_dependency(
1378
-                    $class_name,
1379
-                    $param_class,
1380
-                    $arguments,
1381
-                    $index
1382
-                );
1383
-            }
1384
-            if (empty($arguments[ $index ])) {
1385
-                $arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1386
-                    $param,
1387
-                    $class_name,
1388
-                    $index
1389
-                );
1390
-            }
1391
-        }
1392
-        return $arguments;
1393
-    }
1394
-
1395
-
1396
-    /**
1397
-     * @param string $class_name
1398
-     * @param string $param_class
1399
-     * @param array  $arguments
1400
-     * @param mixed  $index
1401
-     * @return array
1402
-     * @throws InvalidArgumentException
1403
-     * @throws InvalidInterfaceException
1404
-     * @throws InvalidDataTypeException
1405
-     */
1406
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1407
-    {
1408
-        $dependency = null;
1409
-        // should dependency be loaded from cache ?
1410
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1411
-            $class_name,
1412
-            $param_class
1413
-        );
1414
-        $cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1415
-        // we might have a dependency...
1416
-        // let's MAYBE try and find it in our cache if that's what's been requested
1417
-        $cached_class = $cache_on
1418
-            ? $this->_get_cached_class($param_class)
1419
-            : null;
1420
-        // and grab it if it exists
1421
-        if ($cached_class instanceof $param_class) {
1422
-            $dependency = $cached_class;
1423
-        } elseif ($param_class !== $class_name) {
1424
-            // obtain the loader method from the dependency map
1425
-            $loader = $this->_dependency_map->class_loader($param_class);
1426
-            // is loader a custom closure ?
1427
-            if ($loader instanceof Closure) {
1428
-                $dependency = $loader($arguments);
1429
-            } else {
1430
-                // set the cache on property for the recursive loading call
1431
-                $this->_cache_on = $cache_on;
1432
-                // if not, then let's try and load it via the registry
1433
-                if ($loader && method_exists($this, $loader)) {
1434
-                    $dependency = $this->{$loader}($param_class);
1435
-                } else {
1436
-                    $dependency = LoaderFactory::getLoader()->load(
1437
-                        $param_class,
1438
-                        array(),
1439
-                        $cache_on
1440
-                    );
1441
-                }
1442
-            }
1443
-        }
1444
-        // did we successfully find the correct dependency ?
1445
-        if ($dependency instanceof $param_class) {
1446
-            // then let's inject it into the incoming array of arguments at the correct location
1447
-            $arguments[ $index ] = $dependency;
1448
-        }
1449
-        return $arguments;
1450
-    }
1451
-
1452
-
1453
-    /**
1454
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1455
-     *
1456
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1457
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1458
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1459
-     * @param array  $arguments
1460
-     * @return object
1461
-     */
1462
-    public static function factory($classname, $arguments = array())
1463
-    {
1464
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1465
-        if ($loader instanceof Closure) {
1466
-            return $loader($arguments);
1467
-        }
1468
-        if (method_exists(self::instance(), $loader)) {
1469
-            return self::instance()->{$loader}($classname, $arguments);
1470
-        }
1471
-        return null;
1472
-    }
1473
-
1474
-
1475
-    /**
1476
-     * Gets the addon by its class name
1477
-     *
1478
-     * @param string $class_name
1479
-     * @return EE_Addon
1480
-     */
1481
-    public function getAddon($class_name)
1482
-    {
1483
-        $class_name = str_replace('\\', '_', $class_name);
1484
-        if (isset($this->addons->{$class_name})) {
1485
-            return $this->addons->{$class_name};
1486
-        } else {
1487
-            return null;
1488
-        }
1489
-    }
1490
-
1491
-
1492
-    /**
1493
-     * removes the addon from the internal cache
1494
-     *
1495
-     * @param string $class_name
1496
-     * @return void
1497
-     */
1498
-    public function removeAddon($class_name)
1499
-    {
1500
-        $class_name = str_replace('\\', '_', $class_name);
1501
-        $this->addons->remove($class_name);
1502
-    }
1503
-
1504
-
1505
-    /**
1506
-     * Gets the addon by its name/slug (not classname. For that, just
1507
-     * use the get_addon() method above
1508
-     *
1509
-     * @param string $name
1510
-     * @return EE_Addon
1511
-     */
1512
-    public function get_addon_by_name($name)
1513
-    {
1514
-        foreach ($this->addons as $addon) {
1515
-            if ($addon->name() === $name) {
1516
-                return $addon;
1517
-            }
1518
-        }
1519
-        return null;
1520
-    }
1521
-
1522
-
1523
-    /**
1524
-     * Gets an array of all the registered addons, where the keys are their names.
1525
-     * (ie, what each returns for their name() function)
1526
-     * They're already available on EE_Registry::instance()->addons as properties,
1527
-     * where each property's name is the addon's classname,
1528
-     * So if you just want to get the addon by classname,
1529
-     * OR use the get_addon() method above.
1530
-     * PLEASE  NOTE:
1531
-     * addons with Fully Qualified Class Names
1532
-     * have had the namespace separators converted to underscores,
1533
-     * so a classname like Fully\Qualified\ClassName
1534
-     * would have been converted to Fully_Qualified_ClassName
1535
-     *
1536
-     * @return EE_Addon[] where the KEYS are the addon's name()
1537
-     */
1538
-    public function get_addons_by_name()
1539
-    {
1540
-        $addons = array();
1541
-        foreach ($this->addons as $addon) {
1542
-            $addons[ $addon->name() ] = $addon;
1543
-        }
1544
-        return $addons;
1545
-    }
1546
-
1547
-
1548
-    /**
1549
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1550
-     * a stale copy of it around
1551
-     *
1552
-     * @param string $model_name
1553
-     * @return \EEM_Base
1554
-     * @throws \EE_Error
1555
-     */
1556
-    public function reset_model($model_name)
1557
-    {
1558
-        $model_class_name = strpos($model_name, 'EEM_') !== 0
1559
-            ? "EEM_{$model_name}"
1560
-            : $model_name;
1561
-        if (! $this->LIB->has($model_class_name)) {
1562
-            return null;
1563
-        }
1564
-        $model = $this->LIB->get($model_class_name);
1565
-        if (! $model instanceof EEM_Base) {
1566
-            return null;
1567
-        }
1568
-        // get that model reset it and make sure we nuke the old reference to it
1569
-        if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1570
-            $this->LIB->remove($model_class_name);
1571
-            $this->LIB->add($model_class_name, $model->reset());
1572
-        } else {
1573
-            throw new EE_Error(
1574
-                sprintf(
1575
-                    esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1576
-                    $model_name
1577
-                )
1578
-            );
1579
-        }
1580
-        return $model;
1581
-    }
1582
-
1583
-
1584
-    /**
1585
-     * Resets the registry.
1586
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when
1587
-     * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1588
-     * - $_dependency_map
1589
-     * - $_class_abbreviations
1590
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1591
-     * - $REQ:  Still on the same request so no need to change.
1592
-     * - $CAP: There is no site specific state in the EE_Capability class.
1593
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1594
-     * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1595
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1596
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1597
-     *             switch or on the restore.
1598
-     * - $modules
1599
-     * - $shortcodes
1600
-     * - $widgets
1601
-     *
1602
-     * @param boolean $hard             [deprecated]
1603
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1604
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1605
-     *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1606
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1607
-     *                                  client
1608
-     *                                  code instead can just change the model context to a different blog id if
1609
-     *                                  necessary
1610
-     * @return EE_Registry
1611
-     * @throws InvalidInterfaceException
1612
-     * @throws InvalidDataTypeException
1613
-     * @throws EE_Error
1614
-     * @throws ReflectionException
1615
-     * @throws InvalidArgumentException
1616
-     */
1617
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1618
-    {
1619
-        $instance = self::instance();
1620
-        $instance->_cache_on = true;
1621
-        // reset some "special" classes
1622
-        EEH_Activation::reset();
1623
-        $hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1624
-        $instance->CFG = EE_Config::reset($hard, $reinstantiate);
1625
-        $instance->CART = null;
1626
-        $instance->MRM = null;
1627
-        $instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1628
-            'EventEspresso\core\services\assets\Registry'
1629
-        );
1630
-        // messages reset
1631
-        EED_Messages::reset();
1632
-        // handle of objects cached on LIB
1633
-        foreach (array('LIB', 'modules') as $cache) {
1634
-            foreach ($instance->{$cache} as $class_name => $class) {
1635
-                if (self::_reset_and_unset_object($class, $reset_models)) {
1636
-                    unset($instance->{$cache}->{$class_name});
1637
-                }
1638
-            }
1639
-        }
1640
-        return $instance;
1641
-    }
1642
-
1643
-
1644
-    /**
1645
-     * if passed object implements ResettableInterface, then call it's reset() method
1646
-     * if passed object implements InterminableInterface, then return false,
1647
-     * to indicate that it should NOT be cleared from the Registry cache
1648
-     *
1649
-     * @param      $object
1650
-     * @param bool $reset_models
1651
-     * @return bool returns true if cached object should be unset
1652
-     */
1653
-    private static function _reset_and_unset_object($object, $reset_models)
1654
-    {
1655
-        if (! is_object($object)) {
1656
-            // don't unset anything that's not an object
1657
-            return false;
1658
-        }
1659
-        if ($object instanceof EED_Module) {
1660
-            $object::reset();
1661
-            // don't unset modules
1662
-            return false;
1663
-        }
1664
-        if ($object instanceof ResettableInterface) {
1665
-            if ($object instanceof EEM_Base) {
1666
-                if ($reset_models) {
1667
-                    $object->reset();
1668
-                    return true;
1669
-                }
1670
-                return false;
1671
-            }
1672
-            $object->reset();
1673
-            return true;
1674
-        }
1675
-        if (! $object instanceof InterminableInterface) {
1676
-            return true;
1677
-        }
1678
-        return false;
1679
-    }
1680
-
1681
-
1682
-    /**
1683
-     * Gets all the custom post type models defined
1684
-     *
1685
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1686
-     */
1687
-    public function cpt_models()
1688
-    {
1689
-        $cpt_models = array();
1690
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1691
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1692
-                $cpt_models[ $short_name ] = $classname;
1693
-            }
1694
-        }
1695
-        return $cpt_models;
1696
-    }
1697
-
1698
-
1699
-    /**
1700
-     * @return \EE_Config
1701
-     */
1702
-    public static function CFG()
1703
-    {
1704
-        return self::instance()->CFG;
1705
-    }
1706
-
1707
-
1708
-    /**
1709
-     * @deprecated 4.9.62.p
1710
-     * @param string $class_name
1711
-     * @return ReflectionClass
1712
-     * @throws ReflectionException
1713
-     * @throws InvalidDataTypeException
1714
-     */
1715
-    public function get_ReflectionClass($class_name)
1716
-    {
1717
-        return $this->mirror->getReflectionClass($class_name);
1718
-    }
1374
+				$param_class !== null
1375
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1376
+			) {
1377
+				$arguments = $this->_resolve_dependency(
1378
+					$class_name,
1379
+					$param_class,
1380
+					$arguments,
1381
+					$index
1382
+				);
1383
+			}
1384
+			if (empty($arguments[ $index ])) {
1385
+				$arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1386
+					$param,
1387
+					$class_name,
1388
+					$index
1389
+				);
1390
+			}
1391
+		}
1392
+		return $arguments;
1393
+	}
1394
+
1395
+
1396
+	/**
1397
+	 * @param string $class_name
1398
+	 * @param string $param_class
1399
+	 * @param array  $arguments
1400
+	 * @param mixed  $index
1401
+	 * @return array
1402
+	 * @throws InvalidArgumentException
1403
+	 * @throws InvalidInterfaceException
1404
+	 * @throws InvalidDataTypeException
1405
+	 */
1406
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1407
+	{
1408
+		$dependency = null;
1409
+		// should dependency be loaded from cache ?
1410
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency(
1411
+			$class_name,
1412
+			$param_class
1413
+		);
1414
+		$cache_on = $cache_on !== EE_Dependency_Map::load_new_object;
1415
+		// we might have a dependency...
1416
+		// let's MAYBE try and find it in our cache if that's what's been requested
1417
+		$cached_class = $cache_on
1418
+			? $this->_get_cached_class($param_class)
1419
+			: null;
1420
+		// and grab it if it exists
1421
+		if ($cached_class instanceof $param_class) {
1422
+			$dependency = $cached_class;
1423
+		} elseif ($param_class !== $class_name) {
1424
+			// obtain the loader method from the dependency map
1425
+			$loader = $this->_dependency_map->class_loader($param_class);
1426
+			// is loader a custom closure ?
1427
+			if ($loader instanceof Closure) {
1428
+				$dependency = $loader($arguments);
1429
+			} else {
1430
+				// set the cache on property for the recursive loading call
1431
+				$this->_cache_on = $cache_on;
1432
+				// if not, then let's try and load it via the registry
1433
+				if ($loader && method_exists($this, $loader)) {
1434
+					$dependency = $this->{$loader}($param_class);
1435
+				} else {
1436
+					$dependency = LoaderFactory::getLoader()->load(
1437
+						$param_class,
1438
+						array(),
1439
+						$cache_on
1440
+					);
1441
+				}
1442
+			}
1443
+		}
1444
+		// did we successfully find the correct dependency ?
1445
+		if ($dependency instanceof $param_class) {
1446
+			// then let's inject it into the incoming array of arguments at the correct location
1447
+			$arguments[ $index ] = $dependency;
1448
+		}
1449
+		return $arguments;
1450
+	}
1451
+
1452
+
1453
+	/**
1454
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1455
+	 *
1456
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1457
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1458
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1459
+	 * @param array  $arguments
1460
+	 * @return object
1461
+	 */
1462
+	public static function factory($classname, $arguments = array())
1463
+	{
1464
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1465
+		if ($loader instanceof Closure) {
1466
+			return $loader($arguments);
1467
+		}
1468
+		if (method_exists(self::instance(), $loader)) {
1469
+			return self::instance()->{$loader}($classname, $arguments);
1470
+		}
1471
+		return null;
1472
+	}
1473
+
1474
+
1475
+	/**
1476
+	 * Gets the addon by its class name
1477
+	 *
1478
+	 * @param string $class_name
1479
+	 * @return EE_Addon
1480
+	 */
1481
+	public function getAddon($class_name)
1482
+	{
1483
+		$class_name = str_replace('\\', '_', $class_name);
1484
+		if (isset($this->addons->{$class_name})) {
1485
+			return $this->addons->{$class_name};
1486
+		} else {
1487
+			return null;
1488
+		}
1489
+	}
1490
+
1491
+
1492
+	/**
1493
+	 * removes the addon from the internal cache
1494
+	 *
1495
+	 * @param string $class_name
1496
+	 * @return void
1497
+	 */
1498
+	public function removeAddon($class_name)
1499
+	{
1500
+		$class_name = str_replace('\\', '_', $class_name);
1501
+		$this->addons->remove($class_name);
1502
+	}
1503
+
1504
+
1505
+	/**
1506
+	 * Gets the addon by its name/slug (not classname. For that, just
1507
+	 * use the get_addon() method above
1508
+	 *
1509
+	 * @param string $name
1510
+	 * @return EE_Addon
1511
+	 */
1512
+	public function get_addon_by_name($name)
1513
+	{
1514
+		foreach ($this->addons as $addon) {
1515
+			if ($addon->name() === $name) {
1516
+				return $addon;
1517
+			}
1518
+		}
1519
+		return null;
1520
+	}
1521
+
1522
+
1523
+	/**
1524
+	 * Gets an array of all the registered addons, where the keys are their names.
1525
+	 * (ie, what each returns for their name() function)
1526
+	 * They're already available on EE_Registry::instance()->addons as properties,
1527
+	 * where each property's name is the addon's classname,
1528
+	 * So if you just want to get the addon by classname,
1529
+	 * OR use the get_addon() method above.
1530
+	 * PLEASE  NOTE:
1531
+	 * addons with Fully Qualified Class Names
1532
+	 * have had the namespace separators converted to underscores,
1533
+	 * so a classname like Fully\Qualified\ClassName
1534
+	 * would have been converted to Fully_Qualified_ClassName
1535
+	 *
1536
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1537
+	 */
1538
+	public function get_addons_by_name()
1539
+	{
1540
+		$addons = array();
1541
+		foreach ($this->addons as $addon) {
1542
+			$addons[ $addon->name() ] = $addon;
1543
+		}
1544
+		return $addons;
1545
+	}
1546
+
1547
+
1548
+	/**
1549
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1550
+	 * a stale copy of it around
1551
+	 *
1552
+	 * @param string $model_name
1553
+	 * @return \EEM_Base
1554
+	 * @throws \EE_Error
1555
+	 */
1556
+	public function reset_model($model_name)
1557
+	{
1558
+		$model_class_name = strpos($model_name, 'EEM_') !== 0
1559
+			? "EEM_{$model_name}"
1560
+			: $model_name;
1561
+		if (! $this->LIB->has($model_class_name)) {
1562
+			return null;
1563
+		}
1564
+		$model = $this->LIB->get($model_class_name);
1565
+		if (! $model instanceof EEM_Base) {
1566
+			return null;
1567
+		}
1568
+		// get that model reset it and make sure we nuke the old reference to it
1569
+		if ($model instanceof $model_class_name && is_callable([$model_class_name, 'reset'])) {
1570
+			$this->LIB->remove($model_class_name);
1571
+			$this->LIB->add($model_class_name, $model->reset());
1572
+		} else {
1573
+			throw new EE_Error(
1574
+				sprintf(
1575
+					esc_html__('Model %s does not have a method "reset"', 'event_espresso'),
1576
+					$model_name
1577
+				)
1578
+			);
1579
+		}
1580
+		return $model;
1581
+	}
1582
+
1583
+
1584
+	/**
1585
+	 * Resets the registry.
1586
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when
1587
+	 * switch_to_blog is used in a multisite install.  Here is a list of things that are NOT reset.
1588
+	 * - $_dependency_map
1589
+	 * - $_class_abbreviations
1590
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1591
+	 * - $REQ:  Still on the same request so no need to change.
1592
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1593
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only
1594
+	 * one Session can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1595
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1596
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1597
+	 *             switch or on the restore.
1598
+	 * - $modules
1599
+	 * - $shortcodes
1600
+	 * - $widgets
1601
+	 *
1602
+	 * @param boolean $hard             [deprecated]
1603
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1604
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not
1605
+	 *                                  sure if you CAN currently reinstantiate the singletons at the moment)
1606
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so
1607
+	 *                                  client
1608
+	 *                                  code instead can just change the model context to a different blog id if
1609
+	 *                                  necessary
1610
+	 * @return EE_Registry
1611
+	 * @throws InvalidInterfaceException
1612
+	 * @throws InvalidDataTypeException
1613
+	 * @throws EE_Error
1614
+	 * @throws ReflectionException
1615
+	 * @throws InvalidArgumentException
1616
+	 */
1617
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1618
+	{
1619
+		$instance = self::instance();
1620
+		$instance->_cache_on = true;
1621
+		// reset some "special" classes
1622
+		EEH_Activation::reset();
1623
+		$hard = apply_filters('FHEE__EE_Registry__reset__hard', $hard);
1624
+		$instance->CFG = EE_Config::reset($hard, $reinstantiate);
1625
+		$instance->CART = null;
1626
+		$instance->MRM = null;
1627
+		$instance->AssetsRegistry = LoaderFactory::getLoader()->getShared(
1628
+			'EventEspresso\core\services\assets\Registry'
1629
+		);
1630
+		// messages reset
1631
+		EED_Messages::reset();
1632
+		// handle of objects cached on LIB
1633
+		foreach (array('LIB', 'modules') as $cache) {
1634
+			foreach ($instance->{$cache} as $class_name => $class) {
1635
+				if (self::_reset_and_unset_object($class, $reset_models)) {
1636
+					unset($instance->{$cache}->{$class_name});
1637
+				}
1638
+			}
1639
+		}
1640
+		return $instance;
1641
+	}
1642
+
1643
+
1644
+	/**
1645
+	 * if passed object implements ResettableInterface, then call it's reset() method
1646
+	 * if passed object implements InterminableInterface, then return false,
1647
+	 * to indicate that it should NOT be cleared from the Registry cache
1648
+	 *
1649
+	 * @param      $object
1650
+	 * @param bool $reset_models
1651
+	 * @return bool returns true if cached object should be unset
1652
+	 */
1653
+	private static function _reset_and_unset_object($object, $reset_models)
1654
+	{
1655
+		if (! is_object($object)) {
1656
+			// don't unset anything that's not an object
1657
+			return false;
1658
+		}
1659
+		if ($object instanceof EED_Module) {
1660
+			$object::reset();
1661
+			// don't unset modules
1662
+			return false;
1663
+		}
1664
+		if ($object instanceof ResettableInterface) {
1665
+			if ($object instanceof EEM_Base) {
1666
+				if ($reset_models) {
1667
+					$object->reset();
1668
+					return true;
1669
+				}
1670
+				return false;
1671
+			}
1672
+			$object->reset();
1673
+			return true;
1674
+		}
1675
+		if (! $object instanceof InterminableInterface) {
1676
+			return true;
1677
+		}
1678
+		return false;
1679
+	}
1680
+
1681
+
1682
+	/**
1683
+	 * Gets all the custom post type models defined
1684
+	 *
1685
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1686
+	 */
1687
+	public function cpt_models()
1688
+	{
1689
+		$cpt_models = array();
1690
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1691
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1692
+				$cpt_models[ $short_name ] = $classname;
1693
+			}
1694
+		}
1695
+		return $cpt_models;
1696
+	}
1697
+
1698
+
1699
+	/**
1700
+	 * @return \EE_Config
1701
+	 */
1702
+	public static function CFG()
1703
+	{
1704
+		return self::instance()->CFG;
1705
+	}
1706
+
1707
+
1708
+	/**
1709
+	 * @deprecated 4.9.62.p
1710
+	 * @param string $class_name
1711
+	 * @return ReflectionClass
1712
+	 * @throws ReflectionException
1713
+	 * @throws InvalidDataTypeException
1714
+	 */
1715
+	public function get_ReflectionClass($class_name)
1716
+	{
1717
+		return $this->mirror->getReflectionClass($class_name);
1718
+	}
1719 1719
 }
Please login to merge, or discard this patch.
Spacing   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
         foreach ($i18n_js_strings as $key => $value) {
310 310
             if (is_scalar($value)) {
311 311
                 $decoded_value           = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
312
-                $i18n_js_strings[ $key ] = wp_strip_all_tags($decoded_value);
312
+                $i18n_js_strings[$key] = wp_strip_all_tags($decoded_value);
313 313
             }
314 314
         }
315 315
         return $i18n_js_strings;
@@ -324,7 +324,7 @@  discard block
 block discarded – undo
324 324
     public static function localize_i18n_js_strings()
325 325
     {
326 326
         $i18n_js_strings = EE_Registry::sanitize_i18n_js_strings();
327
-        return '/* <![CDATA[ */ var eei18n = ' . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
327
+        return '/* <![CDATA[ */ var eei18n = '.wp_json_encode($i18n_js_strings).'; /* ]]> */';
328 328
     }
329 329
 
330 330
 
@@ -343,7 +343,7 @@  discard block
 block discarded – undo
343 343
             $module_class = get_class($module);
344 344
             $this->modules->add($module_class, $module);
345 345
         } else {
346
-            if (! class_exists('EE_Module_Request_Router', false)) {
346
+            if ( ! class_exists('EE_Module_Request_Router', false)) {
347 347
                 $this->load_core('Module_Request_Router');
348 348
             }
349 349
             EE_Module_Request_Router::module_factory($module);
@@ -382,10 +382,10 @@  discard block
 block discarded – undo
382 382
                 EE_CORE,
383 383
                 EE_ADMIN,
384 384
                 EE_CPTS,
385
-                EE_CORE . 'CPTs/',
386
-                EE_CORE . 'data_migration_scripts/',
387
-                EE_CORE . 'request_stack/',
388
-                EE_CORE . 'middleware/',
385
+                EE_CORE.'CPTs/',
386
+                EE_CORE.'data_migration_scripts/',
387
+                EE_CORE.'request_stack/',
388
+                EE_CORE.'middleware/',
389 389
             )
390 390
         );
391 391
         // retrieve instantiated class
@@ -420,7 +420,7 @@  discard block
 block discarded – undo
420 420
         $service_paths = apply_filters(
421 421
             'FHEE__EE_Registry__load_service__service_paths',
422 422
             array(
423
-                EE_CORE . 'services/',
423
+                EE_CORE.'services/',
424 424
             )
425 425
         );
426 426
         // retrieve instantiated class
@@ -555,10 +555,10 @@  discard block
 block discarded – undo
555 555
     {
556 556
         $paths = array(
557 557
             EE_LIBRARIES,
558
-            EE_LIBRARIES . 'messages/',
559
-            EE_LIBRARIES . 'shortcodes/',
560
-            EE_LIBRARIES . 'qtips/',
561
-            EE_LIBRARIES . 'payment_methods/',
558
+            EE_LIBRARIES.'messages/',
559
+            EE_LIBRARIES.'shortcodes/',
560
+            EE_LIBRARIES.'qtips/',
561
+            EE_LIBRARIES.'payment_methods/',
562 562
         );
563 563
         // retrieve instantiated class
564 564
         return $this->_load(
@@ -626,10 +626,10 @@  discard block
 block discarded – undo
626 626
     public function load_model_class($class_name, $arguments = array(), $load_only = true)
627 627
     {
628 628
         $paths = array(
629
-            EE_MODELS . 'fields/',
630
-            EE_MODELS . 'helpers/',
631
-            EE_MODELS . 'relations/',
632
-            EE_MODELS . 'strategies/',
629
+            EE_MODELS.'fields/',
630
+            EE_MODELS.'helpers/',
631
+            EE_MODELS.'relations/',
632
+            EE_MODELS.'strategies/',
633 633
         );
634 634
         // retrieve instantiated class
635 635
         return $this->_load(
@@ -653,7 +653,7 @@  discard block
 block discarded – undo
653 653
      */
654 654
     public function is_model_name($model_name)
655 655
     {
656
-        return isset($this->models[ $model_name ]);
656
+        return isset($this->models[$model_name]);
657 657
     }
658 658
 
659 659
 
@@ -774,7 +774,7 @@  discard block
 block discarded – undo
774 774
                 return $cached_class;
775 775
             }
776 776
         }// obtain the loader method from the dependency map
777
-        $loader = $this->_dependency_map->class_loader($class_name);// instantiate the requested object
777
+        $loader = $this->_dependency_map->class_loader($class_name); // instantiate the requested object
778 778
         if ($loader instanceof Closure) {
779 779
             $class_obj = $loader($arguments);
780 780
         } else {
@@ -816,7 +816,7 @@  discard block
 block discarded – undo
816 816
             case 1:
817 817
                 // if it's a FQCN then maybe the class is registered with a preceding \
818 818
                 $class_name = strpos($class_name, '\\') !== false
819
-                    ? '\\' . ltrim($class_name, '\\')
819
+                    ? '\\'.ltrim($class_name, '\\')
820 820
                     : $class_name;
821 821
                 break;
822 822
             case 2:
@@ -870,11 +870,11 @@  discard block
 block discarded – undo
870 870
         // strip php file extension
871 871
         $class_name = str_replace('.php', '', trim($class_name));
872 872
         // does the class have a prefix ?
873
-        if (! empty($class_prefix) && $class_prefix !== 'addon') {
873
+        if ( ! empty($class_prefix) && $class_prefix !== 'addon') {
874 874
             // make sure $class_prefix is uppercase
875 875
             $class_prefix = strtoupper(trim($class_prefix));
876 876
             // add class prefix ONCE!!!
877
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
877
+            $class_name = $class_prefix.str_replace($class_prefix, '', $class_name);
878 878
         }
879 879
         $class_name = $this->class_cache->getFqnForAlias($class_name);
880 880
         $class_exists = class_exists($class_name, false);
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
             }
895 895
         }
896 896
         // if the class doesn't already exist.. then we need to try and find the file and load it
897
-        if (! $class_exists) {
897
+        if ( ! $class_exists) {
898 898
             // get full path to file
899 899
             $path = $this->_resolve_path($class_name, $type, $file_paths);
900 900
             // load the file
@@ -905,7 +905,7 @@  discard block
 block discarded – undo
905 905
                 return $loaded;
906 906
             }
907 907
             // if an object was expected but loading failed, then return nothing
908
-            if (! $loaded) {
908
+            if ( ! $loaded) {
909 909
                 return null;
910 910
             }
911 911
         }
@@ -933,8 +933,8 @@  discard block
 block discarded – undo
933 933
      */
934 934
     protected function get_class_abbreviation($class_name, $default = 'FANCY_BATMAN_PANTS')
935 935
     {
936
-        return isset($this->_class_abbreviations[ $class_name ])
937
-            ? $this->_class_abbreviations[ $class_name ]
936
+        return isset($this->_class_abbreviations[$class_name])
937
+            ? $this->_class_abbreviations[$class_name]
938 938
             : $default;
939 939
     }
940 940
 
@@ -1068,7 +1068,7 @@  discard block
 block discarded – undo
1068 1068
             $this->addons->add($class_name, $class_obj);
1069 1069
             return;
1070 1070
         }
1071
-        if (! $from_db) {
1071
+        if ( ! $from_db) {
1072 1072
             $class_name = $this->object_identifier->getIdentifier($class_name, $arguments);
1073 1073
             $this->LIB->add($class_name, $class_obj);
1074 1074
         }
@@ -1099,13 +1099,13 @@  discard block
 block discarded – undo
1099 1099
                 : EE_CLASSES;
1100 1100
             // prep file type
1101 1101
             $type = ! empty($type)
1102
-                ? trim($type, '.') . '.'
1102
+                ? trim($type, '.').'.'
1103 1103
                 : '';
1104 1104
             // build full file path
1105
-            $file_paths[ $key ] = rtrim($file_path, '/') . '/' . $class_name . '.' . $type . 'php';
1105
+            $file_paths[$key] = rtrim($file_path, '/').'/'.$class_name.'.'.$type.'php';
1106 1106
             // does the file exist and can be read ?
1107
-            if (is_readable($file_paths[ $key ])) {
1108
-                return $file_paths[ $key ];
1107
+            if (is_readable($file_paths[$key])) {
1108
+                return $file_paths[$key];
1109 1109
             }
1110 1110
         }
1111 1111
         return false;
@@ -1130,7 +1130,7 @@  discard block
 block discarded – undo
1130 1130
         // don't give up! you gotta...
1131 1131
         try {
1132 1132
             // does the file exist and can it be read ?
1133
-            if (! $path) {
1133
+            if ( ! $path) {
1134 1134
                 // just in case the file has already been autoloaded,
1135 1135
                 // but discrepancies in the naming schema are preventing it from
1136 1136
                 // being loaded via one of the EE_Registry::load_*() methods,
@@ -1148,7 +1148,7 @@  discard block
 block discarded – undo
1148 1148
                         ),
1149 1149
                         trim($type, '.'),
1150 1150
                         $class_name,
1151
-                        '<br />' . implode(',<br />', $file_paths)
1151
+                        '<br />'.implode(',<br />', $file_paths)
1152 1152
                     )
1153 1153
                 );
1154 1154
             }
@@ -1191,8 +1191,8 @@  discard block
 block discarded – undo
1191 1191
             $legacy_parent_class_map = array(
1192 1192
                 'EE_Payment_Processor' => 'core/business/EE_Processor_Base.class.php',
1193 1193
             );
1194
-            if (isset($legacy_parent_class_map[ $class_name ])) {
1195
-                require_once EE_PLUGIN_DIR_PATH . $legacy_parent_class_map[ $class_name ];
1194
+            if (isset($legacy_parent_class_map[$class_name])) {
1195
+                require_once EE_PLUGIN_DIR_PATH.$legacy_parent_class_map[$class_name];
1196 1196
             }
1197 1197
         } catch (Exception $exception) {
1198 1198
         }
@@ -1325,7 +1325,7 @@  discard block
 block discarded – undo
1325 1325
         // let's examine the constructor
1326 1326
         $constructor = $this->mirror->getConstructorFromReflection($reflector);
1327 1327
         // whu? huh? nothing?
1328
-        if (! $constructor) {
1328
+        if ( ! $constructor) {
1329 1329
             return $arguments;
1330 1330
         }
1331 1331
         // get constructor parameters
@@ -1355,7 +1355,7 @@  discard block
 block discarded – undo
1355 1355
                 $param_class === null
1356 1356
                 // and something already exists in the incoming arguments for this param
1357 1357
                 && array_key_exists($index, $argument_keys)
1358
-                && array_key_exists($argument_keys[ $index ], $arguments)
1358
+                && array_key_exists($argument_keys[$index], $arguments)
1359 1359
             ) {
1360 1360
                 // so let's skip this argument and move on to the next
1361 1361
                 continue;
@@ -1363,8 +1363,8 @@  discard block
 block discarded – undo
1363 1363
             if (
1364 1364
 // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1365 1365
                 $param_class !== null
1366
-                && isset($argument_keys[ $index ], $arguments[ $argument_keys[ $index ] ])
1367
-                && $arguments[ $argument_keys[ $index ] ] instanceof $param_class
1366
+                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1367
+                && $arguments[$argument_keys[$index]] instanceof $param_class
1368 1368
             ) {
1369 1369
                 // skip this argument and move on to the next
1370 1370
                 continue;
@@ -1381,8 +1381,8 @@  discard block
 block discarded – undo
1381 1381
                     $index
1382 1382
                 );
1383 1383
             }
1384
-            if (empty($arguments[ $index ])) {
1385
-                $arguments[ $index ] = $this->mirror->getParameterDefaultValue(
1384
+            if (empty($arguments[$index])) {
1385
+                $arguments[$index] = $this->mirror->getParameterDefaultValue(
1386 1386
                     $param,
1387 1387
                     $class_name,
1388 1388
                     $index
@@ -1444,7 +1444,7 @@  discard block
 block discarded – undo
1444 1444
         // did we successfully find the correct dependency ?
1445 1445
         if ($dependency instanceof $param_class) {
1446 1446
             // then let's inject it into the incoming array of arguments at the correct location
1447
-            $arguments[ $index ] = $dependency;
1447
+            $arguments[$index] = $dependency;
1448 1448
         }
1449 1449
         return $arguments;
1450 1450
     }
@@ -1539,7 +1539,7 @@  discard block
 block discarded – undo
1539 1539
     {
1540 1540
         $addons = array();
1541 1541
         foreach ($this->addons as $addon) {
1542
-            $addons[ $addon->name() ] = $addon;
1542
+            $addons[$addon->name()] = $addon;
1543 1543
         }
1544 1544
         return $addons;
1545 1545
     }
@@ -1558,11 +1558,11 @@  discard block
 block discarded – undo
1558 1558
         $model_class_name = strpos($model_name, 'EEM_') !== 0
1559 1559
             ? "EEM_{$model_name}"
1560 1560
             : $model_name;
1561
-        if (! $this->LIB->has($model_class_name)) {
1561
+        if ( ! $this->LIB->has($model_class_name)) {
1562 1562
             return null;
1563 1563
         }
1564 1564
         $model = $this->LIB->get($model_class_name);
1565
-        if (! $model instanceof EEM_Base) {
1565
+        if ( ! $model instanceof EEM_Base) {
1566 1566
             return null;
1567 1567
         }
1568 1568
         // get that model reset it and make sure we nuke the old reference to it
@@ -1652,7 +1652,7 @@  discard block
 block discarded – undo
1652 1652
      */
1653 1653
     private static function _reset_and_unset_object($object, $reset_models)
1654 1654
     {
1655
-        if (! is_object($object)) {
1655
+        if ( ! is_object($object)) {
1656 1656
             // don't unset anything that's not an object
1657 1657
             return false;
1658 1658
         }
@@ -1672,7 +1672,7 @@  discard block
 block discarded – undo
1672 1672
             $object->reset();
1673 1673
             return true;
1674 1674
         }
1675
-        if (! $object instanceof InterminableInterface) {
1675
+        if ( ! $object instanceof InterminableInterface) {
1676 1676
             return true;
1677 1677
         }
1678 1678
         return false;
@@ -1689,7 +1689,7 @@  discard block
 block discarded – undo
1689 1689
         $cpt_models = array();
1690 1690
         foreach ($this->non_abstract_db_models as $short_name => $classname) {
1691 1691
             if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1692
-                $cpt_models[ $short_name ] = $classname;
1692
+                $cpt_models[$short_name] = $classname;
1693 1693
             }
1694 1694
         }
1695 1695
         return $cpt_models;
Please login to merge, or discard this patch.