Completed
Branch BUG/11475/decode-site-title-fo... (bbd86e)
by
unknown
13:39 queued 25s
created
core/domain/Domain.php 2 patches
Indentation   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -19,54 +19,54 @@
 block discarded – undo
19 19
 class Domain extends DomainBase implements CaffeinatedInterface
20 20
 {
21 21
 
22
-    /**
23
-     * URL path component used to denote an API request
24
-     */
25
-    const API_NAMESPACE = 'ee/v';
22
+	/**
23
+	 * URL path component used to denote an API request
24
+	 */
25
+	const API_NAMESPACE = 'ee/v';
26 26
 
27
-    /**
28
-     * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
29
-     * Page ui.
30
-     */
31
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
32
-        = 'manual_registration_status_change_from_registration_admin';
27
+	/**
28
+	 * Slug used for the context where a registration status is changed from a manual trigger in the Registration Admin
29
+	 * Page ui.
30
+	 */
31
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN
32
+		= 'manual_registration_status_change_from_registration_admin';
33 33
 
34
-    const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
35
-        = 'manual_registration_status_change_from_registration_admin_and_notify';
34
+	const CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
35
+		= 'manual_registration_status_change_from_registration_admin_and_notify';
36 36
 
37 37
 
38
-    /**
39
-     * Whether or not EE core is the full premium version.
40
-     * @since $VID:$
41
-     * @var bool
42
-     */
43
-    private $caffeinated;
38
+	/**
39
+	 * Whether or not EE core is the full premium version.
40
+	 * @since $VID:$
41
+	 * @var bool
42
+	 */
43
+	private $caffeinated;
44 44
 
45 45
 
46
-    public function __construct(FilePath $plugin_file, Version $version)
47
-    {
48
-        parent::__construct($plugin_file, $version);
49
-        $this->setCaffeinated();
50
-    }
46
+	public function __construct(FilePath $plugin_file, Version $version)
47
+	{
48
+		parent::__construct($plugin_file, $version);
49
+		$this->setCaffeinated();
50
+	}
51 51
 
52
-    /**
53
-     * Whether or not EE core is the full premium version.
54
-     * @since $VID:$
55
-     * @return bool
56
-     */
57
-    public function isCaffeinated()
58
-    {
59
-        return $this->caffeinated;
60
-    }
52
+	/**
53
+	 * Whether or not EE core is the full premium version.
54
+	 * @since $VID:$
55
+	 * @return bool
56
+	 */
57
+	public function isCaffeinated()
58
+	{
59
+		return $this->caffeinated;
60
+	}
61 61
 
62 62
 
63
-    /**
64
-     * Setter for $is_caffeinated property.
65
-     * @since $VID:$
66
-     */
67
-    private function setCaffeinated()
68
-    {
69
-        $this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
70
-            && is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
71
-    }
63
+	/**
64
+	 * Setter for $is_caffeinated property.
65
+	 * @since $VID:$
66
+	 */
67
+	private function setCaffeinated()
68
+	{
69
+		$this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
70
+			&& is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
71
+	}
72 72
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -66,7 +66,7 @@
 block discarded – undo
66 66
      */
67 67
     private function setCaffeinated()
68 68
     {
69
-        $this->caffeinated = (! defined('EE_DECAF') || EE_DECAF !== true)
70
-            && is_readable($this->pluginPath() . 'caffeinated/brewing_regular.php');
69
+        $this->caffeinated = ( ! defined('EE_DECAF') || EE_DECAF !== true)
70
+            && is_readable($this->pluginPath().'caffeinated/brewing_regular.php');
71 71
     }
72 72
 }
Please login to merge, or discard this patch.
core/EE_System.core.php 2 patches
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
         EE_Maintenance_Mode $maintenance_mode = null
149 149
     ) {
150 150
         // check if class object is instantiated
151
-        if (! self::$_instance instanceof EE_System) {
151
+        if ( ! self::$_instance instanceof EE_System) {
152 152
             self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
153 153
         }
154 154
         return self::$_instance;
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
         $this->capabilities = $this->loader->getShared('EE_Capabilities');
268 268
         add_action(
269 269
             'AHEE__EE_Capabilities__init_caps__before_initialization',
270
-            function ()
270
+            function()
271 271
             {
272 272
                 LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
273 273
             }
@@ -311,7 +311,7 @@  discard block
 block discarded – undo
311 311
     {
312 312
         // set autoloaders for all of the classes implementing EEI_Plugin_API
313 313
         // which provide helpers for EE plugin authors to more easily register certain components with EE.
314
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
314
+        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES.'plugin_api');
315 315
         $this->loader->getShared('EE_Request_Handler');
316 316
     }
317 317
 
@@ -331,14 +331,14 @@  discard block
 block discarded – undo
331 331
         $load_callback,
332 332
         $plugin_file_constant
333 333
     ) {
334
-        if (! defined($version_constant)) {
334
+        if ( ! defined($version_constant)) {
335 335
             return;
336 336
         }
337 337
         $addon_version = constant($version_constant);
338 338
         if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
339 339
             remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
340
-            if (! function_exists('deactivate_plugins')) {
341
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
340
+            if ( ! function_exists('deactivate_plugins')) {
341
+                require_once ABSPATH.'wp-admin/includes/plugin.php';
342 342
             }
343 343
             deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
344 344
             unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
@@ -351,7 +351,7 @@  discard block
 block discarded – undo
351 351
                     $addon_name,
352 352
                     $min_version_required
353 353
                 ),
354
-                __FILE__, __FUNCTION__ . "({$addon_name})", __LINE__
354
+                __FILE__, __FUNCTION__."({$addon_name})", __LINE__
355 355
             );
356 356
             EE_Error::get_notices(false, true);
357 357
         }
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
                 true
402 402
             )
403 403
         ) {
404
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
404
+            include_once EE_THIRD_PARTY.'wp-api-basic-auth'.DS.'basic-auth.php';
405 405
         }
406 406
         do_action('AHEE__EE_System__load_espresso_addons__complete');
407 407
     }
@@ -508,11 +508,11 @@  discard block
 block discarded – undo
508 508
     private function fix_espresso_db_upgrade_option($espresso_db_update = null)
509 509
     {
510 510
         do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
511
-        if (! $espresso_db_update) {
511
+        if ( ! $espresso_db_update) {
512 512
             $espresso_db_update = get_option('espresso_db_update');
513 513
         }
514 514
         // check that option is an array
515
-        if (! is_array($espresso_db_update)) {
515
+        if ( ! is_array($espresso_db_update)) {
516 516
             // if option is FALSE, then it never existed
517 517
             if ($espresso_db_update === false) {
518 518
                 // make $espresso_db_update an array and save option with autoload OFF
@@ -532,10 +532,10 @@  discard block
 block discarded – undo
532 532
                     //so it must be numerically-indexed, where values are versions installed...
533 533
                     //fix it!
534 534
                     $version_string                         = $should_be_array;
535
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
535
+                    $corrected_db_update[$version_string] = array('unknown-date');
536 536
                 } else {
537 537
                     //ok it checks out
538
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
538
+                    $corrected_db_update[$should_be_version_string] = $should_be_array;
539 539
                 }
540 540
             }
541 541
             $espresso_db_update = $corrected_db_update;
@@ -617,13 +617,13 @@  discard block
 block discarded – undo
617 617
      */
618 618
     public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
619 619
     {
620
-        if (! $version_history) {
620
+        if ( ! $version_history) {
621 621
             $version_history = $this->fix_espresso_db_upgrade_option($version_history);
622 622
         }
623 623
         if ($current_version_to_add === null) {
624 624
             $current_version_to_add = espresso_version();
625 625
         }
626
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
626
+        $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
627 627
         // re-save
628 628
         return update_option('espresso_db_update', $version_history);
629 629
     }
@@ -716,7 +716,7 @@  discard block
 block discarded – undo
716 716
         if ($activation_history_for_addon) {
717 717
             //it exists, so this isn't a completely new install
718 718
             //check if this version already in that list of previously installed versions
719
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
719
+            if ( ! isset($activation_history_for_addon[$version_to_upgrade_to])) {
720 720
                 //it a version we haven't seen before
721 721
                 if ($version_is_higher === 1) {
722 722
                     $req_type = EE_System::req_type_upgrade;
@@ -796,7 +796,7 @@  discard block
 block discarded – undo
796 796
             foreach ($activation_history as $version => $times_activated) {
797 797
                 //check there is a record of when this version was activated. Otherwise,
798 798
                 //mark it as unknown
799
-                if (! $times_activated) {
799
+                if ( ! $times_activated) {
800 800
                     $times_activated = array('unknown-date');
801 801
                 }
802 802
                 if (is_string($times_activated)) {
@@ -897,7 +897,7 @@  discard block
 block discarded – undo
897 897
     private function _parse_model_names()
898 898
     {
899 899
         //get all the files in the EE_MODELS folder that end in .model.php
900
-        $models                 = glob(EE_MODELS . '*.model.php');
900
+        $models                 = glob(EE_MODELS.'*.model.php');
901 901
         $model_names            = array();
902 902
         $non_abstract_db_models = array();
903 903
         foreach ($models as $model) {
@@ -906,9 +906,9 @@  discard block
 block discarded – undo
906 906
             $short_name      = str_replace('EEM_', '', $classname);
907 907
             $reflectionClass = new ReflectionClass($classname);
908 908
             if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
909
-                $non_abstract_db_models[ $short_name ] = $classname;
909
+                $non_abstract_db_models[$short_name] = $classname;
910 910
             }
911
-            $model_names[ $short_name ] = $classname;
911
+            $model_names[$short_name] = $classname;
912 912
         }
913 913
         $this->registry->models                 = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
914 914
         $this->registry->non_abstract_db_models = apply_filters(
@@ -943,7 +943,7 @@  discard block
 block discarded – undo
943 943
             )
944 944
         );
945 945
         if ($domain->isCaffeinated()) {
946
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
946
+            require_once EE_CAFF_PATH.'brewing_regular.php';
947 947
         }
948 948
     }
949 949
 
@@ -996,17 +996,17 @@  discard block
 block discarded – undo
996 996
         $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
997 997
             'AHEE__EE_System__register_shortcodes_modules_and_addons'
998 998
         );
999
-        if (! empty($class_names)) {
999
+        if ( ! empty($class_names)) {
1000 1000
             $msg = __(
1001 1001
                 'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1002 1002
                 'event_espresso'
1003 1003
             );
1004 1004
             $msg .= '<ul>';
1005 1005
             foreach ($class_names as $class_name) {
1006
-                $msg .= '<li><b>Event Espresso - ' . str_replace(
1006
+                $msg .= '<li><b>Event Espresso - '.str_replace(
1007 1007
                         array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
1008 1008
                         $class_name
1009
-                    ) . '</b></li>';
1009
+                    ).'</b></li>';
1010 1010
             }
1011 1011
             $msg .= '</ul>';
1012 1012
             $msg .= __(
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
     private function _deactivate_incompatible_addons()
1078 1078
     {
1079 1079
         $incompatible_addons = get_option('ee_incompatible_addons', array());
1080
-        if (! empty($incompatible_addons)) {
1080
+        if ( ! empty($incompatible_addons)) {
1081 1081
             $active_plugins = get_option('active_plugins', array());
1082 1082
             foreach ($active_plugins as $active_plugin) {
1083 1083
                 foreach ($incompatible_addons as $incompatible_addon) {
@@ -1172,10 +1172,10 @@  discard block
 block discarded – undo
1172 1172
         do_action('AHEE__EE_System__core_loaded_and_ready');
1173 1173
         // load_espresso_template_tags
1174 1174
         if (
1175
-            is_readable(EE_PUBLIC . 'template_tags.php')
1175
+            is_readable(EE_PUBLIC.'template_tags.php')
1176 1176
             && ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isFeed())
1177 1177
         ) {
1178
-            require_once EE_PUBLIC . 'template_tags.php';
1178
+            require_once EE_PUBLIC.'template_tags.php';
1179 1179
         }
1180 1180
         do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1181 1181
         if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
@@ -1239,13 +1239,13 @@  discard block
 block discarded – undo
1239 1239
     public static function do_not_cache()
1240 1240
     {
1241 1241
         // set no cache constants
1242
-        if (! defined('DONOTCACHEPAGE')) {
1242
+        if ( ! defined('DONOTCACHEPAGE')) {
1243 1243
             define('DONOTCACHEPAGE', true);
1244 1244
         }
1245
-        if (! defined('DONOTCACHCEOBJECT')) {
1245
+        if ( ! defined('DONOTCACHCEOBJECT')) {
1246 1246
             define('DONOTCACHCEOBJECT', true);
1247 1247
         }
1248
-        if (! defined('DONOTCACHEDB')) {
1248
+        if ( ! defined('DONOTCACHEDB')) {
1249 1249
             define('DONOTCACHEDB', true);
1250 1250
         }
1251 1251
         // add no cache headers
Please login to merge, or discard this patch.
Indentation   +1265 added lines, -1265 removed lines patch added patch discarded remove patch
@@ -32,1271 +32,1271 @@
 block discarded – undo
32 32
 {
33 33
 
34 34
 
35
-    /**
36
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
37
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
38
-     */
39
-    const req_type_normal = 0;
40
-
41
-    /**
42
-     * Indicates this is a brand new installation of EE so we should install
43
-     * tables and default data etc
44
-     */
45
-    const req_type_new_activation = 1;
46
-
47
-    /**
48
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
49
-     * and we just exited maintenance mode). We MUST check the database is setup properly
50
-     * and that default data is setup too
51
-     */
52
-    const req_type_reactivation = 2;
53
-
54
-    /**
55
-     * indicates that EE has been upgraded since its previous request.
56
-     * We may have data migration scripts to call and will want to trigger maintenance mode
57
-     */
58
-    const req_type_upgrade = 3;
59
-
60
-    /**
61
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
62
-     */
63
-    const req_type_downgrade = 4;
64
-
65
-    /**
66
-     * @deprecated since version 4.6.0.dev.006
67
-     * Now whenever a new_activation is detected the request type is still just
68
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
69
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
70
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
71
-     * (Specifically, when the migration manager indicates migrations are finished
72
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
73
-     */
74
-    const req_type_activation_but_not_installed = 5;
75
-
76
-    /**
77
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
78
-     */
79
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
80
-
81
-
82
-    /**
83
-     * @var EE_System $_instance
84
-     */
85
-    private static $_instance;
86
-
87
-    /**
88
-     * @var EE_Registry $registry
89
-     */
90
-    private $registry;
91
-
92
-    /**
93
-     * @var LoaderInterface $loader
94
-     */
95
-    private $loader;
96
-
97
-    /**
98
-     * @var EE_Capabilities $capabilities
99
-     */
100
-    private $capabilities;
101
-
102
-    /**
103
-     * @var RequestInterface $request
104
-     */
105
-    private $request;
106
-
107
-    /**
108
-     * @var EE_Maintenance_Mode $maintenance_mode
109
-     */
110
-    private $maintenance_mode;
111
-
112
-    /**
113
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
114
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
115
-     *
116
-     * @var int $_req_type
117
-     */
118
-    private $_req_type;
119
-
120
-    /**
121
-     * Whether or not there was a non-micro version change in EE core version during this request
122
-     *
123
-     * @var boolean $_major_version_change
124
-     */
125
-    private $_major_version_change = false;
126
-
127
-    /**
128
-     * A Context DTO dedicated solely to identifying the current request type.
129
-     *
130
-     * @var RequestTypeContextCheckerInterface $request_type
131
-     */
132
-    private $request_type;
133
-
134
-
135
-
136
-    /**
137
-     * @singleton method used to instantiate class object
138
-     * @param EE_Registry|null         $registry
139
-     * @param LoaderInterface|null     $loader
140
-     * @param RequestInterface|null          $request
141
-     * @param EE_Maintenance_Mode|null $maintenance_mode
142
-     * @return EE_System
143
-     */
144
-    public static function instance(
145
-        EE_Registry $registry = null,
146
-        LoaderInterface $loader = null,
147
-        RequestInterface $request = null,
148
-        EE_Maintenance_Mode $maintenance_mode = null
149
-    ) {
150
-        // check if class object is instantiated
151
-        if (! self::$_instance instanceof EE_System) {
152
-            self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
153
-        }
154
-        return self::$_instance;
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * resets the instance and returns it
161
-     *
162
-     * @return EE_System
163
-     */
164
-    public static function reset()
165
-    {
166
-        self::$_instance->_req_type = null;
167
-        //make sure none of the old hooks are left hanging around
168
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
169
-        //we need to reset the migration manager in order for it to detect DMSs properly
170
-        EE_Data_Migration_Manager::reset();
171
-        self::instance()->detect_activations_or_upgrades();
172
-        self::instance()->perform_activations_upgrades_and_migrations();
173
-        return self::instance();
174
-    }
175
-
176
-
177
-
178
-    /**
179
-     * sets hooks for running rest of system
180
-     * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
181
-     * starting EE Addons from any other point may lead to problems
182
-     *
183
-     * @param EE_Registry         $registry
184
-     * @param LoaderInterface     $loader
185
-     * @param RequestInterface          $request
186
-     * @param EE_Maintenance_Mode $maintenance_mode
187
-     */
188
-    private function __construct(
189
-        EE_Registry $registry,
190
-        LoaderInterface $loader,
191
-        RequestInterface $request,
192
-        EE_Maintenance_Mode $maintenance_mode
193
-    ) {
194
-        $this->registry         = $registry;
195
-        $this->loader           = $loader;
196
-        $this->request          = $request;
197
-        $this->maintenance_mode = $maintenance_mode;
198
-        do_action('AHEE__EE_System__construct__begin', $this);
199
-        add_action(
200
-            'AHEE__EE_Bootstrap__load_espresso_addons',
201
-            array($this, 'loadCapabilities'),
202
-            5
203
-        );
204
-        add_action(
205
-            'AHEE__EE_Bootstrap__load_espresso_addons',
206
-            array($this, 'loadCommandBus'),
207
-            7
208
-        );
209
-        add_action(
210
-            'AHEE__EE_Bootstrap__load_espresso_addons',
211
-            array($this, 'loadPluginApi'),
212
-            9
213
-        );
214
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
215
-        add_action(
216
-            'AHEE__EE_Bootstrap__load_espresso_addons',
217
-            array($this, 'load_espresso_addons')
218
-        );
219
-        // when an ee addon is activated, we want to call the core hook(s) again
220
-        // because the newly-activated addon didn't get a chance to run at all
221
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
222
-        // detect whether install or upgrade
223
-        add_action(
224
-            'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
225
-            array($this, 'detect_activations_or_upgrades'),
226
-            3
227
-        );
228
-        // load EE_Config, EE_Textdomain, etc
229
-        add_action(
230
-            'AHEE__EE_Bootstrap__load_core_configuration',
231
-            array($this, 'load_core_configuration'),
232
-            5
233
-        );
234
-        // load EE_Config, EE_Textdomain, etc
235
-        add_action(
236
-            'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
237
-            array($this, 'register_shortcodes_modules_and_widgets'),
238
-            7
239
-        );
240
-        // you wanna get going? I wanna get going... let's get going!
241
-        add_action(
242
-            'AHEE__EE_Bootstrap__brew_espresso',
243
-            array($this, 'brew_espresso'),
244
-            9
245
-        );
246
-        //other housekeeping
247
-        //exclude EE critical pages from wp_list_pages
248
-        add_filter(
249
-            'wp_list_pages_excludes',
250
-            array($this, 'remove_pages_from_wp_list_pages'),
251
-            10
252
-        );
253
-        // ALL EE Addons should use the following hook point to attach their initial setup too
254
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
255
-        do_action('AHEE__EE_System__construct__complete', $this);
256
-    }
257
-
258
-
259
-    /**
260
-     * load and setup EE_Capabilities
261
-     *
262
-     * @return void
263
-     * @throws EE_Error
264
-     */
265
-    public function loadCapabilities()
266
-    {
267
-        $this->capabilities = $this->loader->getShared('EE_Capabilities');
268
-        add_action(
269
-            'AHEE__EE_Capabilities__init_caps__before_initialization',
270
-            function ()
271
-            {
272
-                LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
273
-            }
274
-        );
275
-    }
276
-
277
-
278
-
279
-    /**
280
-     * create and cache the CommandBus, and also add middleware
281
-     * The CapChecker middleware requires the use of EE_Capabilities
282
-     * which is why we need to load the CommandBus after Caps are set up
283
-     *
284
-     * @return void
285
-     * @throws EE_Error
286
-     */
287
-    public function loadCommandBus()
288
-    {
289
-        $this->loader->getShared(
290
-            'CommandBusInterface',
291
-            array(
292
-                null,
293
-                apply_filters(
294
-                    'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
295
-                    array(
296
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
297
-                        $this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
298
-                    )
299
-                ),
300
-            )
301
-        );
302
-    }
303
-
304
-
305
-
306
-    /**
307
-     * @return void
308
-     * @throws EE_Error
309
-     */
310
-    public function loadPluginApi()
311
-    {
312
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
313
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
314
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
315
-        $this->loader->getShared('EE_Request_Handler');
316
-    }
317
-
318
-
319
-    /**
320
-     * @param string $addon_name
321
-     * @param string $version_constant
322
-     * @param string $min_version_required
323
-     * @param string $load_callback
324
-     * @param string $plugin_file_constant
325
-     * @return void
326
-     */
327
-    private function deactivateIncompatibleAddon(
328
-        $addon_name,
329
-        $version_constant,
330
-        $min_version_required,
331
-        $load_callback,
332
-        $plugin_file_constant
333
-    ) {
334
-        if (! defined($version_constant)) {
335
-            return;
336
-        }
337
-        $addon_version = constant($version_constant);
338
-        if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
339
-            remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
340
-            if (! function_exists('deactivate_plugins')) {
341
-                require_once ABSPATH . 'wp-admin/includes/plugin.php';
342
-            }
343
-            deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
344
-            unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
345
-            EE_Error::add_error(
346
-                sprintf(
347
-                    esc_html__(
348
-                        '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.',
349
-                        'event_espresso'
350
-                    ),
351
-                    $addon_name,
352
-                    $min_version_required
353
-                ),
354
-                __FILE__, __FUNCTION__ . "({$addon_name})", __LINE__
355
-            );
356
-            EE_Error::get_notices(false, true);
357
-        }
358
-    }
359
-
360
-
361
-    /**
362
-     * load_espresso_addons
363
-     * allow addons to load first so that they can set hooks for running DMS's, etc
364
-     * this is hooked into both:
365
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
366
-     *        which runs during the WP 'plugins_loaded' action at priority 5
367
-     *    and the WP 'activate_plugin' hook point
368
-     *
369
-     * @access public
370
-     * @return void
371
-     */
372
-    public function load_espresso_addons()
373
-    {
374
-        $this->deactivateIncompatibleAddon(
375
-            'Wait Lists',
376
-            'EE_WAIT_LISTS_VERSION',
377
-            '1.0.0.beta.074',
378
-            'load_espresso_wait_lists',
379
-            'EE_WAIT_LISTS_PLUGIN_FILE'
380
-        );
381
-        $this->deactivateIncompatibleAddon(
382
-            'Automated Upcoming Event Notifications',
383
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
384
-            '1.0.0.beta.091',
385
-            'load_espresso_automated_upcoming_event_notification',
386
-            'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
387
-        );
388
-        do_action('AHEE__EE_System__load_espresso_addons');
389
-        //if the WP API basic auth plugin isn't already loaded, load it now.
390
-        //We want it for mobile apps. Just include the entire plugin
391
-        //also, don't load the basic auth when a plugin is getting activated, because
392
-        //it could be the basic auth plugin, and it doesn't check if its methods are already defined
393
-        //and causes a fatal error
394
-        if (
395
-            $this->request->getRequestParam('activate') !== 'true'
396
-            && ! function_exists('json_basic_auth_handler')
397
-            && ! function_exists('json_basic_auth_error')
398
-            && ! in_array(
399
-                $this->request->getRequestParam('action'),
400
-                array('activate', 'activate-selected'),
401
-                true
402
-            )
403
-        ) {
404
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
405
-        }
406
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
407
-    }
408
-
409
-
410
-
411
-    /**
412
-     * detect_activations_or_upgrades
413
-     * Checks for activation or upgrade of core first;
414
-     * then also checks if any registered addons have been activated or upgraded
415
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
416
-     * which runs during the WP 'plugins_loaded' action at priority 3
417
-     *
418
-     * @access public
419
-     * @return void
420
-     */
421
-    public function detect_activations_or_upgrades()
422
-    {
423
-        //first off: let's make sure to handle core
424
-        $this->detect_if_activation_or_upgrade();
425
-        foreach ($this->registry->addons as $addon) {
426
-            if ($addon instanceof EE_Addon) {
427
-                //detect teh request type for that addon
428
-                $addon->detect_activation_or_upgrade();
429
-            }
430
-        }
431
-    }
432
-
433
-
434
-
435
-    /**
436
-     * detect_if_activation_or_upgrade
437
-     * Takes care of detecting whether this is a brand new install or code upgrade,
438
-     * and either setting up the DB or setting up maintenance mode etc.
439
-     *
440
-     * @access public
441
-     * @return void
442
-     */
443
-    public function detect_if_activation_or_upgrade()
444
-    {
445
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
446
-        // check if db has been updated, or if its a brand-new installation
447
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
448
-        $request_type       = $this->detect_req_type($espresso_db_update);
449
-        //EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
450
-        switch ($request_type) {
451
-            case EE_System::req_type_new_activation:
452
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
453
-                $this->_handle_core_version_change($espresso_db_update);
454
-                break;
455
-            case EE_System::req_type_reactivation:
456
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
457
-                $this->_handle_core_version_change($espresso_db_update);
458
-                break;
459
-            case EE_System::req_type_upgrade:
460
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
461
-                //migrations may be required now that we've upgraded
462
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
463
-                $this->_handle_core_version_change($espresso_db_update);
464
-                //				echo "done upgrade";die;
465
-                break;
466
-            case EE_System::req_type_downgrade:
467
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
468
-                //its possible migrations are no longer required
469
-                $this->maintenance_mode->set_maintenance_mode_if_db_old();
470
-                $this->_handle_core_version_change($espresso_db_update);
471
-                break;
472
-            case EE_System::req_type_normal:
473
-            default:
474
-                break;
475
-        }
476
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
477
-    }
478
-
479
-
480
-
481
-    /**
482
-     * Updates the list of installed versions and sets hooks for
483
-     * initializing the database later during the request
484
-     *
485
-     * @param array $espresso_db_update
486
-     */
487
-    private function _handle_core_version_change($espresso_db_update)
488
-    {
489
-        $this->update_list_of_installed_versions($espresso_db_update);
490
-        //get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
491
-        add_action(
492
-            'AHEE__EE_System__perform_activations_upgrades_and_migrations',
493
-            array($this, 'initialize_db_if_no_migrations_required')
494
-        );
495
-    }
496
-
497
-
498
-
499
-    /**
500
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
501
-     * information about what versions of EE have been installed and activated,
502
-     * NOT necessarily the state of the database
503
-     *
504
-     * @param mixed $espresso_db_update           the value of the WordPress option.
505
-     *                                            If not supplied, fetches it from the options table
506
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
507
-     */
508
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
509
-    {
510
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
511
-        if (! $espresso_db_update) {
512
-            $espresso_db_update = get_option('espresso_db_update');
513
-        }
514
-        // check that option is an array
515
-        if (! is_array($espresso_db_update)) {
516
-            // if option is FALSE, then it never existed
517
-            if ($espresso_db_update === false) {
518
-                // make $espresso_db_update an array and save option with autoload OFF
519
-                $espresso_db_update = array();
520
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
521
-            } else {
522
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
523
-                $espresso_db_update = array($espresso_db_update => array());
524
-                update_option('espresso_db_update', $espresso_db_update);
525
-            }
526
-        } else {
527
-            $corrected_db_update = array();
528
-            //if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
529
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
530
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
531
-                    //the key is an int, and the value IS NOT an array
532
-                    //so it must be numerically-indexed, where values are versions installed...
533
-                    //fix it!
534
-                    $version_string                         = $should_be_array;
535
-                    $corrected_db_update[ $version_string ] = array('unknown-date');
536
-                } else {
537
-                    //ok it checks out
538
-                    $corrected_db_update[ $should_be_version_string ] = $should_be_array;
539
-                }
540
-            }
541
-            $espresso_db_update = $corrected_db_update;
542
-            update_option('espresso_db_update', $espresso_db_update);
543
-        }
544
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
545
-        return $espresso_db_update;
546
-    }
547
-
548
-
549
-
550
-    /**
551
-     * Does the traditional work of setting up the plugin's database and adding default data.
552
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
553
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
554
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
555
-     * so that it will be done when migrations are finished
556
-     *
557
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
558
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
559
-     *                                       This is a resource-intensive job
560
-     *                                       so we prefer to only do it when necessary
561
-     * @return void
562
-     * @throws EE_Error
563
-     */
564
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
565
-    {
566
-        $request_type = $this->detect_req_type();
567
-        //only initialize system if we're not in maintenance mode.
568
-        if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
569
-            update_option('ee_flush_rewrite_rules', true);
570
-            if ($verify_schema) {
571
-                EEH_Activation::initialize_db_and_folders();
572
-            }
573
-            EEH_Activation::initialize_db_content();
574
-            EEH_Activation::system_initialization();
575
-            if ($initialize_addons_too) {
576
-                $this->initialize_addons();
577
-            }
578
-        } else {
579
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
580
-        }
581
-        if ($request_type === EE_System::req_type_new_activation
582
-            || $request_type === EE_System::req_type_reactivation
583
-            || (
584
-                $request_type === EE_System::req_type_upgrade
585
-                && $this->is_major_version_change()
586
-            )
587
-        ) {
588
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
589
-        }
590
-    }
591
-
592
-
593
-
594
-    /**
595
-     * Initializes the db for all registered addons
596
-     *
597
-     * @throws EE_Error
598
-     */
599
-    public function initialize_addons()
600
-    {
601
-        //foreach registered addon, make sure its db is up-to-date too
602
-        foreach ($this->registry->addons as $addon) {
603
-            if ($addon instanceof EE_Addon) {
604
-                $addon->initialize_db_if_no_migrations_required();
605
-            }
606
-        }
607
-    }
608
-
609
-
610
-
611
-    /**
612
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
613
-     *
614
-     * @param    array  $version_history
615
-     * @param    string $current_version_to_add version to be added to the version history
616
-     * @return    boolean success as to whether or not this option was changed
617
-     */
618
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
619
-    {
620
-        if (! $version_history) {
621
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
622
-        }
623
-        if ($current_version_to_add === null) {
624
-            $current_version_to_add = espresso_version();
625
-        }
626
-        $version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
627
-        // re-save
628
-        return update_option('espresso_db_update', $version_history);
629
-    }
630
-
631
-
632
-
633
-    /**
634
-     * Detects if the current version indicated in the has existed in the list of
635
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
636
-     *
637
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
638
-     *                                  If not supplied, fetches it from the options table.
639
-     *                                  Also, caches its result so later parts of the code can also know whether
640
-     *                                  there's been an update or not. This way we can add the current version to
641
-     *                                  espresso_db_update, but still know if this is a new install or not
642
-     * @return int one of the constants on EE_System::req_type_
643
-     */
644
-    public function detect_req_type($espresso_db_update = null)
645
-    {
646
-        if ($this->_req_type === null) {
647
-            $espresso_db_update          = ! empty($espresso_db_update)
648
-                ? $espresso_db_update
649
-                : $this->fix_espresso_db_upgrade_option();
650
-            $this->_req_type             = EE_System::detect_req_type_given_activation_history(
651
-                $espresso_db_update,
652
-                'ee_espresso_activation', espresso_version()
653
-            );
654
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
655
-            $this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
656
-        }
657
-        return $this->_req_type;
658
-    }
659
-
660
-
661
-
662
-    /**
663
-     * Returns whether or not there was a non-micro version change (ie, change in either
664
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
665
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
666
-     *
667
-     * @param $activation_history
668
-     * @return bool
669
-     */
670
-    private function _detect_major_version_change($activation_history)
671
-    {
672
-        $previous_version       = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
673
-        $previous_version_parts = explode('.', $previous_version);
674
-        $current_version_parts  = explode('.', espresso_version());
675
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
676
-               && ($previous_version_parts[0] !== $current_version_parts[0]
677
-                   || $previous_version_parts[1] !== $current_version_parts[1]
678
-               );
679
-    }
680
-
681
-
682
-
683
-    /**
684
-     * Returns true if either the major or minor version of EE changed during this request.
685
-     * 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
686
-     *
687
-     * @return bool
688
-     */
689
-    public function is_major_version_change()
690
-    {
691
-        return $this->_major_version_change;
692
-    }
693
-
694
-
695
-
696
-    /**
697
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
698
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
699
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
700
-     * just activated to (for core that will always be espresso_version())
701
-     *
702
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
703
-     *                                                 ee plugin. for core that's 'espresso_db_update'
704
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
705
-     *                                                 indicate that this plugin was just activated
706
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
707
-     *                                                 espresso_version())
708
-     * @return int one of the constants on EE_System::req_type_*
709
-     */
710
-    public static function detect_req_type_given_activation_history(
711
-        $activation_history_for_addon,
712
-        $activation_indicator_option_name,
713
-        $version_to_upgrade_to
714
-    ) {
715
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
716
-        if ($activation_history_for_addon) {
717
-            //it exists, so this isn't a completely new install
718
-            //check if this version already in that list of previously installed versions
719
-            if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
720
-                //it a version we haven't seen before
721
-                if ($version_is_higher === 1) {
722
-                    $req_type = EE_System::req_type_upgrade;
723
-                } else {
724
-                    $req_type = EE_System::req_type_downgrade;
725
-                }
726
-                delete_option($activation_indicator_option_name);
727
-            } else {
728
-                // its not an update. maybe a reactivation?
729
-                if (get_option($activation_indicator_option_name, false)) {
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, but it's an activation. must be a reactivation
734
-                        $req_type = EE_System::req_type_reactivation;
735
-                    } else {//$version_is_higher === 1
736
-                        $req_type = EE_System::req_type_upgrade;
737
-                    }
738
-                    delete_option($activation_indicator_option_name);
739
-                } else {
740
-                    //we've seen this version before and the activation indicate doesn't show it was just activated
741
-                    if ($version_is_higher === -1) {
742
-                        $req_type = EE_System::req_type_downgrade;
743
-                    } elseif ($version_is_higher === 0) {
744
-                        //we've seen this version before and it's not an activation. its normal request
745
-                        $req_type = EE_System::req_type_normal;
746
-                    } else {//$version_is_higher === 1
747
-                        $req_type = EE_System::req_type_upgrade;
748
-                    }
749
-                }
750
-            }
751
-        } else {
752
-            //brand new install
753
-            $req_type = EE_System::req_type_new_activation;
754
-            delete_option($activation_indicator_option_name);
755
-        }
756
-        return $req_type;
757
-    }
758
-
759
-
760
-
761
-    /**
762
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
763
-     * the $activation_history_for_addon
764
-     *
765
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
766
-     *                                             sometimes containing 'unknown-date'
767
-     * @param string $version_to_upgrade_to        (current version)
768
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
769
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
770
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
771
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
772
-     */
773
-    private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
774
-    {
775
-        //find the most recently-activated version
776
-        $most_recently_active_version =
777
-            EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
778
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
779
-    }
780
-
781
-
782
-
783
-    /**
784
-     * Gets the most recently active version listed in the activation history,
785
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
786
-     *
787
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
788
-     *                                   sometimes containing 'unknown-date'
789
-     * @return string
790
-     */
791
-    private static function _get_most_recently_active_version_from_activation_history($activation_history)
792
-    {
793
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
794
-        $most_recently_active_version            = '0.0.0.dev.000';
795
-        if (is_array($activation_history)) {
796
-            foreach ($activation_history as $version => $times_activated) {
797
-                //check there is a record of when this version was activated. Otherwise,
798
-                //mark it as unknown
799
-                if (! $times_activated) {
800
-                    $times_activated = array('unknown-date');
801
-                }
802
-                if (is_string($times_activated)) {
803
-                    $times_activated = array($times_activated);
804
-                }
805
-                foreach ($times_activated as $an_activation) {
806
-                    if ($an_activation !== 'unknown-date'
807
-                        && $an_activation
808
-                           > $most_recently_active_version_activation) {
809
-                        $most_recently_active_version            = $version;
810
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
811
-                            ? '1970-01-01 00:00:00'
812
-                            : $an_activation;
813
-                    }
814
-                }
815
-            }
816
-        }
817
-        return $most_recently_active_version;
818
-    }
819
-
820
-
821
-
822
-    /**
823
-     * This redirects to the about EE page after activation
824
-     *
825
-     * @return void
826
-     */
827
-    public function redirect_to_about_ee()
828
-    {
829
-        $notices = EE_Error::get_notices(false);
830
-        //if current user is an admin and it's not an ajax or rest request
831
-        if (
832
-            ! isset($notices['errors'])
833
-            && $this->request->isAdmin()
834
-            && apply_filters(
835
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
836
-                $this->capabilities->current_user_can('manage_options', 'espresso_about_default')
837
-            )
838
-        ) {
839
-            $query_params = array('page' => 'espresso_about');
840
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
841
-                $query_params['new_activation'] = true;
842
-            }
843
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
844
-                $query_params['reactivation'] = true;
845
-            }
846
-            $url = add_query_arg($query_params, admin_url('admin.php'));
847
-            wp_safe_redirect($url);
848
-            exit();
849
-        }
850
-    }
851
-
852
-
853
-
854
-    /**
855
-     * load_core_configuration
856
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
857
-     * which runs during the WP 'plugins_loaded' action at priority 5
858
-     *
859
-     * @return void
860
-     * @throws ReflectionException
861
-     */
862
-    public function load_core_configuration()
863
-    {
864
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
865
-        $this->loader->getShared('EE_Load_Textdomain');
866
-        //load textdomain
867
-        EE_Load_Textdomain::load_textdomain();
868
-        // load and setup EE_Config and EE_Network_Config
869
-        $config = $this->loader->getShared('EE_Config');
870
-        $this->loader->getShared('EE_Network_Config');
871
-        // setup autoloaders
872
-        // enable logging?
873
-        if ($config->admin->use_full_logging) {
874
-            $this->loader->getShared('EE_Log');
875
-        }
876
-        // check for activation errors
877
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
878
-        if ($activation_errors) {
879
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
880
-            update_option('ee_plugin_activation_errors', false);
881
-        }
882
-        // get model names
883
-        $this->_parse_model_names();
884
-        //load caf stuff a chance to play during the activation process too.
885
-        $this->_maybe_brew_regular();
886
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
887
-    }
888
-
889
-
890
-
891
-    /**
892
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
893
-     *
894
-     * @return void
895
-     * @throws ReflectionException
896
-     */
897
-    private function _parse_model_names()
898
-    {
899
-        //get all the files in the EE_MODELS folder that end in .model.php
900
-        $models                 = glob(EE_MODELS . '*.model.php');
901
-        $model_names            = array();
902
-        $non_abstract_db_models = array();
903
-        foreach ($models as $model) {
904
-            // get model classname
905
-            $classname       = EEH_File::get_classname_from_filepath_with_standard_filename($model);
906
-            $short_name      = str_replace('EEM_', '', $classname);
907
-            $reflectionClass = new ReflectionClass($classname);
908
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
909
-                $non_abstract_db_models[ $short_name ] = $classname;
910
-            }
911
-            $model_names[ $short_name ] = $classname;
912
-        }
913
-        $this->registry->models                 = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
914
-        $this->registry->non_abstract_db_models = apply_filters(
915
-            'FHEE__EE_System__parse_implemented_model_names',
916
-            $non_abstract_db_models
917
-        );
918
-    }
919
-
920
-
921
-    /**
922
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
923
-     * that need to be setup before our EE_System launches.
924
-     *
925
-     * @return void
926
-     * @throws DomainException
927
-     * @throws InvalidArgumentException
928
-     * @throws InvalidDataTypeException
929
-     * @throws InvalidInterfaceException
930
-     * @throws InvalidClassException
931
-     * @throws InvalidFilePathException
932
-     */
933
-    private function _maybe_brew_regular()
934
-    {
935
-        /** @var Domain $domain */
936
-        $domain = DomainFactory::getShared(
937
-            new FullyQualifiedName(
938
-                'EventEspresso\core\domain\Domain'
939
-            ),
940
-            array(
941
-                new FilePath(EVENT_ESPRESSO_MAIN_FILE),
942
-                Version::fromString(espresso_version())
943
-            )
944
-        );
945
-        if ($domain->isCaffeinated()) {
946
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
947
-        }
948
-    }
949
-
950
-
951
-
952
-    /**
953
-     * register_shortcodes_modules_and_widgets
954
-     * generate lists of shortcodes and modules, then verify paths and classes
955
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
956
-     * which runs during the WP 'plugins_loaded' action at priority 7
957
-     *
958
-     * @access public
959
-     * @return void
960
-     * @throws Exception
961
-     */
962
-    public function register_shortcodes_modules_and_widgets()
963
-    {
964
-        if ($this->request->isFrontend() || $this->request->isIframe()) {
965
-            try {
966
-                // load, register, and add shortcodes the new way
967
-                $this->loader->getShared(
968
-                    'EventEspresso\core\services\shortcodes\ShortcodesManager',
969
-                    array(
970
-                        // and the old way, but we'll put it under control of the new system
971
-                        EE_Config::getLegacyShortcodesManager(),
972
-                    )
973
-                );
974
-            } catch (Exception $exception) {
975
-                new ExceptionStackTraceDisplay($exception);
976
-            }
977
-        }
978
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
979
-        // check for addons using old hook point
980
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
981
-            $this->_incompatible_addon_error();
982
-        }
983
-    }
984
-
985
-
986
-
987
-    /**
988
-     * _incompatible_addon_error
989
-     *
990
-     * @access public
991
-     * @return void
992
-     */
993
-    private function _incompatible_addon_error()
994
-    {
995
-        // get array of classes hooking into here
996
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
997
-            'AHEE__EE_System__register_shortcodes_modules_and_addons'
998
-        );
999
-        if (! empty($class_names)) {
1000
-            $msg = __(
1001
-                'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1002
-                'event_espresso'
1003
-            );
1004
-            $msg .= '<ul>';
1005
-            foreach ($class_names as $class_name) {
1006
-                $msg .= '<li><b>Event Espresso - ' . str_replace(
1007
-                        array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
1008
-                        $class_name
1009
-                    ) . '</b></li>';
1010
-            }
1011
-            $msg .= '</ul>';
1012
-            $msg .= __(
1013
-                'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1014
-                'event_espresso'
1015
-            );
1016
-            // save list of incompatible addons to wp-options for later use
1017
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
1018
-            if (is_admin()) {
1019
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1020
-            }
1021
-        }
1022
-    }
1023
-
1024
-
1025
-
1026
-    /**
1027
-     * brew_espresso
1028
-     * begins the process of setting hooks for initializing EE in the correct order
1029
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1030
-     * which runs during the WP 'plugins_loaded' action at priority 9
1031
-     *
1032
-     * @return void
1033
-     */
1034
-    public function brew_espresso()
1035
-    {
1036
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
1037
-        // load some final core systems
1038
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
1039
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1040
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
1041
-        add_action('init', array($this, 'load_controllers'), 7);
1042
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
1043
-        add_action('init', array($this, 'initialize'), 10);
1044
-        add_action('init', array($this, 'initialize_last'), 100);
1045
-        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1046
-            // pew pew pew
1047
-            $this->loader->getShared('EE_PUE');
1048
-            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1049
-        }
1050
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
1051
-    }
1052
-
1053
-
1054
-
1055
-    /**
1056
-     *    set_hooks_for_core
1057
-     *
1058
-     * @access public
1059
-     * @return    void
1060
-     * @throws EE_Error
1061
-     */
1062
-    public function set_hooks_for_core()
1063
-    {
1064
-        $this->_deactivate_incompatible_addons();
1065
-        do_action('AHEE__EE_System__set_hooks_for_core');
1066
-        $this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1067
-        //caps need to be initialized on every request so that capability maps are set.
1068
-        //@see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1069
-        $this->registry->CAP->init_caps();
1070
-    }
1071
-
1072
-
1073
-
1074
-    /**
1075
-     * Using the information gathered in EE_System::_incompatible_addon_error,
1076
-     * deactivates any addons considered incompatible with the current version of EE
1077
-     */
1078
-    private function _deactivate_incompatible_addons()
1079
-    {
1080
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
1081
-        if (! empty($incompatible_addons)) {
1082
-            $active_plugins = get_option('active_plugins', array());
1083
-            foreach ($active_plugins as $active_plugin) {
1084
-                foreach ($incompatible_addons as $incompatible_addon) {
1085
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
1086
-                        unset($_GET['activate']);
1087
-                        espresso_deactivate_plugin($active_plugin);
1088
-                    }
1089
-                }
1090
-            }
1091
-        }
1092
-    }
1093
-
1094
-
1095
-
1096
-    /**
1097
-     *    perform_activations_upgrades_and_migrations
1098
-     *
1099
-     * @access public
1100
-     * @return    void
1101
-     */
1102
-    public function perform_activations_upgrades_and_migrations()
1103
-    {
1104
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1105
-    }
1106
-
1107
-
1108
-
1109
-    /**
1110
-     *    load_CPTs_and_session
1111
-     *
1112
-     * @access public
1113
-     * @return    void
1114
-     */
1115
-    public function load_CPTs_and_session()
1116
-    {
1117
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
1118
-        // register Custom Post Types
1119
-        $this->loader->getShared('EE_Register_CPTs');
1120
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1121
-    }
1122
-
1123
-
1124
-
1125
-    /**
1126
-     * load_controllers
1127
-     * this is the best place to load any additional controllers that needs access to EE core.
1128
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1129
-     * time
1130
-     *
1131
-     * @access public
1132
-     * @return void
1133
-     */
1134
-    public function load_controllers()
1135
-    {
1136
-        do_action('AHEE__EE_System__load_controllers__start');
1137
-        // let's get it started
1138
-        if (
1139
-            ! $this->maintenance_mode->level()
1140
-            && ($this->request->isFrontend() || $this->request->isFrontAjax())
1141
-        ) {
1142
-            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1143
-            $this->loader->getShared('EE_Front_Controller');
1144
-        } elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1145
-            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1146
-            $this->loader->getShared('EE_Admin');
1147
-        }
1148
-        do_action('AHEE__EE_System__load_controllers__complete');
1149
-    }
1150
-
1151
-
1152
-
1153
-    /**
1154
-     * core_loaded_and_ready
1155
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1156
-     *
1157
-     * @access public
1158
-     * @return void
1159
-     */
1160
-    public function core_loaded_and_ready()
1161
-    {
1162
-        if (
1163
-            $this->request->isAdmin()
1164
-            || $this->request->isEeAjax()
1165
-            || $this->request->isFrontend()
1166
-        ) {
1167
-            $this->loader->getShared('EE_Session');
1168
-        }
1169
-        do_action('AHEE__EE_System__core_loaded_and_ready');
1170
-        // load_espresso_template_tags
1171
-        if (
1172
-            is_readable(EE_PUBLIC . 'template_tags.php')
1173
-            && ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isFeed())
1174
-        ) {
1175
-            require_once EE_PUBLIC . 'template_tags.php';
1176
-        }
1177
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1178
-        if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1179
-            $this->loader->getShared('EventEspresso\core\services\assets\Registry');
1180
-        }
1181
-    }
1182
-
1183
-
1184
-
1185
-    /**
1186
-     * initialize
1187
-     * this is the best place to begin initializing client code
1188
-     *
1189
-     * @access public
1190
-     * @return void
1191
-     */
1192
-    public function initialize()
1193
-    {
1194
-        do_action('AHEE__EE_System__initialize');
1195
-    }
1196
-
1197
-
1198
-
1199
-    /**
1200
-     * initialize_last
1201
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1202
-     * initialize has done so
1203
-     *
1204
-     * @access public
1205
-     * @return void
1206
-     */
1207
-    public function initialize_last()
1208
-    {
1209
-        do_action('AHEE__EE_System__initialize_last');
1210
-        add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1211
-    }
1212
-
1213
-
1214
-
1215
-    /**
1216
-     * @return void
1217
-     * @throws EE_Error
1218
-     */
1219
-    public function addEspressoToolbar()
1220
-    {
1221
-        $this->loader->getShared(
1222
-            'EventEspresso\core\domain\services\admin\AdminToolBar',
1223
-            array($this->registry->CAP)
1224
-        );
1225
-    }
1226
-
1227
-
1228
-
1229
-    /**
1230
-     * do_not_cache
1231
-     * sets no cache headers and defines no cache constants for WP plugins
1232
-     *
1233
-     * @access public
1234
-     * @return void
1235
-     */
1236
-    public static function do_not_cache()
1237
-    {
1238
-        // set no cache constants
1239
-        if (! defined('DONOTCACHEPAGE')) {
1240
-            define('DONOTCACHEPAGE', true);
1241
-        }
1242
-        if (! defined('DONOTCACHCEOBJECT')) {
1243
-            define('DONOTCACHCEOBJECT', true);
1244
-        }
1245
-        if (! defined('DONOTCACHEDB')) {
1246
-            define('DONOTCACHEDB', true);
1247
-        }
1248
-        // add no cache headers
1249
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1250
-        // plus a little extra for nginx and Google Chrome
1251
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1252
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1253
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1254
-    }
1255
-
1256
-
1257
-
1258
-    /**
1259
-     *    extra_nocache_headers
1260
-     *
1261
-     * @access    public
1262
-     * @param $headers
1263
-     * @return    array
1264
-     */
1265
-    public static function extra_nocache_headers($headers)
1266
-    {
1267
-        // for NGINX
1268
-        $headers['X-Accel-Expires'] = 0;
1269
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1270
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1271
-        return $headers;
1272
-    }
1273
-
1274
-
1275
-
1276
-    /**
1277
-     *    nocache_headers
1278
-     *
1279
-     * @access    public
1280
-     * @return    void
1281
-     */
1282
-    public static function nocache_headers()
1283
-    {
1284
-        nocache_headers();
1285
-    }
1286
-
1287
-
1288
-
1289
-    /**
1290
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1291
-     * never returned with the function.
1292
-     *
1293
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1294
-     * @return array
1295
-     */
1296
-    public function remove_pages_from_wp_list_pages($exclude_array)
1297
-    {
1298
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1299
-    }
35
+	/**
36
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
37
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
38
+	 */
39
+	const req_type_normal = 0;
40
+
41
+	/**
42
+	 * Indicates this is a brand new installation of EE so we should install
43
+	 * tables and default data etc
44
+	 */
45
+	const req_type_new_activation = 1;
46
+
47
+	/**
48
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
49
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
50
+	 * and that default data is setup too
51
+	 */
52
+	const req_type_reactivation = 2;
53
+
54
+	/**
55
+	 * indicates that EE has been upgraded since its previous request.
56
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
57
+	 */
58
+	const req_type_upgrade = 3;
59
+
60
+	/**
61
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
62
+	 */
63
+	const req_type_downgrade = 4;
64
+
65
+	/**
66
+	 * @deprecated since version 4.6.0.dev.006
67
+	 * Now whenever a new_activation is detected the request type is still just
68
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
69
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
70
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
71
+	 * (Specifically, when the migration manager indicates migrations are finished
72
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
73
+	 */
74
+	const req_type_activation_but_not_installed = 5;
75
+
76
+	/**
77
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
78
+	 */
79
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
80
+
81
+
82
+	/**
83
+	 * @var EE_System $_instance
84
+	 */
85
+	private static $_instance;
86
+
87
+	/**
88
+	 * @var EE_Registry $registry
89
+	 */
90
+	private $registry;
91
+
92
+	/**
93
+	 * @var LoaderInterface $loader
94
+	 */
95
+	private $loader;
96
+
97
+	/**
98
+	 * @var EE_Capabilities $capabilities
99
+	 */
100
+	private $capabilities;
101
+
102
+	/**
103
+	 * @var RequestInterface $request
104
+	 */
105
+	private $request;
106
+
107
+	/**
108
+	 * @var EE_Maintenance_Mode $maintenance_mode
109
+	 */
110
+	private $maintenance_mode;
111
+
112
+	/**
113
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
114
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
115
+	 *
116
+	 * @var int $_req_type
117
+	 */
118
+	private $_req_type;
119
+
120
+	/**
121
+	 * Whether or not there was a non-micro version change in EE core version during this request
122
+	 *
123
+	 * @var boolean $_major_version_change
124
+	 */
125
+	private $_major_version_change = false;
126
+
127
+	/**
128
+	 * A Context DTO dedicated solely to identifying the current request type.
129
+	 *
130
+	 * @var RequestTypeContextCheckerInterface $request_type
131
+	 */
132
+	private $request_type;
133
+
134
+
135
+
136
+	/**
137
+	 * @singleton method used to instantiate class object
138
+	 * @param EE_Registry|null         $registry
139
+	 * @param LoaderInterface|null     $loader
140
+	 * @param RequestInterface|null          $request
141
+	 * @param EE_Maintenance_Mode|null $maintenance_mode
142
+	 * @return EE_System
143
+	 */
144
+	public static function instance(
145
+		EE_Registry $registry = null,
146
+		LoaderInterface $loader = null,
147
+		RequestInterface $request = null,
148
+		EE_Maintenance_Mode $maintenance_mode = null
149
+	) {
150
+		// check if class object is instantiated
151
+		if (! self::$_instance instanceof EE_System) {
152
+			self::$_instance = new self($registry, $loader, $request, $maintenance_mode);
153
+		}
154
+		return self::$_instance;
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * resets the instance and returns it
161
+	 *
162
+	 * @return EE_System
163
+	 */
164
+	public static function reset()
165
+	{
166
+		self::$_instance->_req_type = null;
167
+		//make sure none of the old hooks are left hanging around
168
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
169
+		//we need to reset the migration manager in order for it to detect DMSs properly
170
+		EE_Data_Migration_Manager::reset();
171
+		self::instance()->detect_activations_or_upgrades();
172
+		self::instance()->perform_activations_upgrades_and_migrations();
173
+		return self::instance();
174
+	}
175
+
176
+
177
+
178
+	/**
179
+	 * sets hooks for running rest of system
180
+	 * provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
181
+	 * starting EE Addons from any other point may lead to problems
182
+	 *
183
+	 * @param EE_Registry         $registry
184
+	 * @param LoaderInterface     $loader
185
+	 * @param RequestInterface          $request
186
+	 * @param EE_Maintenance_Mode $maintenance_mode
187
+	 */
188
+	private function __construct(
189
+		EE_Registry $registry,
190
+		LoaderInterface $loader,
191
+		RequestInterface $request,
192
+		EE_Maintenance_Mode $maintenance_mode
193
+	) {
194
+		$this->registry         = $registry;
195
+		$this->loader           = $loader;
196
+		$this->request          = $request;
197
+		$this->maintenance_mode = $maintenance_mode;
198
+		do_action('AHEE__EE_System__construct__begin', $this);
199
+		add_action(
200
+			'AHEE__EE_Bootstrap__load_espresso_addons',
201
+			array($this, 'loadCapabilities'),
202
+			5
203
+		);
204
+		add_action(
205
+			'AHEE__EE_Bootstrap__load_espresso_addons',
206
+			array($this, 'loadCommandBus'),
207
+			7
208
+		);
209
+		add_action(
210
+			'AHEE__EE_Bootstrap__load_espresso_addons',
211
+			array($this, 'loadPluginApi'),
212
+			9
213
+		);
214
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
215
+		add_action(
216
+			'AHEE__EE_Bootstrap__load_espresso_addons',
217
+			array($this, 'load_espresso_addons')
218
+		);
219
+		// when an ee addon is activated, we want to call the core hook(s) again
220
+		// because the newly-activated addon didn't get a chance to run at all
221
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
222
+		// detect whether install or upgrade
223
+		add_action(
224
+			'AHEE__EE_Bootstrap__detect_activations_or_upgrades',
225
+			array($this, 'detect_activations_or_upgrades'),
226
+			3
227
+		);
228
+		// load EE_Config, EE_Textdomain, etc
229
+		add_action(
230
+			'AHEE__EE_Bootstrap__load_core_configuration',
231
+			array($this, 'load_core_configuration'),
232
+			5
233
+		);
234
+		// load EE_Config, EE_Textdomain, etc
235
+		add_action(
236
+			'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
237
+			array($this, 'register_shortcodes_modules_and_widgets'),
238
+			7
239
+		);
240
+		// you wanna get going? I wanna get going... let's get going!
241
+		add_action(
242
+			'AHEE__EE_Bootstrap__brew_espresso',
243
+			array($this, 'brew_espresso'),
244
+			9
245
+		);
246
+		//other housekeeping
247
+		//exclude EE critical pages from wp_list_pages
248
+		add_filter(
249
+			'wp_list_pages_excludes',
250
+			array($this, 'remove_pages_from_wp_list_pages'),
251
+			10
252
+		);
253
+		// ALL EE Addons should use the following hook point to attach their initial setup too
254
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
255
+		do_action('AHEE__EE_System__construct__complete', $this);
256
+	}
257
+
258
+
259
+	/**
260
+	 * load and setup EE_Capabilities
261
+	 *
262
+	 * @return void
263
+	 * @throws EE_Error
264
+	 */
265
+	public function loadCapabilities()
266
+	{
267
+		$this->capabilities = $this->loader->getShared('EE_Capabilities');
268
+		add_action(
269
+			'AHEE__EE_Capabilities__init_caps__before_initialization',
270
+			function ()
271
+			{
272
+				LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager');
273
+			}
274
+		);
275
+	}
276
+
277
+
278
+
279
+	/**
280
+	 * create and cache the CommandBus, and also add middleware
281
+	 * The CapChecker middleware requires the use of EE_Capabilities
282
+	 * which is why we need to load the CommandBus after Caps are set up
283
+	 *
284
+	 * @return void
285
+	 * @throws EE_Error
286
+	 */
287
+	public function loadCommandBus()
288
+	{
289
+		$this->loader->getShared(
290
+			'CommandBusInterface',
291
+			array(
292
+				null,
293
+				apply_filters(
294
+					'FHEE__EE_Load_Espresso_Core__handle_request__CommandBus_middleware',
295
+					array(
296
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\CapChecker'),
297
+						$this->loader->getShared('EventEspresso\core\services\commands\middleware\AddActionHook'),
298
+					)
299
+				),
300
+			)
301
+		);
302
+	}
303
+
304
+
305
+
306
+	/**
307
+	 * @return void
308
+	 * @throws EE_Error
309
+	 */
310
+	public function loadPluginApi()
311
+	{
312
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
313
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
314
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
315
+		$this->loader->getShared('EE_Request_Handler');
316
+	}
317
+
318
+
319
+	/**
320
+	 * @param string $addon_name
321
+	 * @param string $version_constant
322
+	 * @param string $min_version_required
323
+	 * @param string $load_callback
324
+	 * @param string $plugin_file_constant
325
+	 * @return void
326
+	 */
327
+	private function deactivateIncompatibleAddon(
328
+		$addon_name,
329
+		$version_constant,
330
+		$min_version_required,
331
+		$load_callback,
332
+		$plugin_file_constant
333
+	) {
334
+		if (! defined($version_constant)) {
335
+			return;
336
+		}
337
+		$addon_version = constant($version_constant);
338
+		if ($addon_version && version_compare($addon_version, $min_version_required, '<')) {
339
+			remove_action('AHEE__EE_System__load_espresso_addons', $load_callback);
340
+			if (! function_exists('deactivate_plugins')) {
341
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
342
+			}
343
+			deactivate_plugins(plugin_basename(constant($plugin_file_constant)));
344
+			unset($_GET['activate'], $_REQUEST['activate'], $_GET['activate-multi'], $_REQUEST['activate-multi']);
345
+			EE_Error::add_error(
346
+				sprintf(
347
+					esc_html__(
348
+						'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.',
349
+						'event_espresso'
350
+					),
351
+					$addon_name,
352
+					$min_version_required
353
+				),
354
+				__FILE__, __FUNCTION__ . "({$addon_name})", __LINE__
355
+			);
356
+			EE_Error::get_notices(false, true);
357
+		}
358
+	}
359
+
360
+
361
+	/**
362
+	 * load_espresso_addons
363
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
364
+	 * this is hooked into both:
365
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
366
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
367
+	 *    and the WP 'activate_plugin' hook point
368
+	 *
369
+	 * @access public
370
+	 * @return void
371
+	 */
372
+	public function load_espresso_addons()
373
+	{
374
+		$this->deactivateIncompatibleAddon(
375
+			'Wait Lists',
376
+			'EE_WAIT_LISTS_VERSION',
377
+			'1.0.0.beta.074',
378
+			'load_espresso_wait_lists',
379
+			'EE_WAIT_LISTS_PLUGIN_FILE'
380
+		);
381
+		$this->deactivateIncompatibleAddon(
382
+			'Automated Upcoming Event Notifications',
383
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_VERSION',
384
+			'1.0.0.beta.091',
385
+			'load_espresso_automated_upcoming_event_notification',
386
+			'EE_AUTOMATED_UPCOMING_EVENT_NOTIFICATION_PLUGIN_FILE'
387
+		);
388
+		do_action('AHEE__EE_System__load_espresso_addons');
389
+		//if the WP API basic auth plugin isn't already loaded, load it now.
390
+		//We want it for mobile apps. Just include the entire plugin
391
+		//also, don't load the basic auth when a plugin is getting activated, because
392
+		//it could be the basic auth plugin, and it doesn't check if its methods are already defined
393
+		//and causes a fatal error
394
+		if (
395
+			$this->request->getRequestParam('activate') !== 'true'
396
+			&& ! function_exists('json_basic_auth_handler')
397
+			&& ! function_exists('json_basic_auth_error')
398
+			&& ! in_array(
399
+				$this->request->getRequestParam('action'),
400
+				array('activate', 'activate-selected'),
401
+				true
402
+			)
403
+		) {
404
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
405
+		}
406
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
407
+	}
408
+
409
+
410
+
411
+	/**
412
+	 * detect_activations_or_upgrades
413
+	 * Checks for activation or upgrade of core first;
414
+	 * then also checks if any registered addons have been activated or upgraded
415
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
416
+	 * which runs during the WP 'plugins_loaded' action at priority 3
417
+	 *
418
+	 * @access public
419
+	 * @return void
420
+	 */
421
+	public function detect_activations_or_upgrades()
422
+	{
423
+		//first off: let's make sure to handle core
424
+		$this->detect_if_activation_or_upgrade();
425
+		foreach ($this->registry->addons as $addon) {
426
+			if ($addon instanceof EE_Addon) {
427
+				//detect teh request type for that addon
428
+				$addon->detect_activation_or_upgrade();
429
+			}
430
+		}
431
+	}
432
+
433
+
434
+
435
+	/**
436
+	 * detect_if_activation_or_upgrade
437
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
438
+	 * and either setting up the DB or setting up maintenance mode etc.
439
+	 *
440
+	 * @access public
441
+	 * @return void
442
+	 */
443
+	public function detect_if_activation_or_upgrade()
444
+	{
445
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
446
+		// check if db has been updated, or if its a brand-new installation
447
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
448
+		$request_type       = $this->detect_req_type($espresso_db_update);
449
+		//EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
450
+		switch ($request_type) {
451
+			case EE_System::req_type_new_activation:
452
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
453
+				$this->_handle_core_version_change($espresso_db_update);
454
+				break;
455
+			case EE_System::req_type_reactivation:
456
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
457
+				$this->_handle_core_version_change($espresso_db_update);
458
+				break;
459
+			case EE_System::req_type_upgrade:
460
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
461
+				//migrations may be required now that we've upgraded
462
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
463
+				$this->_handle_core_version_change($espresso_db_update);
464
+				//				echo "done upgrade";die;
465
+				break;
466
+			case EE_System::req_type_downgrade:
467
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
468
+				//its possible migrations are no longer required
469
+				$this->maintenance_mode->set_maintenance_mode_if_db_old();
470
+				$this->_handle_core_version_change($espresso_db_update);
471
+				break;
472
+			case EE_System::req_type_normal:
473
+			default:
474
+				break;
475
+		}
476
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
477
+	}
478
+
479
+
480
+
481
+	/**
482
+	 * Updates the list of installed versions and sets hooks for
483
+	 * initializing the database later during the request
484
+	 *
485
+	 * @param array $espresso_db_update
486
+	 */
487
+	private function _handle_core_version_change($espresso_db_update)
488
+	{
489
+		$this->update_list_of_installed_versions($espresso_db_update);
490
+		//get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
491
+		add_action(
492
+			'AHEE__EE_System__perform_activations_upgrades_and_migrations',
493
+			array($this, 'initialize_db_if_no_migrations_required')
494
+		);
495
+	}
496
+
497
+
498
+
499
+	/**
500
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
501
+	 * information about what versions of EE have been installed and activated,
502
+	 * NOT necessarily the state of the database
503
+	 *
504
+	 * @param mixed $espresso_db_update           the value of the WordPress option.
505
+	 *                                            If not supplied, fetches it from the options table
506
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
507
+	 */
508
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
509
+	{
510
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
511
+		if (! $espresso_db_update) {
512
+			$espresso_db_update = get_option('espresso_db_update');
513
+		}
514
+		// check that option is an array
515
+		if (! is_array($espresso_db_update)) {
516
+			// if option is FALSE, then it never existed
517
+			if ($espresso_db_update === false) {
518
+				// make $espresso_db_update an array and save option with autoload OFF
519
+				$espresso_db_update = array();
520
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
521
+			} else {
522
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
523
+				$espresso_db_update = array($espresso_db_update => array());
524
+				update_option('espresso_db_update', $espresso_db_update);
525
+			}
526
+		} else {
527
+			$corrected_db_update = array();
528
+			//if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
529
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
530
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
531
+					//the key is an int, and the value IS NOT an array
532
+					//so it must be numerically-indexed, where values are versions installed...
533
+					//fix it!
534
+					$version_string                         = $should_be_array;
535
+					$corrected_db_update[ $version_string ] = array('unknown-date');
536
+				} else {
537
+					//ok it checks out
538
+					$corrected_db_update[ $should_be_version_string ] = $should_be_array;
539
+				}
540
+			}
541
+			$espresso_db_update = $corrected_db_update;
542
+			update_option('espresso_db_update', $espresso_db_update);
543
+		}
544
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
545
+		return $espresso_db_update;
546
+	}
547
+
548
+
549
+
550
+	/**
551
+	 * Does the traditional work of setting up the plugin's database and adding default data.
552
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
553
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
554
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
555
+	 * so that it will be done when migrations are finished
556
+	 *
557
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
558
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
559
+	 *                                       This is a resource-intensive job
560
+	 *                                       so we prefer to only do it when necessary
561
+	 * @return void
562
+	 * @throws EE_Error
563
+	 */
564
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
565
+	{
566
+		$request_type = $this->detect_req_type();
567
+		//only initialize system if we're not in maintenance mode.
568
+		if ($this->maintenance_mode->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
569
+			update_option('ee_flush_rewrite_rules', true);
570
+			if ($verify_schema) {
571
+				EEH_Activation::initialize_db_and_folders();
572
+			}
573
+			EEH_Activation::initialize_db_content();
574
+			EEH_Activation::system_initialization();
575
+			if ($initialize_addons_too) {
576
+				$this->initialize_addons();
577
+			}
578
+		} else {
579
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
580
+		}
581
+		if ($request_type === EE_System::req_type_new_activation
582
+			|| $request_type === EE_System::req_type_reactivation
583
+			|| (
584
+				$request_type === EE_System::req_type_upgrade
585
+				&& $this->is_major_version_change()
586
+			)
587
+		) {
588
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
589
+		}
590
+	}
591
+
592
+
593
+
594
+	/**
595
+	 * Initializes the db for all registered addons
596
+	 *
597
+	 * @throws EE_Error
598
+	 */
599
+	public function initialize_addons()
600
+	{
601
+		//foreach registered addon, make sure its db is up-to-date too
602
+		foreach ($this->registry->addons as $addon) {
603
+			if ($addon instanceof EE_Addon) {
604
+				$addon->initialize_db_if_no_migrations_required();
605
+			}
606
+		}
607
+	}
608
+
609
+
610
+
611
+	/**
612
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
613
+	 *
614
+	 * @param    array  $version_history
615
+	 * @param    string $current_version_to_add version to be added to the version history
616
+	 * @return    boolean success as to whether or not this option was changed
617
+	 */
618
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
619
+	{
620
+		if (! $version_history) {
621
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
622
+		}
623
+		if ($current_version_to_add === null) {
624
+			$current_version_to_add = espresso_version();
625
+		}
626
+		$version_history[ $current_version_to_add ][] = date('Y-m-d H:i:s', time());
627
+		// re-save
628
+		return update_option('espresso_db_update', $version_history);
629
+	}
630
+
631
+
632
+
633
+	/**
634
+	 * Detects if the current version indicated in the has existed in the list of
635
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
636
+	 *
637
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
638
+	 *                                  If not supplied, fetches it from the options table.
639
+	 *                                  Also, caches its result so later parts of the code can also know whether
640
+	 *                                  there's been an update or not. This way we can add the current version to
641
+	 *                                  espresso_db_update, but still know if this is a new install or not
642
+	 * @return int one of the constants on EE_System::req_type_
643
+	 */
644
+	public function detect_req_type($espresso_db_update = null)
645
+	{
646
+		if ($this->_req_type === null) {
647
+			$espresso_db_update          = ! empty($espresso_db_update)
648
+				? $espresso_db_update
649
+				: $this->fix_espresso_db_upgrade_option();
650
+			$this->_req_type             = EE_System::detect_req_type_given_activation_history(
651
+				$espresso_db_update,
652
+				'ee_espresso_activation', espresso_version()
653
+			);
654
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
655
+			$this->request->setIsActivation($this->_req_type !== EE_System::req_type_normal);
656
+		}
657
+		return $this->_req_type;
658
+	}
659
+
660
+
661
+
662
+	/**
663
+	 * Returns whether or not there was a non-micro version change (ie, change in either
664
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
665
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
666
+	 *
667
+	 * @param $activation_history
668
+	 * @return bool
669
+	 */
670
+	private function _detect_major_version_change($activation_history)
671
+	{
672
+		$previous_version       = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
673
+		$previous_version_parts = explode('.', $previous_version);
674
+		$current_version_parts  = explode('.', espresso_version());
675
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
676
+			   && ($previous_version_parts[0] !== $current_version_parts[0]
677
+				   || $previous_version_parts[1] !== $current_version_parts[1]
678
+			   );
679
+	}
680
+
681
+
682
+
683
+	/**
684
+	 * Returns true if either the major or minor version of EE changed during this request.
685
+	 * 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
686
+	 *
687
+	 * @return bool
688
+	 */
689
+	public function is_major_version_change()
690
+	{
691
+		return $this->_major_version_change;
692
+	}
693
+
694
+
695
+
696
+	/**
697
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
698
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
699
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
700
+	 * just activated to (for core that will always be espresso_version())
701
+	 *
702
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
703
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
704
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
705
+	 *                                                 indicate that this plugin was just activated
706
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
707
+	 *                                                 espresso_version())
708
+	 * @return int one of the constants on EE_System::req_type_*
709
+	 */
710
+	public static function detect_req_type_given_activation_history(
711
+		$activation_history_for_addon,
712
+		$activation_indicator_option_name,
713
+		$version_to_upgrade_to
714
+	) {
715
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
716
+		if ($activation_history_for_addon) {
717
+			//it exists, so this isn't a completely new install
718
+			//check if this version already in that list of previously installed versions
719
+			if (! isset($activation_history_for_addon[ $version_to_upgrade_to ])) {
720
+				//it a version we haven't seen before
721
+				if ($version_is_higher === 1) {
722
+					$req_type = EE_System::req_type_upgrade;
723
+				} else {
724
+					$req_type = EE_System::req_type_downgrade;
725
+				}
726
+				delete_option($activation_indicator_option_name);
727
+			} else {
728
+				// its not an update. maybe a reactivation?
729
+				if (get_option($activation_indicator_option_name, false)) {
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, but it's an activation. must be a reactivation
734
+						$req_type = EE_System::req_type_reactivation;
735
+					} else {//$version_is_higher === 1
736
+						$req_type = EE_System::req_type_upgrade;
737
+					}
738
+					delete_option($activation_indicator_option_name);
739
+				} else {
740
+					//we've seen this version before and the activation indicate doesn't show it was just activated
741
+					if ($version_is_higher === -1) {
742
+						$req_type = EE_System::req_type_downgrade;
743
+					} elseif ($version_is_higher === 0) {
744
+						//we've seen this version before and it's not an activation. its normal request
745
+						$req_type = EE_System::req_type_normal;
746
+					} else {//$version_is_higher === 1
747
+						$req_type = EE_System::req_type_upgrade;
748
+					}
749
+				}
750
+			}
751
+		} else {
752
+			//brand new install
753
+			$req_type = EE_System::req_type_new_activation;
754
+			delete_option($activation_indicator_option_name);
755
+		}
756
+		return $req_type;
757
+	}
758
+
759
+
760
+
761
+	/**
762
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
763
+	 * the $activation_history_for_addon
764
+	 *
765
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
766
+	 *                                             sometimes containing 'unknown-date'
767
+	 * @param string $version_to_upgrade_to        (current version)
768
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
769
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
770
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
771
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
772
+	 */
773
+	private static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
774
+	{
775
+		//find the most recently-activated version
776
+		$most_recently_active_version =
777
+			EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
778
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
779
+	}
780
+
781
+
782
+
783
+	/**
784
+	 * Gets the most recently active version listed in the activation history,
785
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
786
+	 *
787
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
788
+	 *                                   sometimes containing 'unknown-date'
789
+	 * @return string
790
+	 */
791
+	private static function _get_most_recently_active_version_from_activation_history($activation_history)
792
+	{
793
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
794
+		$most_recently_active_version            = '0.0.0.dev.000';
795
+		if (is_array($activation_history)) {
796
+			foreach ($activation_history as $version => $times_activated) {
797
+				//check there is a record of when this version was activated. Otherwise,
798
+				//mark it as unknown
799
+				if (! $times_activated) {
800
+					$times_activated = array('unknown-date');
801
+				}
802
+				if (is_string($times_activated)) {
803
+					$times_activated = array($times_activated);
804
+				}
805
+				foreach ($times_activated as $an_activation) {
806
+					if ($an_activation !== 'unknown-date'
807
+						&& $an_activation
808
+						   > $most_recently_active_version_activation) {
809
+						$most_recently_active_version            = $version;
810
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
811
+							? '1970-01-01 00:00:00'
812
+							: $an_activation;
813
+					}
814
+				}
815
+			}
816
+		}
817
+		return $most_recently_active_version;
818
+	}
819
+
820
+
821
+
822
+	/**
823
+	 * This redirects to the about EE page after activation
824
+	 *
825
+	 * @return void
826
+	 */
827
+	public function redirect_to_about_ee()
828
+	{
829
+		$notices = EE_Error::get_notices(false);
830
+		//if current user is an admin and it's not an ajax or rest request
831
+		if (
832
+			! isset($notices['errors'])
833
+			&& $this->request->isAdmin()
834
+			&& apply_filters(
835
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
836
+				$this->capabilities->current_user_can('manage_options', 'espresso_about_default')
837
+			)
838
+		) {
839
+			$query_params = array('page' => 'espresso_about');
840
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
841
+				$query_params['new_activation'] = true;
842
+			}
843
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
844
+				$query_params['reactivation'] = true;
845
+			}
846
+			$url = add_query_arg($query_params, admin_url('admin.php'));
847
+			wp_safe_redirect($url);
848
+			exit();
849
+		}
850
+	}
851
+
852
+
853
+
854
+	/**
855
+	 * load_core_configuration
856
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
857
+	 * which runs during the WP 'plugins_loaded' action at priority 5
858
+	 *
859
+	 * @return void
860
+	 * @throws ReflectionException
861
+	 */
862
+	public function load_core_configuration()
863
+	{
864
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
865
+		$this->loader->getShared('EE_Load_Textdomain');
866
+		//load textdomain
867
+		EE_Load_Textdomain::load_textdomain();
868
+		// load and setup EE_Config and EE_Network_Config
869
+		$config = $this->loader->getShared('EE_Config');
870
+		$this->loader->getShared('EE_Network_Config');
871
+		// setup autoloaders
872
+		// enable logging?
873
+		if ($config->admin->use_full_logging) {
874
+			$this->loader->getShared('EE_Log');
875
+		}
876
+		// check for activation errors
877
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
878
+		if ($activation_errors) {
879
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
880
+			update_option('ee_plugin_activation_errors', false);
881
+		}
882
+		// get model names
883
+		$this->_parse_model_names();
884
+		//load caf stuff a chance to play during the activation process too.
885
+		$this->_maybe_brew_regular();
886
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
887
+	}
888
+
889
+
890
+
891
+	/**
892
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
893
+	 *
894
+	 * @return void
895
+	 * @throws ReflectionException
896
+	 */
897
+	private function _parse_model_names()
898
+	{
899
+		//get all the files in the EE_MODELS folder that end in .model.php
900
+		$models                 = glob(EE_MODELS . '*.model.php');
901
+		$model_names            = array();
902
+		$non_abstract_db_models = array();
903
+		foreach ($models as $model) {
904
+			// get model classname
905
+			$classname       = EEH_File::get_classname_from_filepath_with_standard_filename($model);
906
+			$short_name      = str_replace('EEM_', '', $classname);
907
+			$reflectionClass = new ReflectionClass($classname);
908
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
909
+				$non_abstract_db_models[ $short_name ] = $classname;
910
+			}
911
+			$model_names[ $short_name ] = $classname;
912
+		}
913
+		$this->registry->models                 = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
914
+		$this->registry->non_abstract_db_models = apply_filters(
915
+			'FHEE__EE_System__parse_implemented_model_names',
916
+			$non_abstract_db_models
917
+		);
918
+	}
919
+
920
+
921
+	/**
922
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
923
+	 * that need to be setup before our EE_System launches.
924
+	 *
925
+	 * @return void
926
+	 * @throws DomainException
927
+	 * @throws InvalidArgumentException
928
+	 * @throws InvalidDataTypeException
929
+	 * @throws InvalidInterfaceException
930
+	 * @throws InvalidClassException
931
+	 * @throws InvalidFilePathException
932
+	 */
933
+	private function _maybe_brew_regular()
934
+	{
935
+		/** @var Domain $domain */
936
+		$domain = DomainFactory::getShared(
937
+			new FullyQualifiedName(
938
+				'EventEspresso\core\domain\Domain'
939
+			),
940
+			array(
941
+				new FilePath(EVENT_ESPRESSO_MAIN_FILE),
942
+				Version::fromString(espresso_version())
943
+			)
944
+		);
945
+		if ($domain->isCaffeinated()) {
946
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
947
+		}
948
+	}
949
+
950
+
951
+
952
+	/**
953
+	 * register_shortcodes_modules_and_widgets
954
+	 * generate lists of shortcodes and modules, then verify paths and classes
955
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
956
+	 * which runs during the WP 'plugins_loaded' action at priority 7
957
+	 *
958
+	 * @access public
959
+	 * @return void
960
+	 * @throws Exception
961
+	 */
962
+	public function register_shortcodes_modules_and_widgets()
963
+	{
964
+		if ($this->request->isFrontend() || $this->request->isIframe()) {
965
+			try {
966
+				// load, register, and add shortcodes the new way
967
+				$this->loader->getShared(
968
+					'EventEspresso\core\services\shortcodes\ShortcodesManager',
969
+					array(
970
+						// and the old way, but we'll put it under control of the new system
971
+						EE_Config::getLegacyShortcodesManager(),
972
+					)
973
+				);
974
+			} catch (Exception $exception) {
975
+				new ExceptionStackTraceDisplay($exception);
976
+			}
977
+		}
978
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
979
+		// check for addons using old hook point
980
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
981
+			$this->_incompatible_addon_error();
982
+		}
983
+	}
984
+
985
+
986
+
987
+	/**
988
+	 * _incompatible_addon_error
989
+	 *
990
+	 * @access public
991
+	 * @return void
992
+	 */
993
+	private function _incompatible_addon_error()
994
+	{
995
+		// get array of classes hooking into here
996
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook(
997
+			'AHEE__EE_System__register_shortcodes_modules_and_addons'
998
+		);
999
+		if (! empty($class_names)) {
1000
+			$msg = __(
1001
+				'The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
1002
+				'event_espresso'
1003
+			);
1004
+			$msg .= '<ul>';
1005
+			foreach ($class_names as $class_name) {
1006
+				$msg .= '<li><b>Event Espresso - ' . str_replace(
1007
+						array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
1008
+						$class_name
1009
+					) . '</b></li>';
1010
+			}
1011
+			$msg .= '</ul>';
1012
+			$msg .= __(
1013
+				'Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
1014
+				'event_espresso'
1015
+			);
1016
+			// save list of incompatible addons to wp-options for later use
1017
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
1018
+			if (is_admin()) {
1019
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1020
+			}
1021
+		}
1022
+	}
1023
+
1024
+
1025
+
1026
+	/**
1027
+	 * brew_espresso
1028
+	 * begins the process of setting hooks for initializing EE in the correct order
1029
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
1030
+	 * which runs during the WP 'plugins_loaded' action at priority 9
1031
+	 *
1032
+	 * @return void
1033
+	 */
1034
+	public function brew_espresso()
1035
+	{
1036
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
1037
+		// load some final core systems
1038
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
1039
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
1040
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
1041
+		add_action('init', array($this, 'load_controllers'), 7);
1042
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
1043
+		add_action('init', array($this, 'initialize'), 10);
1044
+		add_action('init', array($this, 'initialize_last'), 100);
1045
+		if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
1046
+			// pew pew pew
1047
+			$this->loader->getShared('EE_PUE');
1048
+			do_action('AHEE__EE_System__brew_espresso__after_pue_init');
1049
+		}
1050
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
1051
+	}
1052
+
1053
+
1054
+
1055
+	/**
1056
+	 *    set_hooks_for_core
1057
+	 *
1058
+	 * @access public
1059
+	 * @return    void
1060
+	 * @throws EE_Error
1061
+	 */
1062
+	public function set_hooks_for_core()
1063
+	{
1064
+		$this->_deactivate_incompatible_addons();
1065
+		do_action('AHEE__EE_System__set_hooks_for_core');
1066
+		$this->loader->getShared('EventEspresso\core\domain\values\session\SessionLifespan');
1067
+		//caps need to be initialized on every request so that capability maps are set.
1068
+		//@see https://events.codebasehq.com/projects/event-espresso/tickets/8674
1069
+		$this->registry->CAP->init_caps();
1070
+	}
1071
+
1072
+
1073
+
1074
+	/**
1075
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
1076
+	 * deactivates any addons considered incompatible with the current version of EE
1077
+	 */
1078
+	private function _deactivate_incompatible_addons()
1079
+	{
1080
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
1081
+		if (! empty($incompatible_addons)) {
1082
+			$active_plugins = get_option('active_plugins', array());
1083
+			foreach ($active_plugins as $active_plugin) {
1084
+				foreach ($incompatible_addons as $incompatible_addon) {
1085
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
1086
+						unset($_GET['activate']);
1087
+						espresso_deactivate_plugin($active_plugin);
1088
+					}
1089
+				}
1090
+			}
1091
+		}
1092
+	}
1093
+
1094
+
1095
+
1096
+	/**
1097
+	 *    perform_activations_upgrades_and_migrations
1098
+	 *
1099
+	 * @access public
1100
+	 * @return    void
1101
+	 */
1102
+	public function perform_activations_upgrades_and_migrations()
1103
+	{
1104
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
1105
+	}
1106
+
1107
+
1108
+
1109
+	/**
1110
+	 *    load_CPTs_and_session
1111
+	 *
1112
+	 * @access public
1113
+	 * @return    void
1114
+	 */
1115
+	public function load_CPTs_and_session()
1116
+	{
1117
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
1118
+		// register Custom Post Types
1119
+		$this->loader->getShared('EE_Register_CPTs');
1120
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
1121
+	}
1122
+
1123
+
1124
+
1125
+	/**
1126
+	 * load_controllers
1127
+	 * this is the best place to load any additional controllers that needs access to EE core.
1128
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
1129
+	 * time
1130
+	 *
1131
+	 * @access public
1132
+	 * @return void
1133
+	 */
1134
+	public function load_controllers()
1135
+	{
1136
+		do_action('AHEE__EE_System__load_controllers__start');
1137
+		// let's get it started
1138
+		if (
1139
+			! $this->maintenance_mode->level()
1140
+			&& ($this->request->isFrontend() || $this->request->isFrontAjax())
1141
+		) {
1142
+			do_action('AHEE__EE_System__load_controllers__load_front_controllers');
1143
+			$this->loader->getShared('EE_Front_Controller');
1144
+		} elseif ($this->request->isAdmin() || $this->request->isAdminAjax()) {
1145
+			do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
1146
+			$this->loader->getShared('EE_Admin');
1147
+		}
1148
+		do_action('AHEE__EE_System__load_controllers__complete');
1149
+	}
1150
+
1151
+
1152
+
1153
+	/**
1154
+	 * core_loaded_and_ready
1155
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
1156
+	 *
1157
+	 * @access public
1158
+	 * @return void
1159
+	 */
1160
+	public function core_loaded_and_ready()
1161
+	{
1162
+		if (
1163
+			$this->request->isAdmin()
1164
+			|| $this->request->isEeAjax()
1165
+			|| $this->request->isFrontend()
1166
+		) {
1167
+			$this->loader->getShared('EE_Session');
1168
+		}
1169
+		do_action('AHEE__EE_System__core_loaded_and_ready');
1170
+		// load_espresso_template_tags
1171
+		if (
1172
+			is_readable(EE_PUBLIC . 'template_tags.php')
1173
+			&& ($this->request->isFrontend() || $this->request->isIframe() || $this->request->isFeed())
1174
+		) {
1175
+			require_once EE_PUBLIC . 'template_tags.php';
1176
+		}
1177
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
1178
+		if ($this->request->isAdmin() || $this->request->isFrontend() || $this->request->isIframe()) {
1179
+			$this->loader->getShared('EventEspresso\core\services\assets\Registry');
1180
+		}
1181
+	}
1182
+
1183
+
1184
+
1185
+	/**
1186
+	 * initialize
1187
+	 * this is the best place to begin initializing client code
1188
+	 *
1189
+	 * @access public
1190
+	 * @return void
1191
+	 */
1192
+	public function initialize()
1193
+	{
1194
+		do_action('AHEE__EE_System__initialize');
1195
+	}
1196
+
1197
+
1198
+
1199
+	/**
1200
+	 * initialize_last
1201
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
1202
+	 * initialize has done so
1203
+	 *
1204
+	 * @access public
1205
+	 * @return void
1206
+	 */
1207
+	public function initialize_last()
1208
+	{
1209
+		do_action('AHEE__EE_System__initialize_last');
1210
+		add_action('admin_bar_init', array($this, 'addEspressoToolbar'));
1211
+	}
1212
+
1213
+
1214
+
1215
+	/**
1216
+	 * @return void
1217
+	 * @throws EE_Error
1218
+	 */
1219
+	public function addEspressoToolbar()
1220
+	{
1221
+		$this->loader->getShared(
1222
+			'EventEspresso\core\domain\services\admin\AdminToolBar',
1223
+			array($this->registry->CAP)
1224
+		);
1225
+	}
1226
+
1227
+
1228
+
1229
+	/**
1230
+	 * do_not_cache
1231
+	 * sets no cache headers and defines no cache constants for WP plugins
1232
+	 *
1233
+	 * @access public
1234
+	 * @return void
1235
+	 */
1236
+	public static function do_not_cache()
1237
+	{
1238
+		// set no cache constants
1239
+		if (! defined('DONOTCACHEPAGE')) {
1240
+			define('DONOTCACHEPAGE', true);
1241
+		}
1242
+		if (! defined('DONOTCACHCEOBJECT')) {
1243
+			define('DONOTCACHCEOBJECT', true);
1244
+		}
1245
+		if (! defined('DONOTCACHEDB')) {
1246
+			define('DONOTCACHEDB', true);
1247
+		}
1248
+		// add no cache headers
1249
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1250
+		// plus a little extra for nginx and Google Chrome
1251
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1252
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1253
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1254
+	}
1255
+
1256
+
1257
+
1258
+	/**
1259
+	 *    extra_nocache_headers
1260
+	 *
1261
+	 * @access    public
1262
+	 * @param $headers
1263
+	 * @return    array
1264
+	 */
1265
+	public static function extra_nocache_headers($headers)
1266
+	{
1267
+		// for NGINX
1268
+		$headers['X-Accel-Expires'] = 0;
1269
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1270
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1271
+		return $headers;
1272
+	}
1273
+
1274
+
1275
+
1276
+	/**
1277
+	 *    nocache_headers
1278
+	 *
1279
+	 * @access    public
1280
+	 * @return    void
1281
+	 */
1282
+	public static function nocache_headers()
1283
+	{
1284
+		nocache_headers();
1285
+	}
1286
+
1287
+
1288
+
1289
+	/**
1290
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1291
+	 * never returned with the function.
1292
+	 *
1293
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1294
+	 * @return array
1295
+	 */
1296
+	public function remove_pages_from_wp_list_pages($exclude_array)
1297
+	{
1298
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1299
+	}
1300 1300
 
1301 1301
 
1302 1302
 
Please login to merge, or discard this patch.
core/admin/EE_Admin.core.php 1 patch
Indentation   +915 added lines, -915 removed lines patch added patch discarded remove patch
@@ -23,458 +23,458 @@  discard block
 block discarded – undo
23 23
 final class EE_Admin implements InterminableInterface
24 24
 {
25 25
 
26
-    /**
27
-     * @var EE_Admin $_instance
28
-     */
29
-    private static $_instance;
30
-
31
-    /**
32
-     * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
33
-     */
34
-    private $persistent_admin_notice_manager;
35
-
36
-    /**
37
-     * @singleton method used to instantiate class object
38
-     * @return EE_Admin
39
-     * @throws EE_Error
40
-     */
41
-    public static function instance()
42
-    {
43
-        // check if class object is instantiated
44
-        if (! self::$_instance instanceof EE_Admin) {
45
-            self::$_instance = new self();
46
-        }
47
-        return self::$_instance;
48
-    }
49
-
50
-
51
-    /**
52
-     * @return EE_Admin
53
-     * @throws EE_Error
54
-     */
55
-    public static function reset()
56
-    {
57
-        self::$_instance = null;
58
-        return self::instance();
59
-    }
60
-
61
-
62
-    /**
63
-     * class constructor
64
-     *
65
-     * @throws EE_Error
66
-     * @throws InvalidDataTypeException
67
-     * @throws InvalidInterfaceException
68
-     * @throws InvalidArgumentException
69
-     */
70
-    protected function __construct()
71
-    {
72
-        // define global EE_Admin constants
73
-        $this->_define_all_constants();
74
-        // set autoloaders for our admin page classes based on included path information
75
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
76
-        // admin hooks
77
-        add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
78
-        // load EE_Request_Handler early
79
-        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
80
-        add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
81
-        add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
82
-        add_action('wp_loaded', array($this, 'wp_loaded'), 100);
83
-        add_action('admin_init', array($this, 'admin_init'), 100);
84
-        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
85
-        add_action('admin_notices', array($this, 'display_admin_notices'), 10);
86
-        add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
87
-        add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
88
-        add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
89
-        add_action('load-plugins.php', array($this, 'hookIntoWpPluginsPage'));
90
-        //reset Environment config (we only do this on admin page loads);
91
-        EE_Registry::instance()->CFG->environment->recheck_values();
92
-        do_action('AHEE__EE_Admin__loaded');
93
-    }
94
-
95
-
96
-
97
-    /**
98
-     * _define_all_constants
99
-     * define constants that are set globally for all admin pages
100
-     *
101
-     * @return void
102
-     */
103
-    private function _define_all_constants()
104
-    {
105
-        if (! defined('EE_ADMIN_URL')) {
106
-            define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
107
-            define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
108
-            define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
109
-            define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
110
-            define('WP_AJAX_URL', admin_url('admin-ajax.php'));
111
-        }
112
-    }
113
-
114
-
115
-    /**
116
-     * filter_plugin_actions - adds links to the Plugins page listing
117
-     *
118
-     * @param    array  $links
119
-     * @param    string $plugin
120
-     * @return    array
121
-     */
122
-    public function filter_plugin_actions($links, $plugin)
123
-    {
124
-        // set $main_file in stone
125
-        static $main_file;
126
-        // if $main_file is not set yet
127
-        if (! $main_file) {
128
-            $main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129
-        }
130
-        if ($plugin === $main_file) {
131
-            // compare current plugin to this one
132
-            if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
-                $maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
134
-                                    . ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
135
-                                    . esc_html__('Maintenance Mode Active', 'event_espresso')
136
-                                    . '</a>';
137
-                array_unshift($links, $maintenance_link);
138
-            } else {
139
-                $org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
140
-                                     . esc_html__('Settings', 'event_espresso')
141
-                                     . '</a>';
142
-                $events_link       = '<a href="admin.php?page=espresso_events">'
143
-                                     . esc_html__('Events', 'event_espresso')
144
-                                     . '</a>';
145
-                // add before other links
146
-                array_unshift($links, $org_settings_link, $events_link);
147
-            }
148
-        }
149
-        return $links;
150
-    }
151
-
152
-
153
-    /**
154
-     * _get_request
155
-     *
156
-     * @return void
157
-     * @throws EE_Error
158
-     * @throws InvalidArgumentException
159
-     * @throws InvalidDataTypeException
160
-     * @throws InvalidInterfaceException
161
-     * @throws ReflectionException
162
-     */
163
-    public function get_request()
164
-    {
165
-        EE_Registry::instance()->load_core('Request_Handler');
166
-        EE_Registry::instance()->load_core('CPT_Strategy');
167
-    }
168
-
169
-
170
-
171
-    /**
172
-     * hide_admin_pages_except_maintenance_mode
173
-     *
174
-     * @param array $admin_page_folder_names
175
-     * @return array
176
-     */
177
-    public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
178
-    {
179
-        return array(
180
-            'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
181
-            'about'       => EE_ADMIN_PAGES . 'about' . DS,
182
-            'support'     => EE_ADMIN_PAGES . 'support' . DS,
183
-        );
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
190
-     * EE_Front_Controller's init phases have run
191
-     *
192
-     * @return void
193
-     * @throws EE_Error
194
-     * @throws InvalidArgumentException
195
-     * @throws InvalidDataTypeException
196
-     * @throws InvalidInterfaceException
197
-     * @throws ReflectionException
198
-     * @throws ServiceNotFoundException
199
-     */
200
-    public function init()
201
-    {
202
-        //only enable most of the EE_Admin IF we're not in full maintenance mode
203
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
204
-            //ok so we want to enable the entire admin
205
-            $this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
206
-                'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
207
-            );
208
-            $this->persistent_admin_notice_manager->setReturnUrl(
209
-                EE_Admin_Page::add_query_args_and_nonce(
210
-                    array(
211
-                        'page'   => EE_Registry::instance()->REQ->get('page', ''),
212
-                        'action' => EE_Registry::instance()->REQ->get('action', ''),
213
-                    ),
214
-                    EE_ADMIN_URL
215
-                )
216
-            );
217
-            $this->maybeSetDatetimeWarningNotice();
218
-            //at a glance dashboard widget
219
-            add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
220
-            //filter for get_edit_post_link used on comments for custom post types
221
-            add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
222
-        }
223
-        // run the admin page factory but ONLY if we are doing an ee admin ajax request
224
-        if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
225
-            try {
226
-                //this loads the controller for the admin pages which will setup routing etc
227
-                EE_Registry::instance()->load_core('Admin_Page_Loader');
228
-            } catch (EE_Error $e) {
229
-                $e->get_error();
230
-            }
231
-        }
232
-        add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
233
-        //make sure our CPTs and custom taxonomy metaboxes get shown for first time users
234
-        add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
235
-        add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
236
-        //exclude EE critical pages from all nav menus and wp_list_pages
237
-        add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
238
-    }
239
-
240
-
241
-    /**
242
-     *    get_persistent_admin_notices
243
-     *
244
-     * @access    public
245
-     * @return void
246
-     * @throws EE_Error
247
-     * @throws InvalidArgumentException
248
-     * @throws InvalidDataTypeException
249
-     * @throws InvalidInterfaceException
250
-     */
251
-    public function maybeSetDatetimeWarningNotice()
252
-    {
253
-        //add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
254
-        //@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
255
-        //with this.  But after enough time (indeterminate at this point) we can just remove this notice.
256
-        //this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
257
-        if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
258
-            && ! get_option('timezone_string')
259
-            && EEM_Event::instance()->count() > 0
260
-        ) {
261
-            new PersistentAdminNotice(
262
-                'datetime_fix_notice',
263
-                sprintf(
264
-                    esc_html__(
265
-                        '%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
266
-                        'event_espresso'
267
-                    ),
268
-                    '<strong>',
269
-                    '</strong>',
270
-                    '<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
271
-                    '</a>',
272
-                    '<a href="' . EE_Admin_Page::add_query_args_and_nonce(
273
-                        array(
274
-                            'page' => 'espresso_maintenance_settings',
275
-                            'action' => 'datetime_tools'
276
-                        ),
277
-                        admin_url('admin.php')
278
-                    ) . '">'
279
-                ),
280
-                false,
281
-                'manage_options',
282
-                'datetime_fix_persistent_notice'
283
-            );
284
-        }
285
-    }
286
-
287
-
288
-
289
-    /**
290
-     * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
291
-     * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
292
-     * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
293
-     * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
294
-     * normal property on the post_type object.  It's found ONLY in this particular context.
295
-     *
296
-     * @param WP_Post $post_type WP post type object
297
-     * @return WP_Post
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     */
302
-    public function remove_pages_from_nav_menu($post_type)
303
-    {
304
-        //if this isn't the "pages" post type let's get out
305
-        if ($post_type->name !== 'page') {
306
-            return $post_type;
307
-        }
308
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
309
-        $post_type->_default_query = array(
310
-            'post__not_in' => $critical_pages,
311
-        );
312
-        return $post_type;
313
-    }
314
-
315
-
316
-
317
-    /**
318
-     * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
319
-     * metaboxes get shown as well
320
-     *
321
-     * @return void
322
-     */
323
-    public function enable_hidden_ee_nav_menu_metaboxes()
324
-    {
325
-        global $wp_meta_boxes, $pagenow;
326
-        if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
327
-            return;
328
-        }
329
-        $user = wp_get_current_user();
330
-        //has this been done yet?
331
-        if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
332
-            return;
333
-        }
334
-
335
-        $hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
336
-        $initial_meta_boxes = apply_filters(
337
-            'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
338
-            array(
339
-                'nav-menu-theme-locations',
340
-                'add-page',
341
-                'add-custom-links',
342
-                'add-category',
343
-                'add-espresso_events',
344
-                'add-espresso_venues',
345
-                'add-espresso_event_categories',
346
-                'add-espresso_venue_categories',
347
-                'add-post-type-post',
348
-                'add-post-type-page',
349
-            )
350
-        );
351
-
352
-        if (is_array($hidden_meta_boxes)) {
353
-            foreach ($hidden_meta_boxes as $key => $meta_box_id) {
354
-                if (in_array($meta_box_id, $initial_meta_boxes, true)) {
355
-                    unset($hidden_meta_boxes[$key]);
356
-                }
357
-            }
358
-        }
359
-        update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
360
-        update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
361
-    }
362
-
363
-
364
-
365
-    /**
366
-     * This method simply registers custom nav menu boxes for "nav_menus.php route"
367
-     * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
368
-     *
369
-     * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
370
-     *         addons etc.
371
-     * @return void
372
-     */
373
-    public function register_custom_nav_menu_boxes()
374
-    {
375
-        add_meta_box(
376
-            'add-extra-nav-menu-pages',
377
-            esc_html__('Event Espresso Pages', 'event_espresso'),
378
-            array($this, 'ee_cpt_archive_pages'),
379
-            'nav-menus',
380
-            'side',
381
-            'core'
382
-        );
383
-    }
384
-
385
-
386
-
387
-    /**
388
-     * Use this to edit the post link for our cpts so that the edit link points to the correct page.
389
-     *
390
-     * @since   4.3.0
391
-     * @param string $link the original link generated by wp
392
-     * @param int    $id   post id
393
-     * @return string  the (maybe) modified link
394
-     */
395
-    public function modify_edit_post_link($link, $id)
396
-    {
397
-        if (! $post = get_post($id)) {
398
-            return $link;
399
-        }
400
-        if ($post->post_type === 'espresso_attendees') {
401
-            $query_args = array(
402
-                'action' => 'edit_attendee',
403
-                'post'   => $id,
404
-            );
405
-            return EEH_URL::add_query_args_and_nonce(
406
-                $query_args,
407
-                admin_url('admin.php?page=espresso_registrations')
408
-            );
409
-        }
410
-        return $link;
411
-    }
412
-
413
-
414
-
415
-    public function ee_cpt_archive_pages()
416
-    {
417
-        global $nav_menu_selected_id;
418
-        $db_fields   = false;
419
-        $walker      = new Walker_Nav_Menu_Checklist($db_fields);
420
-        $current_tab = 'event-archives';
421
-        $removed_args = array(
422
-            'action',
423
-            'customlink-tab',
424
-            'edit-menu-item',
425
-            'menu-item',
426
-            'page-tab',
427
-            '_wpnonce',
428
-        );
429
-        ?>
26
+	/**
27
+	 * @var EE_Admin $_instance
28
+	 */
29
+	private static $_instance;
30
+
31
+	/**
32
+	 * @var PersistentAdminNoticeManager $persistent_admin_notice_manager
33
+	 */
34
+	private $persistent_admin_notice_manager;
35
+
36
+	/**
37
+	 * @singleton method used to instantiate class object
38
+	 * @return EE_Admin
39
+	 * @throws EE_Error
40
+	 */
41
+	public static function instance()
42
+	{
43
+		// check if class object is instantiated
44
+		if (! self::$_instance instanceof EE_Admin) {
45
+			self::$_instance = new self();
46
+		}
47
+		return self::$_instance;
48
+	}
49
+
50
+
51
+	/**
52
+	 * @return EE_Admin
53
+	 * @throws EE_Error
54
+	 */
55
+	public static function reset()
56
+	{
57
+		self::$_instance = null;
58
+		return self::instance();
59
+	}
60
+
61
+
62
+	/**
63
+	 * class constructor
64
+	 *
65
+	 * @throws EE_Error
66
+	 * @throws InvalidDataTypeException
67
+	 * @throws InvalidInterfaceException
68
+	 * @throws InvalidArgumentException
69
+	 */
70
+	protected function __construct()
71
+	{
72
+		// define global EE_Admin constants
73
+		$this->_define_all_constants();
74
+		// set autoloaders for our admin page classes based on included path information
75
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_ADMIN);
76
+		// admin hooks
77
+		add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
78
+		// load EE_Request_Handler early
79
+		add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'get_request'));
80
+		add_action('AHEE__EE_System__initialize_last', array($this, 'init'));
81
+		add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'route_admin_request'), 100, 2);
82
+		add_action('wp_loaded', array($this, 'wp_loaded'), 100);
83
+		add_action('admin_init', array($this, 'admin_init'), 100);
84
+		add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'), 20);
85
+		add_action('admin_notices', array($this, 'display_admin_notices'), 10);
86
+		add_action('network_admin_notices', array($this, 'display_admin_notices'), 10);
87
+		add_filter('pre_update_option', array($this, 'check_for_invalid_datetime_formats'), 100, 2);
88
+		add_filter('admin_footer_text', array($this, 'espresso_admin_footer'));
89
+		add_action('load-plugins.php', array($this, 'hookIntoWpPluginsPage'));
90
+		//reset Environment config (we only do this on admin page loads);
91
+		EE_Registry::instance()->CFG->environment->recheck_values();
92
+		do_action('AHEE__EE_Admin__loaded');
93
+	}
94
+
95
+
96
+
97
+	/**
98
+	 * _define_all_constants
99
+	 * define constants that are set globally for all admin pages
100
+	 *
101
+	 * @return void
102
+	 */
103
+	private function _define_all_constants()
104
+	{
105
+		if (! defined('EE_ADMIN_URL')) {
106
+			define('EE_ADMIN_URL', EE_PLUGIN_DIR_URL . 'core/admin/');
107
+			define('EE_ADMIN_PAGES_URL', EE_PLUGIN_DIR_URL . 'admin_pages/');
108
+			define('EE_ADMIN_TEMPLATE', EE_ADMIN . 'templates' . DS);
109
+			define('WP_ADMIN_PATH', ABSPATH . 'wp-admin/');
110
+			define('WP_AJAX_URL', admin_url('admin-ajax.php'));
111
+		}
112
+	}
113
+
114
+
115
+	/**
116
+	 * filter_plugin_actions - adds links to the Plugins page listing
117
+	 *
118
+	 * @param    array  $links
119
+	 * @param    string $plugin
120
+	 * @return    array
121
+	 */
122
+	public function filter_plugin_actions($links, $plugin)
123
+	{
124
+		// set $main_file in stone
125
+		static $main_file;
126
+		// if $main_file is not set yet
127
+		if (! $main_file) {
128
+			$main_file = plugin_basename(EVENT_ESPRESSO_MAIN_FILE);
129
+		}
130
+		if ($plugin === $main_file) {
131
+			// compare current plugin to this one
132
+			if (EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance) {
133
+				$maintenance_link = '<a href="admin.php?page=espresso_maintenance_settings"'
134
+									. ' title="Event Espresso is in maintenance mode.  Click this link to learn why.">'
135
+									. esc_html__('Maintenance Mode Active', 'event_espresso')
136
+									. '</a>';
137
+				array_unshift($links, $maintenance_link);
138
+			} else {
139
+				$org_settings_link = '<a href="admin.php?page=espresso_general_settings">'
140
+									 . esc_html__('Settings', 'event_espresso')
141
+									 . '</a>';
142
+				$events_link       = '<a href="admin.php?page=espresso_events">'
143
+									 . esc_html__('Events', 'event_espresso')
144
+									 . '</a>';
145
+				// add before other links
146
+				array_unshift($links, $org_settings_link, $events_link);
147
+			}
148
+		}
149
+		return $links;
150
+	}
151
+
152
+
153
+	/**
154
+	 * _get_request
155
+	 *
156
+	 * @return void
157
+	 * @throws EE_Error
158
+	 * @throws InvalidArgumentException
159
+	 * @throws InvalidDataTypeException
160
+	 * @throws InvalidInterfaceException
161
+	 * @throws ReflectionException
162
+	 */
163
+	public function get_request()
164
+	{
165
+		EE_Registry::instance()->load_core('Request_Handler');
166
+		EE_Registry::instance()->load_core('CPT_Strategy');
167
+	}
168
+
169
+
170
+
171
+	/**
172
+	 * hide_admin_pages_except_maintenance_mode
173
+	 *
174
+	 * @param array $admin_page_folder_names
175
+	 * @return array
176
+	 */
177
+	public function hide_admin_pages_except_maintenance_mode($admin_page_folder_names = array())
178
+	{
179
+		return array(
180
+			'maintenance' => EE_ADMIN_PAGES . 'maintenance' . DS,
181
+			'about'       => EE_ADMIN_PAGES . 'about' . DS,
182
+			'support'     => EE_ADMIN_PAGES . 'support' . DS,
183
+		);
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * init- should fire after shortcode, module,  addon, other plugin (default priority), and even
190
+	 * EE_Front_Controller's init phases have run
191
+	 *
192
+	 * @return void
193
+	 * @throws EE_Error
194
+	 * @throws InvalidArgumentException
195
+	 * @throws InvalidDataTypeException
196
+	 * @throws InvalidInterfaceException
197
+	 * @throws ReflectionException
198
+	 * @throws ServiceNotFoundException
199
+	 */
200
+	public function init()
201
+	{
202
+		//only enable most of the EE_Admin IF we're not in full maintenance mode
203
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
204
+			//ok so we want to enable the entire admin
205
+			$this->persistent_admin_notice_manager = LoaderFactory::getLoader()->getShared(
206
+				'EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
207
+			);
208
+			$this->persistent_admin_notice_manager->setReturnUrl(
209
+				EE_Admin_Page::add_query_args_and_nonce(
210
+					array(
211
+						'page'   => EE_Registry::instance()->REQ->get('page', ''),
212
+						'action' => EE_Registry::instance()->REQ->get('action', ''),
213
+					),
214
+					EE_ADMIN_URL
215
+				)
216
+			);
217
+			$this->maybeSetDatetimeWarningNotice();
218
+			//at a glance dashboard widget
219
+			add_filter('dashboard_glance_items', array($this, 'dashboard_glance_items'), 10);
220
+			//filter for get_edit_post_link used on comments for custom post types
221
+			add_filter('get_edit_post_link', array($this, 'modify_edit_post_link'), 10, 2);
222
+		}
223
+		// run the admin page factory but ONLY if we are doing an ee admin ajax request
224
+		if (! defined('DOING_AJAX') || EE_ADMIN_AJAX) {
225
+			try {
226
+				//this loads the controller for the admin pages which will setup routing etc
227
+				EE_Registry::instance()->load_core('Admin_Page_Loader');
228
+			} catch (EE_Error $e) {
229
+				$e->get_error();
230
+			}
231
+		}
232
+		add_filter('content_save_pre', array($this, 'its_eSpresso'), 10, 1);
233
+		//make sure our CPTs and custom taxonomy metaboxes get shown for first time users
234
+		add_action('admin_head', array($this, 'enable_hidden_ee_nav_menu_metaboxes'), 10);
235
+		add_action('admin_head', array($this, 'register_custom_nav_menu_boxes'), 10);
236
+		//exclude EE critical pages from all nav menus and wp_list_pages
237
+		add_filter('nav_menu_meta_box_object', array($this, 'remove_pages_from_nav_menu'), 10);
238
+	}
239
+
240
+
241
+	/**
242
+	 *    get_persistent_admin_notices
243
+	 *
244
+	 * @access    public
245
+	 * @return void
246
+	 * @throws EE_Error
247
+	 * @throws InvalidArgumentException
248
+	 * @throws InvalidDataTypeException
249
+	 * @throws InvalidInterfaceException
250
+	 */
251
+	public function maybeSetDatetimeWarningNotice()
252
+	{
253
+		//add dismissable notice for datetime changes.  Only valid if site does not have a timezone_string set.
254
+		//@todo This needs to stay in core for a bit to catch anyone upgrading from a version without this to a version
255
+		//with this.  But after enough time (indeterminate at this point) we can just remove this notice.
256
+		//this was added with https://events.codebasehq.com/projects/event-espresso/tickets/10626
257
+		if (apply_filters('FHEE__EE_Admin__maybeSetDatetimeWarningNotice', true)
258
+			&& ! get_option('timezone_string')
259
+			&& EEM_Event::instance()->count() > 0
260
+		) {
261
+			new PersistentAdminNotice(
262
+				'datetime_fix_notice',
263
+				sprintf(
264
+					esc_html__(
265
+						'%1$sImportant announcement related to your install of Event Espresso%2$s: There are some changes made to your site that could affect how dates display for your events and other related items with dates and times.  Read more about it %3$shere%4$s. If your dates and times are displaying incorrectly (incorrect offset), you can fix it using the tool on %5$sthis page%4$s.',
266
+						'event_espresso'
267
+					),
268
+					'<strong>',
269
+					'</strong>',
270
+					'<a href="https://eventespresso.com/2017/08/important-upcoming-changes-dates-times">',
271
+					'</a>',
272
+					'<a href="' . EE_Admin_Page::add_query_args_and_nonce(
273
+						array(
274
+							'page' => 'espresso_maintenance_settings',
275
+							'action' => 'datetime_tools'
276
+						),
277
+						admin_url('admin.php')
278
+					) . '">'
279
+				),
280
+				false,
281
+				'manage_options',
282
+				'datetime_fix_persistent_notice'
283
+			);
284
+		}
285
+	}
286
+
287
+
288
+
289
+	/**
290
+	 * this simply hooks into the nav menu setup of pages metabox and makes sure that we remove EE critical pages from
291
+	 * the list of options. the wp function "wp_nav_menu_item_post_type_meta_box" found in
292
+	 * wp-admin/includes/nav-menu.php looks for the "_default_query" property on the post_type object and it uses that
293
+	 * to override any queries found in the existing query for the given post type.  Note that _default_query is not a
294
+	 * normal property on the post_type object.  It's found ONLY in this particular context.
295
+	 *
296
+	 * @param WP_Post $post_type WP post type object
297
+	 * @return WP_Post
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 */
302
+	public function remove_pages_from_nav_menu($post_type)
303
+	{
304
+		//if this isn't the "pages" post type let's get out
305
+		if ($post_type->name !== 'page') {
306
+			return $post_type;
307
+		}
308
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
309
+		$post_type->_default_query = array(
310
+			'post__not_in' => $critical_pages,
311
+		);
312
+		return $post_type;
313
+	}
314
+
315
+
316
+
317
+	/**
318
+	 * WP by default only shows three metaboxes in "nav-menus.php" for first times users.  We want to make sure our
319
+	 * metaboxes get shown as well
320
+	 *
321
+	 * @return void
322
+	 */
323
+	public function enable_hidden_ee_nav_menu_metaboxes()
324
+	{
325
+		global $wp_meta_boxes, $pagenow;
326
+		if (! is_array($wp_meta_boxes) || $pagenow !== 'nav-menus.php') {
327
+			return;
328
+		}
329
+		$user = wp_get_current_user();
330
+		//has this been done yet?
331
+		if (get_user_option('ee_nav_menu_initialized', $user->ID)) {
332
+			return;
333
+		}
334
+
335
+		$hidden_meta_boxes  = get_user_option('metaboxhidden_nav-menus', $user->ID);
336
+		$initial_meta_boxes = apply_filters(
337
+			'FHEE__EE_Admin__enable_hidden_ee_nav_menu_boxes__initial_meta_boxes',
338
+			array(
339
+				'nav-menu-theme-locations',
340
+				'add-page',
341
+				'add-custom-links',
342
+				'add-category',
343
+				'add-espresso_events',
344
+				'add-espresso_venues',
345
+				'add-espresso_event_categories',
346
+				'add-espresso_venue_categories',
347
+				'add-post-type-post',
348
+				'add-post-type-page',
349
+			)
350
+		);
351
+
352
+		if (is_array($hidden_meta_boxes)) {
353
+			foreach ($hidden_meta_boxes as $key => $meta_box_id) {
354
+				if (in_array($meta_box_id, $initial_meta_boxes, true)) {
355
+					unset($hidden_meta_boxes[$key]);
356
+				}
357
+			}
358
+		}
359
+		update_user_option($user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes, true);
360
+		update_user_option($user->ID, 'ee_nav_menu_initialized', 1, true);
361
+	}
362
+
363
+
364
+
365
+	/**
366
+	 * This method simply registers custom nav menu boxes for "nav_menus.php route"
367
+	 * Currently EE is using this to make sure there are menu options for our CPT archive page routes.
368
+	 *
369
+	 * @todo   modify this so its more dynamic and automatic for all ee CPTs and setups and can also be hooked into by
370
+	 *         addons etc.
371
+	 * @return void
372
+	 */
373
+	public function register_custom_nav_menu_boxes()
374
+	{
375
+		add_meta_box(
376
+			'add-extra-nav-menu-pages',
377
+			esc_html__('Event Espresso Pages', 'event_espresso'),
378
+			array($this, 'ee_cpt_archive_pages'),
379
+			'nav-menus',
380
+			'side',
381
+			'core'
382
+		);
383
+	}
384
+
385
+
386
+
387
+	/**
388
+	 * Use this to edit the post link for our cpts so that the edit link points to the correct page.
389
+	 *
390
+	 * @since   4.3.0
391
+	 * @param string $link the original link generated by wp
392
+	 * @param int    $id   post id
393
+	 * @return string  the (maybe) modified link
394
+	 */
395
+	public function modify_edit_post_link($link, $id)
396
+	{
397
+		if (! $post = get_post($id)) {
398
+			return $link;
399
+		}
400
+		if ($post->post_type === 'espresso_attendees') {
401
+			$query_args = array(
402
+				'action' => 'edit_attendee',
403
+				'post'   => $id,
404
+			);
405
+			return EEH_URL::add_query_args_and_nonce(
406
+				$query_args,
407
+				admin_url('admin.php?page=espresso_registrations')
408
+			);
409
+		}
410
+		return $link;
411
+	}
412
+
413
+
414
+
415
+	public function ee_cpt_archive_pages()
416
+	{
417
+		global $nav_menu_selected_id;
418
+		$db_fields   = false;
419
+		$walker      = new Walker_Nav_Menu_Checklist($db_fields);
420
+		$current_tab = 'event-archives';
421
+		$removed_args = array(
422
+			'action',
423
+			'customlink-tab',
424
+			'edit-menu-item',
425
+			'menu-item',
426
+			'page-tab',
427
+			'_wpnonce',
428
+		);
429
+		?>
430 430
         <div id="posttype-extra-nav-menu-pages" class="posttypediv">
431 431
             <ul id="posttype-extra-nav-menu-pages-tabs" class="posttype-tabs add-menu-item-tabs">
432 432
                 <li <?php echo('event-archives' === $current_tab ? ' class="tabs"' : ''); ?>>
433 433
                     <a class="nav-tab-link" data-type="tabs-panel-posttype-extra-nav-menu-pages-event-archives"
434 434
                        href="<?php if ($nav_menu_selected_id) {
435
-                            echo esc_url(
436
-                                add_query_arg(
437
-                                    'extra-nav-menu-pages-tab',
438
-                                    'event-archives',
439
-                                    remove_query_arg($removed_args)
440
-                                )
441
-                            );
442
-                       } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
435
+							echo esc_url(
436
+								add_query_arg(
437
+									'extra-nav-menu-pages-tab',
438
+									'event-archives',
439
+									remove_query_arg($removed_args)
440
+								)
441
+							);
442
+					   } ?>#tabs-panel-posttype-extra-nav-menu-pages-event-archives">
443 443
                         <?php _e('Event Archive Pages', 'event_espresso'); ?>
444 444
                     </a>
445 445
                 </li>
446 446
             </ul><!-- .posttype-tabs -->
447 447
 
448 448
             <div id="tabs-panel-posttype-extra-nav-menu-pages-event-archives" class="tabs-panel <?php
449
-                echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
450
-                ?>">
449
+				echo('event-archives' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive');
450
+				?>">
451 451
                     <ul id="extra-nav-menu-pageschecklist-event-archives" class="categorychecklist form-no-clear">
452 452
                         <?php
453
-                        $pages          = $this->_get_extra_nav_menu_pages_items();
454
-                        $args['walker'] = $walker;
455
-                        echo walk_nav_menu_tree(
456
-                            array_map(
457
-                                array($this, '_setup_extra_nav_menu_pages_items'),
458
-                                $pages
459
-                            ),
460
-                            0,
461
-                            (object) $args
462
-                        );
463
-                        ?>
453
+						$pages          = $this->_get_extra_nav_menu_pages_items();
454
+						$args['walker'] = $walker;
455
+						echo walk_nav_menu_tree(
456
+							array_map(
457
+								array($this, '_setup_extra_nav_menu_pages_items'),
458
+								$pages
459
+							),
460
+							0,
461
+							(object) $args
462
+						);
463
+						?>
464 464
                     </ul>
465 465
                 </div><!-- /.tabs-panel -->
466 466
 
467 467
                 <p class="button-controls">
468 468
                 <span class="list-controls">
469 469
                     <a href="<?php
470
-                    echo esc_url(add_query_arg(
471
-                        array(
472
-                            'extra-nav-menu-pages-tab' => 'event-archives',
473
-                            'selectall'                => 1,
474
-                        ),
475
-                        remove_query_arg($removed_args)
476
-                    ));
477
-                    ?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
470
+					echo esc_url(add_query_arg(
471
+						array(
472
+							'extra-nav-menu-pages-tab' => 'event-archives',
473
+							'selectall'                => 1,
474
+						),
475
+						remove_query_arg($removed_args)
476
+					));
477
+					?>#posttype-extra-nav-menu-pages>" class="select-all"><?php _e('Select All'); ?></a>
478 478
                 </span>
479 479
                 <span class="add-to-menu">
480 480
                     <input type="submit"<?php wp_nav_menu_disabled_check($nav_menu_selected_id); ?>
@@ -487,486 +487,486 @@  discard block
 block discarded – undo
487 487
 
488 488
         </div><!-- /.posttypediv -->
489 489
         <?php
490
-    }
491
-
492
-
493
-    /**
494
-     * Returns an array of event archive nav items.
495
-     *
496
-     * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
497
-     *        method we use for getting the extra nav menu items
498
-     * @return array
499
-     */
500
-    private function _get_extra_nav_menu_pages_items()
501
-    {
502
-        $menuitems[] = array(
503
-            'title'       => esc_html__('Event List', 'event_espresso'),
504
-            'url'         => get_post_type_archive_link('espresso_events'),
505
-            'description' => esc_html__('Archive page for all events.', 'event_espresso'),
506
-        );
507
-        return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
508
-    }
509
-
510
-
511
-    /**
512
-     * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
513
-     * the properties and converts it to the menu item object.
514
-     *
515
-     * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
516
-     * @param $menu_item_values
517
-     * @return stdClass
518
-     */
519
-    private function _setup_extra_nav_menu_pages_items($menu_item_values)
520
-    {
521
-        $menu_item = new stdClass();
522
-        $keys      = array(
523
-            'ID'               => 0,
524
-            'db_id'            => 0,
525
-            'menu_item_parent' => 0,
526
-            'object_id'        => -1,
527
-            'post_parent'      => 0,
528
-            'type'             => 'custom',
529
-            'object'           => '',
530
-            'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
531
-            'title'            => '',
532
-            'url'              => '',
533
-            'target'           => '',
534
-            'attr_title'       => '',
535
-            'description'      => '',
536
-            'classes'          => array(),
537
-            'xfn'              => '',
538
-        );
539
-
540
-        foreach ($keys as $key => $value) {
541
-            $menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
542
-        }
543
-        return $menu_item;
544
-    }
545
-
546
-
547
-    /**
548
-     * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
549
-     * EE_Admin_Page route is called.
550
-     *
551
-     * @return void
552
-     */
553
-    public function route_admin_request()
554
-    {
555
-    }
556
-
557
-
558
-    /**
559
-     * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
560
-     *
561
-     * @return void
562
-     */
563
-    public function wp_loaded()
564
-    {
565
-    }
566
-
567
-
568
-    /**
569
-     * admin_init
570
-     *
571
-     * @return void
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws InvalidDataTypeException
575
-     * @throws InvalidInterfaceException
576
-     * @throws ReflectionException
577
-     */
578
-    public function admin_init()
579
-    {
580
-
581
-        /**
582
-         * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
583
-         * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
584
-         * - check if doing post processing.
585
-         * - check if doing post processing of one of EE CPTs
586
-         * - instantiate the corresponding EE CPT model for the post_type being processed.
587
-         */
588
-        if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
589
-            EE_Registry::instance()->load_core('Register_CPTs');
590
-            EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
591
-        }
592
-
593
-
594
-        /**
595
-         * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
596
-         * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
597
-         * Pages" tab in the EE General Settings Admin page.
598
-         * This is for user-proofing.
599
-         */
600
-        add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
601
-    }
602
-
603
-
604
-    /**
605
-     * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
606
-     *
607
-     * @param string $output Current output.
608
-     * @return string
609
-     * @throws InvalidArgumentException
610
-     * @throws InvalidDataTypeException
611
-     * @throws InvalidInterfaceException
612
-     */
613
-    public function modify_dropdown_pages($output)
614
-    {
615
-        //get critical pages
616
-        $critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
617
-
618
-        //split current output by line break for easier parsing.
619
-        $split_output = explode("\n", $output);
620
-
621
-        //loop through to remove any critical pages from the array.
622
-        foreach ($critical_pages as $page_id) {
623
-            $needle = 'value="' . $page_id . '"';
624
-            foreach ($split_output as $key => $haystack) {
625
-                if (strpos($haystack, $needle) !== false) {
626
-                    unset($split_output[$key]);
627
-                }
628
-            }
629
-        }
630
-        //replace output with the new contents
631
-        return implode("\n", $split_output);
632
-    }
633
-
634
-
635
-    /**
636
-     * enqueue all admin scripts that need loaded for admin pages
637
-     *
638
-     * @return void
639
-     */
640
-    public function enqueue_admin_scripts()
641
-    {
642
-        // this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
643
-        // Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
644
-        // calls.
645
-        wp_enqueue_script(
646
-            'ee-inject-wp',
647
-            EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
648
-            array('jquery'),
649
-            EVENT_ESPRESSO_VERSION,
650
-            true
651
-        );
652
-        // register cookie script for future dependencies
653
-        wp_register_script(
654
-            'jquery-cookie',
655
-            EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
656
-            array('jquery'),
657
-            '2.1',
658
-            true
659
-        );
660
-        //joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
661
-        // via: add_filter('FHEE_load_joyride', '__return_true' );
662
-        if (apply_filters('FHEE_load_joyride', false)) {
663
-            //joyride style
664
-            wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
665
-            wp_register_style(
666
-                'ee-joyride-css',
667
-                EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
668
-                array('joyride-css'),
669
-                EVENT_ESPRESSO_VERSION
670
-            );
671
-            wp_register_script(
672
-                'joyride-modernizr',
673
-                EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
674
-                array(),
675
-                '2.1',
676
-                true
677
-            );
678
-            //joyride JS
679
-            wp_register_script(
680
-                'jquery-joyride',
681
-                EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
682
-                array('jquery-cookie', 'joyride-modernizr'),
683
-                '2.1',
684
-                true
685
-            );
686
-            // wanna go for a joyride?
687
-            wp_enqueue_style('ee-joyride-css');
688
-            wp_enqueue_script('jquery-joyride');
689
-        }
690
-    }
691
-
692
-
693
-    /**
694
-     * display_admin_notices
695
-     *
696
-     * @return void
697
-     */
698
-    public function display_admin_notices()
699
-    {
700
-        echo EE_Error::get_notices();
701
-    }
702
-
703
-
704
-
705
-    /**
706
-     * @param array $elements
707
-     * @return array
708
-     * @throws EE_Error
709
-     * @throws InvalidArgumentException
710
-     * @throws InvalidDataTypeException
711
-     * @throws InvalidInterfaceException
712
-     */
713
-    public function dashboard_glance_items($elements)
714
-    {
715
-        $elements                        = is_array($elements) ? $elements : array($elements);
716
-        $events                          = EEM_Event::instance()->count();
717
-        $items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
718
-            array('page' => 'espresso_events'),
719
-            admin_url('admin.php')
720
-        );
721
-        $items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
722
-        $items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
723
-        $registrations                   = EEM_Registration::instance()->count(
724
-            array(
725
-                array(
726
-                    'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
727
-                ),
728
-            )
729
-        );
730
-        $items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
731
-            array('page' => 'espresso_registrations'),
732
-            admin_url('admin.php')
733
-        );
734
-        $items['registrations']['text']  = sprintf(
735
-            _n('%s Registration', '%s Registrations', $registrations),
736
-            number_format_i18n($registrations)
737
-        );
738
-        $items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
739
-
740
-        $items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
741
-
742
-        foreach ($items as $type => $item_properties) {
743
-            $elements[] = sprintf(
744
-                '<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
745
-                $item_properties['url'],
746
-                $item_properties['title'],
747
-                $item_properties['text']
748
-            );
749
-        }
750
-        return $elements;
751
-    }
752
-
753
-
754
-    /**
755
-     * check_for_invalid_datetime_formats
756
-     * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
757
-     * their selected format can be parsed by PHP
758
-     *
759
-     * @param    $value
760
-     * @param    $option
761
-     * @throws EE_Error
762
-     * @return    string
763
-     */
764
-    public function check_for_invalid_datetime_formats($value, $option)
765
-    {
766
-        // check for date_format or time_format
767
-        switch ($option) {
768
-            case 'date_format':
769
-                $date_time_format = $value . ' ' . get_option('time_format');
770
-                break;
771
-            case 'time_format':
772
-                $date_time_format = get_option('date_format') . ' ' . $value;
773
-                break;
774
-            default:
775
-                $date_time_format = false;
776
-        }
777
-        // do we have a date_time format to check ?
778
-        if ($date_time_format) {
779
-            $error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
780
-
781
-            if (is_array($error_msg)) {
782
-                $msg = '<p>'
783
-                       . sprintf(
784
-                           esc_html__(
785
-                               'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
786
-                               'event_espresso'
787
-                           ),
788
-                           date($date_time_format),
789
-                           $date_time_format
790
-                       )
791
-                       . '</p><p><ul>';
792
-
793
-
794
-                foreach ($error_msg as $error) {
795
-                    $msg .= '<li>' . $error . '</li>';
796
-                }
797
-
798
-                $msg .= '</ul></p><p>'
799
-                        . sprintf(
800
-                            esc_html__(
801
-                                '%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
802
-                                'event_espresso'
803
-                            ),
804
-                            '<span style="color:#D54E21;">',
805
-                            '</span>'
806
-                        )
807
-                        . '</p>';
808
-
809
-                // trigger WP settings error
810
-                add_settings_error(
811
-                    'date_format',
812
-                    'date_format',
813
-                    $msg
814
-                );
815
-
816
-                // set format to something valid
817
-                switch ($option) {
818
-                    case 'date_format':
819
-                        $value = 'F j, Y';
820
-                        break;
821
-                    case 'time_format':
822
-                        $value = 'g:i a';
823
-                        break;
824
-                }
825
-            }
826
-        }
827
-        return $value;
828
-    }
829
-
830
-
831
-    /**
832
-     * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
833
-     *
834
-     * @param $content
835
-     * @return    string
836
-     */
837
-    public function its_eSpresso($content)
838
-    {
839
-        return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
840
-    }
841
-
842
-
843
-    /**
844
-     * espresso_admin_footer
845
-     *
846
-     * @return    string
847
-     */
848
-    public function espresso_admin_footer()
849
-    {
850
-        return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
851
-    }
852
-
853
-
854
-    /**
855
-     * static method for registering ee admin page.
856
-     * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
857
-     *
858
-     * @since      4.3.0
859
-     * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
860
-     * @see        EE_Register_Admin_Page::register()
861
-     * @param       $page_basename
862
-     * @param       $page_path
863
-     * @param array $config
864
-     * @return void
865
-     * @throws EE_Error
866
-     */
867
-    public static function register_ee_admin_page($page_basename, $page_path, $config = array())
868
-    {
869
-        EE_Error::doing_it_wrong(
870
-            __METHOD__,
871
-            sprintf(
872
-                esc_html__(
873
-                    'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
874
-                    'event_espresso'
875
-                ),
876
-                $page_basename
877
-            ),
878
-            '4.3'
879
-        );
880
-        if (class_exists('EE_Register_Admin_Page')) {
881
-            $config['page_path'] = $page_path;
882
-        }
883
-        EE_Register_Admin_Page::register($page_basename, $config);
884
-    }
885
-
886
-
887
-    /**
888
-     * @deprecated 4.8.41
889
-     * @param  int      $post_ID
890
-     * @param  \WP_Post $post
891
-     * @return void
892
-     */
893
-    public static function parse_post_content_on_save($post_ID, $post)
894
-    {
895
-        EE_Error::doing_it_wrong(
896
-            __METHOD__,
897
-            esc_html__('Usage is deprecated', 'event_espresso'),
898
-            '4.8.41'
899
-        );
900
-    }
901
-
902
-
903
-    /**
904
-     * @deprecated 4.8.41
905
-     * @param  $option
906
-     * @param  $old_value
907
-     * @param  $value
908
-     * @return void
909
-     */
910
-    public function reset_page_for_posts_on_change($option, $old_value, $value)
911
-    {
912
-        EE_Error::doing_it_wrong(
913
-            __METHOD__,
914
-            esc_html__('Usage is deprecated', 'event_espresso'),
915
-            '4.8.41'
916
-        );
917
-    }
918
-
919
-
920
-
921
-    /**
922
-     * @deprecated 4.9.27
923
-     * @return void
924
-     */
925
-    public function get_persistent_admin_notices()
926
-    {
927
-        EE_Error::doing_it_wrong(
928
-            __METHOD__,
929
-            sprintf(
930
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
931
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
932
-            ),
933
-            '4.9.27'
934
-        );
935
-    }
936
-
937
-
938
-
939
-    /**
940
-     * @deprecated 4.9.27
941
-     * @throws InvalidInterfaceException
942
-     * @throws InvalidDataTypeException
943
-     * @throws DomainException
944
-     */
945
-    public function dismiss_ee_nag_notice_callback()
946
-    {
947
-        EE_Error::doing_it_wrong(
948
-            __METHOD__,
949
-            sprintf(
950
-                __('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
951
-                '\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
952
-            ),
953
-            '4.9.27'
954
-        );
955
-        $this->persistent_admin_notice_manager->dismissNotice();
956
-    }
957
-
958
-
959
-    /**
960
-     * Callback on load-plugins.php hook for setting up anything hooking into the wp plugins page.
961
-     * @throws InvalidArgumentException
962
-     * @throws InvalidDataTypeException
963
-     * @throws InvalidInterfaceException
964
-     */
965
-    public function hookIntoWpPluginsPage()
966
-    {
967
-        LoaderFactory::getLoader()->getShared('EventEspresso\core\domain\services\admin\ExitModal');
968
-        LoaderFactory::getLoader()
969
-                     ->getShared('EventEspresso\core\domain\services\admin\PluginUpsells')
970
-                     ->decafUpsells();
971
-    }
490
+	}
491
+
492
+
493
+	/**
494
+	 * Returns an array of event archive nav items.
495
+	 *
496
+	 * @todo  for now this method is just in place so when it gets abstracted further we can substitute in whatever
497
+	 *        method we use for getting the extra nav menu items
498
+	 * @return array
499
+	 */
500
+	private function _get_extra_nav_menu_pages_items()
501
+	{
502
+		$menuitems[] = array(
503
+			'title'       => esc_html__('Event List', 'event_espresso'),
504
+			'url'         => get_post_type_archive_link('espresso_events'),
505
+			'description' => esc_html__('Archive page for all events.', 'event_espresso'),
506
+		);
507
+		return apply_filters('FHEE__EE_Admin__get_extra_nav_menu_pages_items', $menuitems);
508
+	}
509
+
510
+
511
+	/**
512
+	 * Setup nav menu walker item for usage in the event archive nav menu metabox.  It receives a menu_item array with
513
+	 * the properties and converts it to the menu item object.
514
+	 *
515
+	 * @see wp_setup_nav_menu_item() in wp-includes/nav-menu.php
516
+	 * @param $menu_item_values
517
+	 * @return stdClass
518
+	 */
519
+	private function _setup_extra_nav_menu_pages_items($menu_item_values)
520
+	{
521
+		$menu_item = new stdClass();
522
+		$keys      = array(
523
+			'ID'               => 0,
524
+			'db_id'            => 0,
525
+			'menu_item_parent' => 0,
526
+			'object_id'        => -1,
527
+			'post_parent'      => 0,
528
+			'type'             => 'custom',
529
+			'object'           => '',
530
+			'type_label'       => esc_html__('Extra Nav Menu Item', 'event_espresso'),
531
+			'title'            => '',
532
+			'url'              => '',
533
+			'target'           => '',
534
+			'attr_title'       => '',
535
+			'description'      => '',
536
+			'classes'          => array(),
537
+			'xfn'              => '',
538
+		);
539
+
540
+		foreach ($keys as $key => $value) {
541
+			$menu_item->{$key} = isset($menu_item_values[$key]) ? $menu_item_values[$key] : $value;
542
+		}
543
+		return $menu_item;
544
+	}
545
+
546
+
547
+	/**
548
+	 * This is the action hook for the AHEE__EE_Admin_Page__route_admin_request hook that fires off right before an
549
+	 * EE_Admin_Page route is called.
550
+	 *
551
+	 * @return void
552
+	 */
553
+	public function route_admin_request()
554
+	{
555
+	}
556
+
557
+
558
+	/**
559
+	 * wp_loaded should fire on the WordPress wp_loaded hook.  This fires on a VERY late priority.
560
+	 *
561
+	 * @return void
562
+	 */
563
+	public function wp_loaded()
564
+	{
565
+	}
566
+
567
+
568
+	/**
569
+	 * admin_init
570
+	 *
571
+	 * @return void
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws InvalidInterfaceException
576
+	 * @throws ReflectionException
577
+	 */
578
+	public function admin_init()
579
+	{
580
+
581
+		/**
582
+		 * our cpt models must be instantiated on WordPress post processing routes (wp-admin/post.php),
583
+		 * so any hooking into core WP routes is taken care of.  So in this next few lines of code:
584
+		 * - check if doing post processing.
585
+		 * - check if doing post processing of one of EE CPTs
586
+		 * - instantiate the corresponding EE CPT model for the post_type being processed.
587
+		 */
588
+		if (isset($_POST['action'], $_POST['post_type']) && $_POST['action'] === 'editpost') {
589
+			EE_Registry::instance()->load_core('Register_CPTs');
590
+			EE_Register_CPTs::instantiate_cpt_models($_POST['post_type']);
591
+		}
592
+
593
+
594
+		/**
595
+		 * This code excludes EE critical pages anywhere `wp_dropdown_pages` is used to create a dropdown for selecting
596
+		 * critical pages.  The only place critical pages need included in a generated dropdown is on the "Critical
597
+		 * Pages" tab in the EE General Settings Admin page.
598
+		 * This is for user-proofing.
599
+		 */
600
+		add_filter('wp_dropdown_pages', array($this, 'modify_dropdown_pages'));
601
+	}
602
+
603
+
604
+	/**
605
+	 * Callback for wp_dropdown_pages hook to remove ee critical pages from the dropdown selection.
606
+	 *
607
+	 * @param string $output Current output.
608
+	 * @return string
609
+	 * @throws InvalidArgumentException
610
+	 * @throws InvalidDataTypeException
611
+	 * @throws InvalidInterfaceException
612
+	 */
613
+	public function modify_dropdown_pages($output)
614
+	{
615
+		//get critical pages
616
+		$critical_pages = EE_Registry::instance()->CFG->core->get_critical_pages_array();
617
+
618
+		//split current output by line break for easier parsing.
619
+		$split_output = explode("\n", $output);
620
+
621
+		//loop through to remove any critical pages from the array.
622
+		foreach ($critical_pages as $page_id) {
623
+			$needle = 'value="' . $page_id . '"';
624
+			foreach ($split_output as $key => $haystack) {
625
+				if (strpos($haystack, $needle) !== false) {
626
+					unset($split_output[$key]);
627
+				}
628
+			}
629
+		}
630
+		//replace output with the new contents
631
+		return implode("\n", $split_output);
632
+	}
633
+
634
+
635
+	/**
636
+	 * enqueue all admin scripts that need loaded for admin pages
637
+	 *
638
+	 * @return void
639
+	 */
640
+	public function enqueue_admin_scripts()
641
+	{
642
+		// this javascript is loaded on every admin page to catch any injections ee needs to add to wp run js.
643
+		// Note: the intention of this script is to only do TARGETED injections.  I.E, only injecting on certain script
644
+		// calls.
645
+		wp_enqueue_script(
646
+			'ee-inject-wp',
647
+			EE_ADMIN_URL . 'assets/ee-cpt-wp-injects.js',
648
+			array('jquery'),
649
+			EVENT_ESPRESSO_VERSION,
650
+			true
651
+		);
652
+		// register cookie script for future dependencies
653
+		wp_register_script(
654
+			'jquery-cookie',
655
+			EE_THIRD_PARTY_URL . 'joyride/jquery.cookie.js',
656
+			array('jquery'),
657
+			'2.1',
658
+			true
659
+		);
660
+		//joyride is turned OFF by default, but prior to the admin_enqueue_scripts hook, can be turned back on again
661
+		// via: add_filter('FHEE_load_joyride', '__return_true' );
662
+		if (apply_filters('FHEE_load_joyride', false)) {
663
+			//joyride style
664
+			wp_register_style('joyride-css', EE_THIRD_PARTY_URL . 'joyride/joyride-2.1.css', array(), '2.1');
665
+			wp_register_style(
666
+				'ee-joyride-css',
667
+				EE_GLOBAL_ASSETS_URL . 'css/ee-joyride-styles.css',
668
+				array('joyride-css'),
669
+				EVENT_ESPRESSO_VERSION
670
+			);
671
+			wp_register_script(
672
+				'joyride-modernizr',
673
+				EE_THIRD_PARTY_URL . 'joyride/modernizr.mq.js',
674
+				array(),
675
+				'2.1',
676
+				true
677
+			);
678
+			//joyride JS
679
+			wp_register_script(
680
+				'jquery-joyride',
681
+				EE_THIRD_PARTY_URL . 'joyride/jquery.joyride-2.1.js',
682
+				array('jquery-cookie', 'joyride-modernizr'),
683
+				'2.1',
684
+				true
685
+			);
686
+			// wanna go for a joyride?
687
+			wp_enqueue_style('ee-joyride-css');
688
+			wp_enqueue_script('jquery-joyride');
689
+		}
690
+	}
691
+
692
+
693
+	/**
694
+	 * display_admin_notices
695
+	 *
696
+	 * @return void
697
+	 */
698
+	public function display_admin_notices()
699
+	{
700
+		echo EE_Error::get_notices();
701
+	}
702
+
703
+
704
+
705
+	/**
706
+	 * @param array $elements
707
+	 * @return array
708
+	 * @throws EE_Error
709
+	 * @throws InvalidArgumentException
710
+	 * @throws InvalidDataTypeException
711
+	 * @throws InvalidInterfaceException
712
+	 */
713
+	public function dashboard_glance_items($elements)
714
+	{
715
+		$elements                        = is_array($elements) ? $elements : array($elements);
716
+		$events                          = EEM_Event::instance()->count();
717
+		$items['events']['url']          = EE_Admin_Page::add_query_args_and_nonce(
718
+			array('page' => 'espresso_events'),
719
+			admin_url('admin.php')
720
+		);
721
+		$items['events']['text']         = sprintf(_n('%s Event', '%s Events', $events), number_format_i18n($events));
722
+		$items['events']['title']        = esc_html__('Click to view all Events', 'event_espresso');
723
+		$registrations                   = EEM_Registration::instance()->count(
724
+			array(
725
+				array(
726
+					'STS_ID' => array('!=', EEM_Registration::status_id_incomplete),
727
+				),
728
+			)
729
+		);
730
+		$items['registrations']['url']   = EE_Admin_Page::add_query_args_and_nonce(
731
+			array('page' => 'espresso_registrations'),
732
+			admin_url('admin.php')
733
+		);
734
+		$items['registrations']['text']  = sprintf(
735
+			_n('%s Registration', '%s Registrations', $registrations),
736
+			number_format_i18n($registrations)
737
+		);
738
+		$items['registrations']['title'] = esc_html__('Click to view all registrations', 'event_espresso');
739
+
740
+		$items = (array)apply_filters('FHEE__EE_Admin__dashboard_glance_items__items', $items);
741
+
742
+		foreach ($items as $type => $item_properties) {
743
+			$elements[] = sprintf(
744
+				'<a class="ee-dashboard-link-' . $type . '" href="%s" title="%s">%s</a>',
745
+				$item_properties['url'],
746
+				$item_properties['title'],
747
+				$item_properties['text']
748
+			);
749
+		}
750
+		return $elements;
751
+	}
752
+
753
+
754
+	/**
755
+	 * check_for_invalid_datetime_formats
756
+	 * if an admin changes their date or time format settings on the WP General Settings admin page, verify that
757
+	 * their selected format can be parsed by PHP
758
+	 *
759
+	 * @param    $value
760
+	 * @param    $option
761
+	 * @throws EE_Error
762
+	 * @return    string
763
+	 */
764
+	public function check_for_invalid_datetime_formats($value, $option)
765
+	{
766
+		// check for date_format or time_format
767
+		switch ($option) {
768
+			case 'date_format':
769
+				$date_time_format = $value . ' ' . get_option('time_format');
770
+				break;
771
+			case 'time_format':
772
+				$date_time_format = get_option('date_format') . ' ' . $value;
773
+				break;
774
+			default:
775
+				$date_time_format = false;
776
+		}
777
+		// do we have a date_time format to check ?
778
+		if ($date_time_format) {
779
+			$error_msg = EEH_DTT_Helper::validate_format_string($date_time_format);
780
+
781
+			if (is_array($error_msg)) {
782
+				$msg = '<p>'
783
+					   . sprintf(
784
+						   esc_html__(
785
+							   'The following date time "%s" ( %s ) is difficult to be properly parsed by PHP for the following reasons:',
786
+							   'event_espresso'
787
+						   ),
788
+						   date($date_time_format),
789
+						   $date_time_format
790
+					   )
791
+					   . '</p><p><ul>';
792
+
793
+
794
+				foreach ($error_msg as $error) {
795
+					$msg .= '<li>' . $error . '</li>';
796
+				}
797
+
798
+				$msg .= '</ul></p><p>'
799
+						. sprintf(
800
+							esc_html__(
801
+								'%sPlease note that your date and time formats have been reset to "F j, Y" and "g:i a" respectively.%s',
802
+								'event_espresso'
803
+							),
804
+							'<span style="color:#D54E21;">',
805
+							'</span>'
806
+						)
807
+						. '</p>';
808
+
809
+				// trigger WP settings error
810
+				add_settings_error(
811
+					'date_format',
812
+					'date_format',
813
+					$msg
814
+				);
815
+
816
+				// set format to something valid
817
+				switch ($option) {
818
+					case 'date_format':
819
+						$value = 'F j, Y';
820
+						break;
821
+					case 'time_format':
822
+						$value = 'g:i a';
823
+						break;
824
+				}
825
+			}
826
+		}
827
+		return $value;
828
+	}
829
+
830
+
831
+	/**
832
+	 * its_eSpresso - converts the less commonly used spelling of "Expresso" to "Espresso"
833
+	 *
834
+	 * @param $content
835
+	 * @return    string
836
+	 */
837
+	public function its_eSpresso($content)
838
+	{
839
+		return str_replace('[EXPRESSO_', '[ESPRESSO_', $content);
840
+	}
841
+
842
+
843
+	/**
844
+	 * espresso_admin_footer
845
+	 *
846
+	 * @return    string
847
+	 */
848
+	public function espresso_admin_footer()
849
+	{
850
+		return \EEH_Template::powered_by_event_espresso('aln-cntr', '', array('utm_content' => 'admin_footer'));
851
+	}
852
+
853
+
854
+	/**
855
+	 * static method for registering ee admin page.
856
+	 * This method is deprecated in favor of the new location in EE_Register_Admin_Page::register.
857
+	 *
858
+	 * @since      4.3.0
859
+	 * @deprecated 4.3.0    Use EE_Register_Admin_Page::register() instead
860
+	 * @see        EE_Register_Admin_Page::register()
861
+	 * @param       $page_basename
862
+	 * @param       $page_path
863
+	 * @param array $config
864
+	 * @return void
865
+	 * @throws EE_Error
866
+	 */
867
+	public static function register_ee_admin_page($page_basename, $page_path, $config = array())
868
+	{
869
+		EE_Error::doing_it_wrong(
870
+			__METHOD__,
871
+			sprintf(
872
+				esc_html__(
873
+					'Usage is deprecated.  Use EE_Register_Admin_Page::register() for registering the %s admin page.',
874
+					'event_espresso'
875
+				),
876
+				$page_basename
877
+			),
878
+			'4.3'
879
+		);
880
+		if (class_exists('EE_Register_Admin_Page')) {
881
+			$config['page_path'] = $page_path;
882
+		}
883
+		EE_Register_Admin_Page::register($page_basename, $config);
884
+	}
885
+
886
+
887
+	/**
888
+	 * @deprecated 4.8.41
889
+	 * @param  int      $post_ID
890
+	 * @param  \WP_Post $post
891
+	 * @return void
892
+	 */
893
+	public static function parse_post_content_on_save($post_ID, $post)
894
+	{
895
+		EE_Error::doing_it_wrong(
896
+			__METHOD__,
897
+			esc_html__('Usage is deprecated', 'event_espresso'),
898
+			'4.8.41'
899
+		);
900
+	}
901
+
902
+
903
+	/**
904
+	 * @deprecated 4.8.41
905
+	 * @param  $option
906
+	 * @param  $old_value
907
+	 * @param  $value
908
+	 * @return void
909
+	 */
910
+	public function reset_page_for_posts_on_change($option, $old_value, $value)
911
+	{
912
+		EE_Error::doing_it_wrong(
913
+			__METHOD__,
914
+			esc_html__('Usage is deprecated', 'event_espresso'),
915
+			'4.8.41'
916
+		);
917
+	}
918
+
919
+
920
+
921
+	/**
922
+	 * @deprecated 4.9.27
923
+	 * @return void
924
+	 */
925
+	public function get_persistent_admin_notices()
926
+	{
927
+		EE_Error::doing_it_wrong(
928
+			__METHOD__,
929
+			sprintf(
930
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
931
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
932
+			),
933
+			'4.9.27'
934
+		);
935
+	}
936
+
937
+
938
+
939
+	/**
940
+	 * @deprecated 4.9.27
941
+	 * @throws InvalidInterfaceException
942
+	 * @throws InvalidDataTypeException
943
+	 * @throws DomainException
944
+	 */
945
+	public function dismiss_ee_nag_notice_callback()
946
+	{
947
+		EE_Error::doing_it_wrong(
948
+			__METHOD__,
949
+			sprintf(
950
+				__('Usage is deprecated. Use "%1$s" instead.', 'event_espresso'),
951
+				'\EventEspresso\core\services\notifications\PersistentAdminNoticeManager'
952
+			),
953
+			'4.9.27'
954
+		);
955
+		$this->persistent_admin_notice_manager->dismissNotice();
956
+	}
957
+
958
+
959
+	/**
960
+	 * Callback on load-plugins.php hook for setting up anything hooking into the wp plugins page.
961
+	 * @throws InvalidArgumentException
962
+	 * @throws InvalidDataTypeException
963
+	 * @throws InvalidInterfaceException
964
+	 */
965
+	public function hookIntoWpPluginsPage()
966
+	{
967
+		LoaderFactory::getLoader()->getShared('EventEspresso\core\domain\services\admin\ExitModal');
968
+		LoaderFactory::getLoader()
969
+					 ->getShared('EventEspresso\core\domain\services\admin\PluginUpsells')
970
+					 ->decafUpsells();
971
+	}
972 972
 }
Please login to merge, or discard this patch.
core/request_stack/EE_Request.core.php 1 patch
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -22,369 +22,369 @@
 block discarded – undo
22 22
 class EE_Request implements LegacyRequestInterface, InterminableInterface
23 23
 {
24 24
 
25
-    /**
26
-     * @var RequestInterface $request
27
-     */
28
-    private $request;
29
-
30
-    /**
31
-     * whether current request is for the admin but NOT via AJAX
32
-     *
33
-     * @var boolean $admin
34
-     */
35
-    public $admin = false;
36
-
37
-    /**
38
-     * whether current request is via AJAX
39
-     *
40
-     * @var boolean $ajax
41
-     */
42
-    public $ajax = false;
43
-
44
-    /**
45
-     * whether current request is via AJAX from the frontend of the site
46
-     *
47
-     * @var boolean $front_ajax
48
-     */
49
-    public $front_ajax = false;
50
-
51
-
52
-    /**
53
-     * @deprecated 4.9.53
54
-     * @param array $get
55
-     * @param array $post
56
-     * @param array $cookie
57
-     * @param array $server
58
-     */
59
-    public function __construct(
60
-        array $get = array(),
61
-        array $post = array(),
62
-        array $cookie = array(),
63
-        array $server = array()
64
-    ) {
65
-    }
66
-
67
-
68
-    /**
69
-     * @return RequestInterface
70
-     * @throws InvalidArgumentException
71
-     * @throws InvalidInterfaceException
72
-     * @throws InvalidDataTypeException
73
-     */
74
-    private function request()
75
-    {
76
-        if($this->request instanceof RequestInterface){
77
-            return $this->request;
78
-        }
79
-        $loader = LoaderFactory::getLoader();
80
-        $this->request = $loader->getShared('EventEspresso\core\services\request\RequestInterface');
81
-        return $this->request;
82
-    }
83
-
84
-
85
-    /**
86
-     * @param RequestInterface $request
87
-     */
88
-    public function setRequest(RequestInterface $request)
89
-    {
90
-        $this->request = $request;
91
-    }
92
-
93
-
94
-
95
-    /**
96
-     * @deprecated 4.9.53
97
-     * @return array
98
-     * @throws InvalidArgumentException
99
-     * @throws InvalidDataTypeException
100
-     * @throws InvalidInterfaceException
101
-     */
102
-    public function get_params()
103
-    {
104
-        return $this->request()->getParams();
105
-    }
106
-
107
-
108
-
109
-    /**
110
-     * @deprecated 4.9.53
111
-     * @return array
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     */
116
-    public function post_params()
117
-    {
118
-        return $this->request()->postParams();
119
-    }
120
-
121
-
122
-
123
-    /**
124
-     * @deprecated 4.9.53
125
-     * @return array
126
-     * @throws InvalidArgumentException
127
-     * @throws InvalidDataTypeException
128
-     * @throws InvalidInterfaceException
129
-     */
130
-    public function cookie_params()
131
-    {
132
-        return $this->request()->cookieParams();
133
-    }
134
-
135
-
136
-    /**
137
-     * @deprecated 4.9.53
138
-     * @return array
139
-     * @throws InvalidArgumentException
140
-     * @throws InvalidDataTypeException
141
-     * @throws InvalidInterfaceException
142
-     */
143
-    public function server_params()
144
-    {
145
-        return $this->request()->serverParams();
146
-    }
147
-
148
-
149
-
150
-    /**
151
-     * returns contents of $_REQUEST
152
-     *
153
-     * @deprecated 4.9.53
154
-     * @return array
155
-     * @throws InvalidArgumentException
156
-     * @throws InvalidDataTypeException
157
-     * @throws InvalidInterfaceException
158
-     */
159
-    public function params()
160
-    {
161
-        return $this->request()->requestParams();
162
-    }
163
-
164
-
165
-
166
-    /**
167
-     * @deprecated 4.9.53
168
-     * @param      $key
169
-     * @param      $value
170
-     * @param bool $override_ee
171
-     * @return void
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     */
176
-    public function set($key, $value, $override_ee = false)
177
-    {
178
-        $this->request()->setRequestParam($key, $value, $override_ee);
179
-    }
180
-
181
-
182
-
183
-    /**
184
-     * returns   the value for a request param if the given key exists
185
-     *
186
-     * @deprecated 4.9.53
187
-     * @param      $key
188
-     * @param null $default
189
-     * @return mixed
190
-     * @throws InvalidArgumentException
191
-     * @throws InvalidDataTypeException
192
-     * @throws InvalidInterfaceException
193
-     */
194
-    public function get($key, $default = null)
195
-    {
196
-        return $this->request()->getRequestParam($key, $default);
197
-    }
198
-
199
-
200
-
201
-    /**
202
-     * check if param exists
203
-     *
204
-     * @deprecated 4.9.53
205
-     * @param $key
206
-     * @return bool
207
-     * @throws InvalidArgumentException
208
-     * @throws InvalidDataTypeException
209
-     * @throws InvalidInterfaceException
210
-     */
211
-    public function is_set($key)
212
-    {
213
-        return $this->request()->requestParamIsSet($key);
214
-    }
215
-
216
-
217
-    /**
218
-     * remove param
219
-     *
220
-     * @deprecated 4.9.53
221
-     * @param      $key
222
-     * @param bool $unset_from_global_too
223
-     * @throws InvalidArgumentException
224
-     * @throws InvalidDataTypeException
225
-     * @throws InvalidInterfaceException
226
-     */
227
-    public function un_set($key, $unset_from_global_too = false)
228
-    {
229
-        $this->request()->unSetRequestParam($key, $unset_from_global_too);
230
-    }
231
-
232
-
233
-
234
-    /**
235
-     * @deprecated 4.9.53
236
-     * @return string
237
-     * @throws InvalidArgumentException
238
-     * @throws InvalidDataTypeException
239
-     * @throws InvalidInterfaceException
240
-     */
241
-    public function ip_address()
242
-    {
243
-        return $this->request()->ipAddress();
244
-    }
245
-
246
-
247
-    /**
248
-     * @deprecated 4.9.53
249
-     * @return bool
250
-     * @throws InvalidArgumentException
251
-     * @throws InvalidDataTypeException
252
-     * @throws InvalidInterfaceException
253
-     */
254
-    public function isAdmin()
255
-    {
256
-        return $this->request()->isAdmin();
257
-    }
258
-
259
-
260
-    /**
261
-     * @deprecated 4.9.53
262
-     * @return mixed
263
-     * @throws InvalidArgumentException
264
-     * @throws InvalidDataTypeException
265
-     * @throws InvalidInterfaceException
266
-     */
267
-    public function isAjax()
268
-    {
269
-        return $this->request()->isAjax();
270
-    }
271
-
272
-
273
-    /**
274
-     * @deprecated 4.9.53
275
-     * @return mixed
276
-     * @throws InvalidArgumentException
277
-     * @throws InvalidDataTypeException
278
-     * @throws InvalidInterfaceException
279
-     */
280
-    public function isFrontAjax()
281
-    {
282
-        return $this->request()->isFrontAjax();
283
-    }
284
-
285
-
286
-    /**
287
-     * @deprecated 4.9.53
288
-     * @return mixed|string
289
-     * @throws InvalidArgumentException
290
-     * @throws InvalidDataTypeException
291
-     * @throws InvalidInterfaceException
292
-     */
293
-    public function requestUri()
294
-    {
295
-        return $this->request()->requestUri();
296
-    }
297
-
298
-
299
-    /**
300
-     * @deprecated 4.9.53
301
-     * @return string
302
-     * @throws InvalidArgumentException
303
-     * @throws InvalidDataTypeException
304
-     * @throws InvalidInterfaceException
305
-     */
306
-    public function userAgent()
307
-    {
308
-        return $this->request()->userAgent();
309
-    }
310
-
311
-
312
-    /**
313
-     * @deprecated 4.9.53
314
-     * @param string $user_agent
315
-     * @throws InvalidArgumentException
316
-     * @throws InvalidDataTypeException
317
-     * @throws InvalidInterfaceException
318
-     */
319
-    public function setUserAgent($user_agent = '')
320
-    {
321
-        $this->request()->setUserAgent($user_agent);
322
-    }
323
-
324
-
325
-    /**
326
-     * @deprecated 4.9.53
327
-     * @return bool
328
-     * @throws InvalidArgumentException
329
-     * @throws InvalidDataTypeException
330
-     * @throws InvalidInterfaceException
331
-     */
332
-    public function isBot()
333
-    {
334
-        return $this->request()->isBot();
335
-    }
336
-
337
-
338
-    /**
339
-     * @deprecated 4.9.53
340
-     * @param bool $is_bot
341
-     * @throws InvalidArgumentException
342
-     * @throws InvalidDataTypeException
343
-     * @throws InvalidInterfaceException
344
-     */
345
-    public function setIsBot($is_bot)
346
-    {
347
-        $this->request()->setIsBot($is_bot);
348
-    }
349
-
350
-
351
-    /**
352
-     * check if a request parameter exists whose key that matches the supplied wildcard pattern
353
-     * and return the value for the first match found
354
-     * wildcards can be either of the following:
355
-     *      ? to represent a single character of any type
356
-     *      * to represent one or more characters of any type
357
-     *
358
-     * @param string     $pattern
359
-     * @param null|mixed $default
360
-     * @return false|int
361
-     * @throws InvalidArgumentException
362
-     * @throws InvalidInterfaceException
363
-     * @throws InvalidDataTypeException
364
-     */
365
-    public function getMatch($pattern, $default = null)
366
-    {
367
-        return $this->request()->getMatch($pattern, $default);
368
-    }
369
-
370
-
371
-    /**
372
-     * check if a request parameter exists whose key matches the supplied wildcard pattern
373
-     * wildcards can be either of the following:
374
-     *      ? to represent a single character of any type
375
-     *      * to represent one or more characters of any type
376
-     * returns true if a match is found or false if not
377
-     *
378
-     * @param string $pattern
379
-     * @return false|int
380
-     * @throws InvalidArgumentException
381
-     * @throws InvalidInterfaceException
382
-     * @throws InvalidDataTypeException
383
-     */
384
-    public function matches($pattern)
385
-    {
386
-        return $this->request()->matches($pattern);
387
-    }
25
+	/**
26
+	 * @var RequestInterface $request
27
+	 */
28
+	private $request;
29
+
30
+	/**
31
+	 * whether current request is for the admin but NOT via AJAX
32
+	 *
33
+	 * @var boolean $admin
34
+	 */
35
+	public $admin = false;
36
+
37
+	/**
38
+	 * whether current request is via AJAX
39
+	 *
40
+	 * @var boolean $ajax
41
+	 */
42
+	public $ajax = false;
43
+
44
+	/**
45
+	 * whether current request is via AJAX from the frontend of the site
46
+	 *
47
+	 * @var boolean $front_ajax
48
+	 */
49
+	public $front_ajax = false;
50
+
51
+
52
+	/**
53
+	 * @deprecated 4.9.53
54
+	 * @param array $get
55
+	 * @param array $post
56
+	 * @param array $cookie
57
+	 * @param array $server
58
+	 */
59
+	public function __construct(
60
+		array $get = array(),
61
+		array $post = array(),
62
+		array $cookie = array(),
63
+		array $server = array()
64
+	) {
65
+	}
66
+
67
+
68
+	/**
69
+	 * @return RequestInterface
70
+	 * @throws InvalidArgumentException
71
+	 * @throws InvalidInterfaceException
72
+	 * @throws InvalidDataTypeException
73
+	 */
74
+	private function request()
75
+	{
76
+		if($this->request instanceof RequestInterface){
77
+			return $this->request;
78
+		}
79
+		$loader = LoaderFactory::getLoader();
80
+		$this->request = $loader->getShared('EventEspresso\core\services\request\RequestInterface');
81
+		return $this->request;
82
+	}
83
+
84
+
85
+	/**
86
+	 * @param RequestInterface $request
87
+	 */
88
+	public function setRequest(RequestInterface $request)
89
+	{
90
+		$this->request = $request;
91
+	}
92
+
93
+
94
+
95
+	/**
96
+	 * @deprecated 4.9.53
97
+	 * @return array
98
+	 * @throws InvalidArgumentException
99
+	 * @throws InvalidDataTypeException
100
+	 * @throws InvalidInterfaceException
101
+	 */
102
+	public function get_params()
103
+	{
104
+		return $this->request()->getParams();
105
+	}
106
+
107
+
108
+
109
+	/**
110
+	 * @deprecated 4.9.53
111
+	 * @return array
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 */
116
+	public function post_params()
117
+	{
118
+		return $this->request()->postParams();
119
+	}
120
+
121
+
122
+
123
+	/**
124
+	 * @deprecated 4.9.53
125
+	 * @return array
126
+	 * @throws InvalidArgumentException
127
+	 * @throws InvalidDataTypeException
128
+	 * @throws InvalidInterfaceException
129
+	 */
130
+	public function cookie_params()
131
+	{
132
+		return $this->request()->cookieParams();
133
+	}
134
+
135
+
136
+	/**
137
+	 * @deprecated 4.9.53
138
+	 * @return array
139
+	 * @throws InvalidArgumentException
140
+	 * @throws InvalidDataTypeException
141
+	 * @throws InvalidInterfaceException
142
+	 */
143
+	public function server_params()
144
+	{
145
+		return $this->request()->serverParams();
146
+	}
147
+
148
+
149
+
150
+	/**
151
+	 * returns contents of $_REQUEST
152
+	 *
153
+	 * @deprecated 4.9.53
154
+	 * @return array
155
+	 * @throws InvalidArgumentException
156
+	 * @throws InvalidDataTypeException
157
+	 * @throws InvalidInterfaceException
158
+	 */
159
+	public function params()
160
+	{
161
+		return $this->request()->requestParams();
162
+	}
163
+
164
+
165
+
166
+	/**
167
+	 * @deprecated 4.9.53
168
+	 * @param      $key
169
+	 * @param      $value
170
+	 * @param bool $override_ee
171
+	 * @return void
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 */
176
+	public function set($key, $value, $override_ee = false)
177
+	{
178
+		$this->request()->setRequestParam($key, $value, $override_ee);
179
+	}
180
+
181
+
182
+
183
+	/**
184
+	 * returns   the value for a request param if the given key exists
185
+	 *
186
+	 * @deprecated 4.9.53
187
+	 * @param      $key
188
+	 * @param null $default
189
+	 * @return mixed
190
+	 * @throws InvalidArgumentException
191
+	 * @throws InvalidDataTypeException
192
+	 * @throws InvalidInterfaceException
193
+	 */
194
+	public function get($key, $default = null)
195
+	{
196
+		return $this->request()->getRequestParam($key, $default);
197
+	}
198
+
199
+
200
+
201
+	/**
202
+	 * check if param exists
203
+	 *
204
+	 * @deprecated 4.9.53
205
+	 * @param $key
206
+	 * @return bool
207
+	 * @throws InvalidArgumentException
208
+	 * @throws InvalidDataTypeException
209
+	 * @throws InvalidInterfaceException
210
+	 */
211
+	public function is_set($key)
212
+	{
213
+		return $this->request()->requestParamIsSet($key);
214
+	}
215
+
216
+
217
+	/**
218
+	 * remove param
219
+	 *
220
+	 * @deprecated 4.9.53
221
+	 * @param      $key
222
+	 * @param bool $unset_from_global_too
223
+	 * @throws InvalidArgumentException
224
+	 * @throws InvalidDataTypeException
225
+	 * @throws InvalidInterfaceException
226
+	 */
227
+	public function un_set($key, $unset_from_global_too = false)
228
+	{
229
+		$this->request()->unSetRequestParam($key, $unset_from_global_too);
230
+	}
231
+
232
+
233
+
234
+	/**
235
+	 * @deprecated 4.9.53
236
+	 * @return string
237
+	 * @throws InvalidArgumentException
238
+	 * @throws InvalidDataTypeException
239
+	 * @throws InvalidInterfaceException
240
+	 */
241
+	public function ip_address()
242
+	{
243
+		return $this->request()->ipAddress();
244
+	}
245
+
246
+
247
+	/**
248
+	 * @deprecated 4.9.53
249
+	 * @return bool
250
+	 * @throws InvalidArgumentException
251
+	 * @throws InvalidDataTypeException
252
+	 * @throws InvalidInterfaceException
253
+	 */
254
+	public function isAdmin()
255
+	{
256
+		return $this->request()->isAdmin();
257
+	}
258
+
259
+
260
+	/**
261
+	 * @deprecated 4.9.53
262
+	 * @return mixed
263
+	 * @throws InvalidArgumentException
264
+	 * @throws InvalidDataTypeException
265
+	 * @throws InvalidInterfaceException
266
+	 */
267
+	public function isAjax()
268
+	{
269
+		return $this->request()->isAjax();
270
+	}
271
+
272
+
273
+	/**
274
+	 * @deprecated 4.9.53
275
+	 * @return mixed
276
+	 * @throws InvalidArgumentException
277
+	 * @throws InvalidDataTypeException
278
+	 * @throws InvalidInterfaceException
279
+	 */
280
+	public function isFrontAjax()
281
+	{
282
+		return $this->request()->isFrontAjax();
283
+	}
284
+
285
+
286
+	/**
287
+	 * @deprecated 4.9.53
288
+	 * @return mixed|string
289
+	 * @throws InvalidArgumentException
290
+	 * @throws InvalidDataTypeException
291
+	 * @throws InvalidInterfaceException
292
+	 */
293
+	public function requestUri()
294
+	{
295
+		return $this->request()->requestUri();
296
+	}
297
+
298
+
299
+	/**
300
+	 * @deprecated 4.9.53
301
+	 * @return string
302
+	 * @throws InvalidArgumentException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws InvalidInterfaceException
305
+	 */
306
+	public function userAgent()
307
+	{
308
+		return $this->request()->userAgent();
309
+	}
310
+
311
+
312
+	/**
313
+	 * @deprecated 4.9.53
314
+	 * @param string $user_agent
315
+	 * @throws InvalidArgumentException
316
+	 * @throws InvalidDataTypeException
317
+	 * @throws InvalidInterfaceException
318
+	 */
319
+	public function setUserAgent($user_agent = '')
320
+	{
321
+		$this->request()->setUserAgent($user_agent);
322
+	}
323
+
324
+
325
+	/**
326
+	 * @deprecated 4.9.53
327
+	 * @return bool
328
+	 * @throws InvalidArgumentException
329
+	 * @throws InvalidDataTypeException
330
+	 * @throws InvalidInterfaceException
331
+	 */
332
+	public function isBot()
333
+	{
334
+		return $this->request()->isBot();
335
+	}
336
+
337
+
338
+	/**
339
+	 * @deprecated 4.9.53
340
+	 * @param bool $is_bot
341
+	 * @throws InvalidArgumentException
342
+	 * @throws InvalidDataTypeException
343
+	 * @throws InvalidInterfaceException
344
+	 */
345
+	public function setIsBot($is_bot)
346
+	{
347
+		$this->request()->setIsBot($is_bot);
348
+	}
349
+
350
+
351
+	/**
352
+	 * check if a request parameter exists whose key that matches the supplied wildcard pattern
353
+	 * and return the value for the first match found
354
+	 * wildcards can be either of the following:
355
+	 *      ? to represent a single character of any type
356
+	 *      * to represent one or more characters of any type
357
+	 *
358
+	 * @param string     $pattern
359
+	 * @param null|mixed $default
360
+	 * @return false|int
361
+	 * @throws InvalidArgumentException
362
+	 * @throws InvalidInterfaceException
363
+	 * @throws InvalidDataTypeException
364
+	 */
365
+	public function getMatch($pattern, $default = null)
366
+	{
367
+		return $this->request()->getMatch($pattern, $default);
368
+	}
369
+
370
+
371
+	/**
372
+	 * check if a request parameter exists whose key matches the supplied wildcard pattern
373
+	 * wildcards can be either of the following:
374
+	 *      ? to represent a single character of any type
375
+	 *      * to represent one or more characters of any type
376
+	 * returns true if a match is found or false if not
377
+	 *
378
+	 * @param string $pattern
379
+	 * @return false|int
380
+	 * @throws InvalidArgumentException
381
+	 * @throws InvalidInterfaceException
382
+	 * @throws InvalidDataTypeException
383
+	 */
384
+	public function matches($pattern)
385
+	{
386
+		return $this->request()->matches($pattern);
387
+	}
388 388
 
389 389
 
390 390
 }
Please login to merge, or discard this patch.
core/services/Benchmark.php 2 patches
Indentation   +328 added lines, -328 removed lines patch added patch discarded remove patch
@@ -20,334 +20,334 @@
 block discarded – undo
20 20
 class Benchmark
21 21
 {
22 22
 
23
-    /**
24
-     * @var string $output
25
-     */
26
-    private static $output;
27
-
28
-    /**
29
-     * @var array $start_times array containing the start time for the timers
30
-     */
31
-    private static $start_times;
32
-
33
-    /**
34
-     * @var array $times array containing all the timer'd times, which can be outputted via show_times()
35
-     */
36
-    private static $times = array();
37
-
38
-    /**
39
-     * @var array $memory_usage
40
-     */
41
-    protected static $memory_usage = array();
42
-
43
-
44
-    /**
45
-     * @param string $output
46
-     * @param bool   $formatted
47
-     */
48
-    public static function addOutput($output, $formatted = true)
49
-    {
50
-        Benchmark::$output .= $formatted
51
-            ? "<br />{$output}"
52
-            : "\n{$output}";
53
-    }
54
-
55
-
56
-    /**
57
-     * @return void
58
-     */
59
-    public static function resetOutput()
60
-    {
61
-        Benchmark::$output = '';
62
-    }
63
-
64
-    /**
65
-     * whether to benchmark code or not
66
-     */
67
-    public static function doNotRun()
68
-    {
69
-        return ! WP_DEBUG || (defined('DOING_AJAX') && DOING_AJAX);
70
-    }
71
-
72
-
73
-
74
-    /**
75
-     * resetTimes
76
-     */
77
-    public static function resetTimes()
78
-    {
79
-        Benchmark::$times = array();
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * Add Benchmark::startTimer() before a block of code you want to measure the performance of
86
-     *
87
-     * @param null $timer_name
88
-     */
89
-    public static function startTimer($timer_name = null)
90
-    {
91
-        if (Benchmark::doNotRun()) {
92
-            return;
93
-        }
94
-        $timer_name = $timer_name !== '' ? $timer_name : get_called_class();
95
-        Benchmark::$start_times[$timer_name] = microtime(true);
96
-    }
97
-
98
-
99
-
100
-    /**
101
-     * Add Benchmark::stopTimer() after a block of code you want to measure the performance of
102
-     *
103
-     * @param string $timer_name
104
-     */
105
-    public static function stopTimer($timer_name = '')
106
-    {
107
-        if (Benchmark::doNotRun()) {
108
-            return;
109
-        }
110
-        $timer_name = $timer_name !== '' ? $timer_name : get_called_class();
111
-        if (isset(Benchmark::$start_times[$timer_name])) {
112
-            $start_time = Benchmark::$start_times[$timer_name];
113
-            unset(Benchmark::$start_times[$timer_name]);
114
-        } else {
115
-            $start_time = array_pop(Benchmark::$start_times);
116
-        }
117
-        Benchmark::$times[$timer_name] = number_format(microtime(true) - $start_time, 8);
118
-    }
119
-
120
-
121
-
122
-    /**
123
-     * Measure the memory usage by PHP so far.
124
-     *
125
-     * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
126
-     * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
127
-     * @param bool    $formatted
128
-     * @return void
129
-     */
130
-    public static function measureMemory($label = 'memory usage', $output_now = false, $formatted = true)
131
-    {
132
-        if (Benchmark::doNotRun()) {
133
-            return;
134
-        }
135
-        $memory_used = Benchmark::convert(memory_get_usage(true));
136
-        Benchmark::$memory_usage[$label] = $memory_used;
137
-        if ($output_now) {
138
-            echo $formatted
139
-                ? "<br>{$label} : {$memory_used}"
140
-                : "\n {$label} : {$memory_used}";
141
-        }
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     * will display the benchmarking results at shutdown
148
-     *
149
-     * @param bool $formatted
150
-     * @return void
151
-     */
152
-    public static function displayResultsAtShutdown($formatted = true)
153
-    {
154
-        Benchmark::resetOutput();
155
-        add_action(
156
-            'shutdown',
157
-            function () use ($formatted) {
158
-                Benchmark::displayResults(true, $formatted);
159
-            }
160
-        );
161
-    }
162
-
163
-
164
-
165
-    /**
166
-     * will display the benchmarking results at shutdown
167
-     *
168
-     * @param string $filepath
169
-     * @param bool   $formatted
170
-     * @param bool   $append
171
-     * @return void
172
-     */
173
-    public static function writeResultsAtShutdown($filepath = '', $formatted = true, $append = true)
174
-    {
175
-        Benchmark::resetOutput();
176
-        add_action(
177
-            'shutdown',
178
-            function () use ($filepath, $formatted, $append) {
179
-                Benchmark::writeResultsToFile($filepath, $formatted, $append);
180
-            }
181
-        );
182
-    }
183
-
184
-
185
-
186
-    /**
187
-     * @param bool $formatted
188
-     * @return string
189
-     */
190
-    private static function generateResults($formatted = true)
191
-    {
192
-        if (Benchmark::doNotRun()) {
193
-            return '';
194
-        }
195
-        if (! empty(Benchmark::$times)) {
196
-            $total = 0;
197
-            Benchmark::$output .= $formatted
198
-                ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />'
199
-                : '';
200
-            foreach (Benchmark::$times as $timer_name => $total_time) {
201
-                Benchmark::$output .= Benchmark::formatTime($timer_name, $total_time, $formatted);
202
-                Benchmark::$output .= $formatted ? '<br />'  : "\n";
203
-                $total += $total_time;
204
-            }
205
-            if($formatted) {
206
-                Benchmark::$output .= '<br />';
207
-                Benchmark::$output .= '<h4>TOTAL TIME</h4>';
208
-                Benchmark::$output .= Benchmark::formatTime('', $total, $formatted);
209
-                Benchmark::$output .= '<span style="color:#999999; font-size:.8em;"> milliseconds</span><br />';
210
-                Benchmark::$output .= '<br />';
211
-                Benchmark::$output .= '<h5>Performance scale (from best to worse)</h5>';
212
-                Benchmark::$output .= '<span style="color:mediumpurple">Like wow! How about a Scooby snack?</span><br />';
213
-                Benchmark::$output .= '<span style="color:deepskyblue">Like...no way man!</span><br />';
214
-                Benchmark::$output .= '<span style="color:limegreen">Like...groovy!</span><br />';
215
-                Benchmark::$output .= '<span style="color:gold">Ruh Oh</span><br />';
216
-                Benchmark::$output .= '<span style="color:darkorange">Zoinks!</span><br />';
217
-                Benchmark::$output .= '<span style="color:red">Like...HEEELLLP</span><br />';
218
-            }
219
-        }
220
-        if (! empty(Benchmark::$memory_usage)) {
221
-            Benchmark::$output .= $formatted
222
-                ? '<h5>Memory</h5>'
223
-                : "\nMemory";
224
-            foreach (Benchmark::$memory_usage as $label => $memory_usage) {
225
-                Benchmark::$output .= $formatted
226
-                    ? "<br />{$memory_usage} : {$label}"
227
-                    : "\n{$memory_usage} : {$label}";
228
-            }
229
-        }
230
-        if (empty(Benchmark::$output)) {
231
-            return '';
232
-        }
233
-        Benchmark::$output = $formatted
234
-            ? '<div style="border:1px solid #dddddd; background-color:#ffffff;'
235
-              . (is_admin()
236
-                ? ' margin:2em 2em 2em 180px;'
237
-                : ' margin:2em;')
238
-              . ' padding:2em;">'
239
-              . '<h4>BENCHMARKING</h4>'
240
-              . Benchmark::$output
241
-              . '</div>'
242
-            : Benchmark::$output;
243
-        return Benchmark::$output;
244
-    }
245
-
246
-
247
-
248
-    /**
249
-     * @param bool $echo
250
-     * @param bool $formatted
251
-     * @return string
252
-     */
253
-    public static function displayResults($echo = true, $formatted = true)
254
-    {
255
-        $results = Benchmark::generateResults($formatted);
256
-        if ($echo) {
257
-            echo $results;
258
-            $results = '';
259
-        }
260
-        return $results;
261
-    }
262
-
263
-
264
-    /**
265
-     * @param string $filepath
266
-     * @param bool   $formatted
267
-     * @param bool   $append
268
-     * @throws EE_Error
269
-     */
270
-    public static function writeResultsToFile($filepath = '', $formatted = true, $append = true)
271
-    {
272
-        $filepath = ! empty($filepath) && is_readable(dirname($filepath))
273
-            ? $filepath
274
-            : '';
275
-        if( empty($filepath)) {
276
-            $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
277
-        }
278
-        EEH_File::ensure_file_exists_and_is_writable($filepath);
279
-        file_put_contents(
280
-            $filepath,
281
-            "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
282
-            $append ? FILE_APPEND | LOCK_EX : LOCK_EX
283
-        );
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
290
-     *
291
-     * @param int $size
292
-     * @return string
293
-     */
294
-    public static function convert($size)
295
-    {
296
-        $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
297
-        return round(
298
-            $size / pow(1024, $i = floor(log($size, 1024))),
299
-            2
300
-        ) . ' ' . $unit[absint($i)];
301
-    }
302
-
303
-
304
-
305
-    /**
306
-     * @param string $timer_name
307
-     * @param float  $total_time
308
-     * @param bool   $formatted
309
-     * @return string
310
-     */
311
-    public static function formatTime($timer_name, $total_time, $formatted = true)
312
-    {
313
-        $total_time *= 1000;
314
-        switch ($total_time) {
315
-            case $total_time > 12500 :
316
-                $color = 'red';
317
-                $bold = 'bold';
318
-                break;
319
-            case $total_time > 2500 :
320
-                $color = 'darkorange';
321
-                $bold = 'bold';
322
-                break;
323
-            case $total_time > 500 :
324
-                $color = 'gold';
325
-                $bold = 'bold';
326
-                break;
327
-            case $total_time > 100 :
328
-                $color = 'limegreen';
329
-                $bold = 'normal';
330
-                break;
331
-            case $total_time > 20 :
332
-                $color = 'deepskyblue';
333
-                $bold = 'normal';
334
-                break;
335
-            default :
336
-                $color = 'mediumpurple';
337
-                $bold = 'normal';
338
-                break;
339
-        }
340
-        return $formatted
341
-            ? '<span style="min-width: 10px; margin:0 1em; color:'
342
-               . $color
343
-               . '; font-weight:'
344
-               . $bold
345
-               . '; font-size:1.2em;">'
346
-               . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT)
347
-               . '</span> '
348
-               . $timer_name
349
-            :  str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT);
350
-    }
23
+	/**
24
+	 * @var string $output
25
+	 */
26
+	private static $output;
27
+
28
+	/**
29
+	 * @var array $start_times array containing the start time for the timers
30
+	 */
31
+	private static $start_times;
32
+
33
+	/**
34
+	 * @var array $times array containing all the timer'd times, which can be outputted via show_times()
35
+	 */
36
+	private static $times = array();
37
+
38
+	/**
39
+	 * @var array $memory_usage
40
+	 */
41
+	protected static $memory_usage = array();
42
+
43
+
44
+	/**
45
+	 * @param string $output
46
+	 * @param bool   $formatted
47
+	 */
48
+	public static function addOutput($output, $formatted = true)
49
+	{
50
+		Benchmark::$output .= $formatted
51
+			? "<br />{$output}"
52
+			: "\n{$output}";
53
+	}
54
+
55
+
56
+	/**
57
+	 * @return void
58
+	 */
59
+	public static function resetOutput()
60
+	{
61
+		Benchmark::$output = '';
62
+	}
63
+
64
+	/**
65
+	 * whether to benchmark code or not
66
+	 */
67
+	public static function doNotRun()
68
+	{
69
+		return ! WP_DEBUG || (defined('DOING_AJAX') && DOING_AJAX);
70
+	}
71
+
72
+
73
+
74
+	/**
75
+	 * resetTimes
76
+	 */
77
+	public static function resetTimes()
78
+	{
79
+		Benchmark::$times = array();
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * Add Benchmark::startTimer() before a block of code you want to measure the performance of
86
+	 *
87
+	 * @param null $timer_name
88
+	 */
89
+	public static function startTimer($timer_name = null)
90
+	{
91
+		if (Benchmark::doNotRun()) {
92
+			return;
93
+		}
94
+		$timer_name = $timer_name !== '' ? $timer_name : get_called_class();
95
+		Benchmark::$start_times[$timer_name] = microtime(true);
96
+	}
97
+
98
+
99
+
100
+	/**
101
+	 * Add Benchmark::stopTimer() after a block of code you want to measure the performance of
102
+	 *
103
+	 * @param string $timer_name
104
+	 */
105
+	public static function stopTimer($timer_name = '')
106
+	{
107
+		if (Benchmark::doNotRun()) {
108
+			return;
109
+		}
110
+		$timer_name = $timer_name !== '' ? $timer_name : get_called_class();
111
+		if (isset(Benchmark::$start_times[$timer_name])) {
112
+			$start_time = Benchmark::$start_times[$timer_name];
113
+			unset(Benchmark::$start_times[$timer_name]);
114
+		} else {
115
+			$start_time = array_pop(Benchmark::$start_times);
116
+		}
117
+		Benchmark::$times[$timer_name] = number_format(microtime(true) - $start_time, 8);
118
+	}
119
+
120
+
121
+
122
+	/**
123
+	 * Measure the memory usage by PHP so far.
124
+	 *
125
+	 * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
126
+	 * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
127
+	 * @param bool    $formatted
128
+	 * @return void
129
+	 */
130
+	public static function measureMemory($label = 'memory usage', $output_now = false, $formatted = true)
131
+	{
132
+		if (Benchmark::doNotRun()) {
133
+			return;
134
+		}
135
+		$memory_used = Benchmark::convert(memory_get_usage(true));
136
+		Benchmark::$memory_usage[$label] = $memory_used;
137
+		if ($output_now) {
138
+			echo $formatted
139
+				? "<br>{$label} : {$memory_used}"
140
+				: "\n {$label} : {$memory_used}";
141
+		}
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 * will display the benchmarking results at shutdown
148
+	 *
149
+	 * @param bool $formatted
150
+	 * @return void
151
+	 */
152
+	public static function displayResultsAtShutdown($formatted = true)
153
+	{
154
+		Benchmark::resetOutput();
155
+		add_action(
156
+			'shutdown',
157
+			function () use ($formatted) {
158
+				Benchmark::displayResults(true, $formatted);
159
+			}
160
+		);
161
+	}
162
+
163
+
164
+
165
+	/**
166
+	 * will display the benchmarking results at shutdown
167
+	 *
168
+	 * @param string $filepath
169
+	 * @param bool   $formatted
170
+	 * @param bool   $append
171
+	 * @return void
172
+	 */
173
+	public static function writeResultsAtShutdown($filepath = '', $formatted = true, $append = true)
174
+	{
175
+		Benchmark::resetOutput();
176
+		add_action(
177
+			'shutdown',
178
+			function () use ($filepath, $formatted, $append) {
179
+				Benchmark::writeResultsToFile($filepath, $formatted, $append);
180
+			}
181
+		);
182
+	}
183
+
184
+
185
+
186
+	/**
187
+	 * @param bool $formatted
188
+	 * @return string
189
+	 */
190
+	private static function generateResults($formatted = true)
191
+	{
192
+		if (Benchmark::doNotRun()) {
193
+			return '';
194
+		}
195
+		if (! empty(Benchmark::$times)) {
196
+			$total = 0;
197
+			Benchmark::$output .= $formatted
198
+				? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />'
199
+				: '';
200
+			foreach (Benchmark::$times as $timer_name => $total_time) {
201
+				Benchmark::$output .= Benchmark::formatTime($timer_name, $total_time, $formatted);
202
+				Benchmark::$output .= $formatted ? '<br />'  : "\n";
203
+				$total += $total_time;
204
+			}
205
+			if($formatted) {
206
+				Benchmark::$output .= '<br />';
207
+				Benchmark::$output .= '<h4>TOTAL TIME</h4>';
208
+				Benchmark::$output .= Benchmark::formatTime('', $total, $formatted);
209
+				Benchmark::$output .= '<span style="color:#999999; font-size:.8em;"> milliseconds</span><br />';
210
+				Benchmark::$output .= '<br />';
211
+				Benchmark::$output .= '<h5>Performance scale (from best to worse)</h5>';
212
+				Benchmark::$output .= '<span style="color:mediumpurple">Like wow! How about a Scooby snack?</span><br />';
213
+				Benchmark::$output .= '<span style="color:deepskyblue">Like...no way man!</span><br />';
214
+				Benchmark::$output .= '<span style="color:limegreen">Like...groovy!</span><br />';
215
+				Benchmark::$output .= '<span style="color:gold">Ruh Oh</span><br />';
216
+				Benchmark::$output .= '<span style="color:darkorange">Zoinks!</span><br />';
217
+				Benchmark::$output .= '<span style="color:red">Like...HEEELLLP</span><br />';
218
+			}
219
+		}
220
+		if (! empty(Benchmark::$memory_usage)) {
221
+			Benchmark::$output .= $formatted
222
+				? '<h5>Memory</h5>'
223
+				: "\nMemory";
224
+			foreach (Benchmark::$memory_usage as $label => $memory_usage) {
225
+				Benchmark::$output .= $formatted
226
+					? "<br />{$memory_usage} : {$label}"
227
+					: "\n{$memory_usage} : {$label}";
228
+			}
229
+		}
230
+		if (empty(Benchmark::$output)) {
231
+			return '';
232
+		}
233
+		Benchmark::$output = $formatted
234
+			? '<div style="border:1px solid #dddddd; background-color:#ffffff;'
235
+			  . (is_admin()
236
+				? ' margin:2em 2em 2em 180px;'
237
+				: ' margin:2em;')
238
+			  . ' padding:2em;">'
239
+			  . '<h4>BENCHMARKING</h4>'
240
+			  . Benchmark::$output
241
+			  . '</div>'
242
+			: Benchmark::$output;
243
+		return Benchmark::$output;
244
+	}
245
+
246
+
247
+
248
+	/**
249
+	 * @param bool $echo
250
+	 * @param bool $formatted
251
+	 * @return string
252
+	 */
253
+	public static function displayResults($echo = true, $formatted = true)
254
+	{
255
+		$results = Benchmark::generateResults($formatted);
256
+		if ($echo) {
257
+			echo $results;
258
+			$results = '';
259
+		}
260
+		return $results;
261
+	}
262
+
263
+
264
+	/**
265
+	 * @param string $filepath
266
+	 * @param bool   $formatted
267
+	 * @param bool   $append
268
+	 * @throws EE_Error
269
+	 */
270
+	public static function writeResultsToFile($filepath = '', $formatted = true, $append = true)
271
+	{
272
+		$filepath = ! empty($filepath) && is_readable(dirname($filepath))
273
+			? $filepath
274
+			: '';
275
+		if( empty($filepath)) {
276
+			$filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
277
+		}
278
+		EEH_File::ensure_file_exists_and_is_writable($filepath);
279
+		file_put_contents(
280
+			$filepath,
281
+			"\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
282
+			$append ? FILE_APPEND | LOCK_EX : LOCK_EX
283
+		);
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * Converts a measure of memory bytes into the most logical units (eg kb, mb, etc)
290
+	 *
291
+	 * @param int $size
292
+	 * @return string
293
+	 */
294
+	public static function convert($size)
295
+	{
296
+		$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
297
+		return round(
298
+			$size / pow(1024, $i = floor(log($size, 1024))),
299
+			2
300
+		) . ' ' . $unit[absint($i)];
301
+	}
302
+
303
+
304
+
305
+	/**
306
+	 * @param string $timer_name
307
+	 * @param float  $total_time
308
+	 * @param bool   $formatted
309
+	 * @return string
310
+	 */
311
+	public static function formatTime($timer_name, $total_time, $formatted = true)
312
+	{
313
+		$total_time *= 1000;
314
+		switch ($total_time) {
315
+			case $total_time > 12500 :
316
+				$color = 'red';
317
+				$bold = 'bold';
318
+				break;
319
+			case $total_time > 2500 :
320
+				$color = 'darkorange';
321
+				$bold = 'bold';
322
+				break;
323
+			case $total_time > 500 :
324
+				$color = 'gold';
325
+				$bold = 'bold';
326
+				break;
327
+			case $total_time > 100 :
328
+				$color = 'limegreen';
329
+				$bold = 'normal';
330
+				break;
331
+			case $total_time > 20 :
332
+				$color = 'deepskyblue';
333
+				$bold = 'normal';
334
+				break;
335
+			default :
336
+				$color = 'mediumpurple';
337
+				$bold = 'normal';
338
+				break;
339
+		}
340
+		return $formatted
341
+			? '<span style="min-width: 10px; margin:0 1em; color:'
342
+			   . $color
343
+			   . '; font-weight:'
344
+			   . $bold
345
+			   . '; font-size:1.2em;">'
346
+			   . str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT)
347
+			   . '</span> '
348
+			   . $timer_name
349
+			:  str_pad(number_format($total_time, 3), 9, '0', STR_PAD_LEFT);
350
+	}
351 351
 
352 352
 
353 353
 
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
         Benchmark::resetOutput();
155 155
         add_action(
156 156
             'shutdown',
157
-            function () use ($formatted) {
157
+            function() use ($formatted) {
158 158
                 Benchmark::displayResults(true, $formatted);
159 159
             }
160 160
         );
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
         Benchmark::resetOutput();
176 176
         add_action(
177 177
             'shutdown',
178
-            function () use ($filepath, $formatted, $append) {
178
+            function() use ($filepath, $formatted, $append) {
179 179
                 Benchmark::writeResultsToFile($filepath, $formatted, $append);
180 180
             }
181 181
         );
@@ -192,17 +192,17 @@  discard block
 block discarded – undo
192 192
         if (Benchmark::doNotRun()) {
193 193
             return '';
194 194
         }
195
-        if (! empty(Benchmark::$times)) {
195
+        if ( ! empty(Benchmark::$times)) {
196 196
             $total = 0;
197 197
             Benchmark::$output .= $formatted
198 198
                 ? '<span style="color:#999999; font-size:.8em;">( time in milliseconds )</span><br />'
199 199
                 : '';
200 200
             foreach (Benchmark::$times as $timer_name => $total_time) {
201 201
                 Benchmark::$output .= Benchmark::formatTime($timer_name, $total_time, $formatted);
202
-                Benchmark::$output .= $formatted ? '<br />'  : "\n";
202
+                Benchmark::$output .= $formatted ? '<br />' : "\n";
203 203
                 $total += $total_time;
204 204
             }
205
-            if($formatted) {
205
+            if ($formatted) {
206 206
                 Benchmark::$output .= '<br />';
207 207
                 Benchmark::$output .= '<h4>TOTAL TIME</h4>';
208 208
                 Benchmark::$output .= Benchmark::formatTime('', $total, $formatted);
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
                 Benchmark::$output .= '<span style="color:red">Like...HEEELLLP</span><br />';
218 218
             }
219 219
         }
220
-        if (! empty(Benchmark::$memory_usage)) {
220
+        if ( ! empty(Benchmark::$memory_usage)) {
221 221
             Benchmark::$output .= $formatted
222 222
                 ? '<h5>Memory</h5>'
223 223
                 : "\nMemory";
@@ -272,13 +272,13 @@  discard block
 block discarded – undo
272 272
         $filepath = ! empty($filepath) && is_readable(dirname($filepath))
273 273
             ? $filepath
274 274
             : '';
275
-        if( empty($filepath)) {
276
-            $filepath = EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-' . date('Y-m-d') . '.html';
275
+        if (empty($filepath)) {
276
+            $filepath = EVENT_ESPRESSO_UPLOAD_DIR.'logs/benchmarking-'.date('Y-m-d').'.html';
277 277
         }
278 278
         EEH_File::ensure_file_exists_and_is_writable($filepath);
279 279
         file_put_contents(
280 280
             $filepath,
281
-            "\n" . date('Y-m-d H:i:s') . Benchmark::generateResults($formatted),
281
+            "\n".date('Y-m-d H:i:s').Benchmark::generateResults($formatted),
282 282
             $append ? FILE_APPEND | LOCK_EX : LOCK_EX
283 283
         );
284 284
     }
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
         return round(
298 298
             $size / pow(1024, $i = floor(log($size, 1024))),
299 299
             2
300
-        ) . ' ' . $unit[absint($i)];
300
+        ).' '.$unit[absint($i)];
301 301
     }
302 302
 
303 303
 
Please login to merge, or discard this patch.
core/EE_Encryption.core.php 2 patches
Indentation   +686 added lines, -686 removed lines patch added patch discarded remove patch
@@ -19,692 +19,692 @@
 block discarded – undo
19 19
 class EE_Encryption implements InterminableInterface
20 20
 {
21 21
 
22
-    /**
23
-     * key used for saving the encryption key to the wp_options table
24
-     */
25
-    const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
26
-
27
-    /**
28
-     * the OPENSSL cipher method used
29
-     */
30
-    const OPENSSL_CIPHER_METHOD = 'AES-128-CBC';
31
-
32
-    /**
33
-     * WP "options_name" used to store a verified available cipher method
34
-     */
35
-    const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method';
36
-
37
-    /**
38
-     * the OPENSSL digest method used
39
-     */
40
-    const OPENSSL_DIGEST_METHOD = 'sha512';
41
-
42
-    /**
43
-     * separates the encrypted text from the initialization vector
44
-     */
45
-    const OPENSSL_IV_DELIMITER = ':iv:';
46
-
47
-    /**
48
-     * appended to text encrypted using the acme encryption
49
-     */
50
-    const ACME_ENCRYPTION_FLAG = '::ae';
51
-
52
-
53
-
54
-    /**
55
-     * instance of the EE_Encryption object
56
-     */
57
-    protected static $_instance;
58
-
59
-    /**
60
-     * @var string $_encryption_key
61
-     */
62
-    protected $_encryption_key;
63
-
64
-    /**
65
-     * @var string $cipher_method
66
-     */
67
-    private $cipher_method = '';
68
-
69
-    /**
70
-     * @var array $cipher_methods
71
-     */
72
-    private $cipher_methods = array();
73
-
74
-    /**
75
-     * @var array $digest_methods
76
-     */
77
-    private $digest_methods = array();
78
-
79
-    /**
80
-     * @var boolean $_use_openssl_encrypt
81
-     */
82
-    protected $_use_openssl_encrypt = false;
83
-
84
-    /**
85
-     * @var boolean $_use_mcrypt
86
-     */
87
-    protected $_use_mcrypt = false;
88
-
89
-    /**
90
-     * @var boolean $_use_base64_encode
91
-     */
92
-    protected $_use_base64_encode = false;
93
-
94
-
95
-
96
-    /**
97
-     * protected constructor to prevent direct creation
98
-     */
99
-    protected function __construct()
100
-    {
101
-        if (! defined('ESPRESSO_ENCRYPT')) {
102
-            define('ESPRESSO_ENCRYPT', true);
103
-        }
104
-        if (extension_loaded('openssl')) {
105
-            $this->_use_openssl_encrypt = true;
106
-        } else if (extension_loaded('mcrypt')) {
107
-            $this->_use_mcrypt = true;
108
-        }
109
-        if (function_exists('base64_encode')) {
110
-            $this->_use_base64_encode = true;
111
-        }
112
-    }
113
-
114
-
115
-
116
-    /**
117
-     * singleton method used to instantiate class object
118
-     *
119
-     * @return EE_Encryption
120
-     */
121
-    public static function instance()
122
-    {
123
-        // check if class object is instantiated
124
-        if (! EE_Encryption::$_instance instanceof EE_Encryption) {
125
-            EE_Encryption::$_instance = new self();
126
-        }
127
-        return EE_Encryption::$_instance;
128
-    }
129
-
130
-
131
-
132
-    /**
133
-     * get encryption key
134
-     *
135
-     * @return string
136
-     */
137
-    public function get_encryption_key()
138
-    {
139
-        // if encryption key has not been set
140
-        if (empty($this->_encryption_key)) {
141
-            // retrieve encryption_key from db
142
-            $this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
143
-            // WHAT?? No encryption_key in the db ??
144
-            if ($this->_encryption_key === '') {
145
-                // let's make one. And md5 it to make it just the right size for a key
146
-                $new_key = md5($this->generate_random_string());
147
-                // now save it to the db for later
148
-                add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
149
-                // here's the key - FINALLY !
150
-                $this->_encryption_key = $new_key;
151
-            }
152
-        }
153
-        return $this->_encryption_key;
154
-    }
155
-
156
-
157
-
158
-    /**
159
-     * encrypts data
160
-     *
161
-     * @param string $text_string - the text to be encrypted
162
-     * @return string
163
-     * @throws RuntimeException
164
-     */
165
-    public function encrypt($text_string = '')
166
-    {
167
-        // you give me nothing??? GET OUT !
168
-        if (empty($text_string)) {
169
-            return $text_string;
170
-        }
171
-        if ($this->_use_openssl_encrypt) {
172
-            $encrypted_text = $this->openssl_encrypt($text_string);
173
-        } else {
174
-            $encrypted_text = $this->acme_encrypt($text_string);
175
-        }
176
-        return $encrypted_text;
177
-    }
178
-
179
-
180
-
181
-    /**
182
-     * decrypts data
183
-     *
184
-     * @param string $encrypted_text - the text to be decrypted
185
-     * @return string
186
-     * @throws RuntimeException
187
-     */
188
-    public function decrypt($encrypted_text = '')
189
-    {
190
-        // you give me nothing??? GET OUT !
191
-        if (empty($encrypted_text)) {
192
-            return $encrypted_text;
193
-        }
194
-        // if PHP's mcrypt functions are installed then we'll use them
195
-        if ($this->_use_openssl_encrypt) {
196
-            $decrypted_text = $this->openssl_decrypt($encrypted_text);
197
-        } else {
198
-            $decrypted_text = $this->acme_decrypt($encrypted_text);
199
-        }
200
-        return $decrypted_text;
201
-    }
202
-
203
-
204
-
205
-    /**
206
-     * encodes string with PHP's base64 encoding
207
-     *
208
-     * @see http://php.net/manual/en/function.base64-encode.php
209
-     * @param string $text_string the text to be encoded
210
-     * @return string
211
-     */
212
-    public function base64_string_encode($text_string = '')
213
-    {
214
-        // you give me nothing??? GET OUT !
215
-        if (empty($text_string) || ! $this->_use_base64_encode) {
216
-            return $text_string;
217
-        }
218
-        // encode
219
-        return base64_encode($text_string);
220
-    }
221
-
222
-
223
-    /**
224
-     * decodes string that has been encoded with PHP's base64 encoding
225
-     *
226
-     * @see http://php.net/manual/en/function.base64-encode.php
227
-     * @param string $encoded_string the text to be decoded
228
-     * @return string
229
-     * @throws RuntimeException
230
-     */
231
-    public function base64_string_decode($encoded_string = '')
232
-    {
233
-        // you give me nothing??? GET OUT !
234
-        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
235
-            return $encoded_string;
236
-        }
237
-        // decode
238
-        $decoded_string = base64_decode($encoded_string);
239
-        if ($decoded_string === false) {
240
-            throw new RuntimeException(
241
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
242
-            );
243
-        }
244
-        return $decoded_string;
245
-    }
246
-
247
-
248
-
249
-    /**
250
-     * encodes  url string with PHP's base64 encoding
251
-     *
252
-     * @see http://php.net/manual/en/function.base64-encode.php
253
-     * @param string $text_string the text to be encoded
254
-     * @return string
255
-     */
256
-    public function base64_url_encode($text_string = '')
257
-    {
258
-        // you give me nothing??? GET OUT !
259
-        if (empty($text_string) || ! $this->_use_base64_encode) {
260
-            return $text_string;
261
-        }
262
-        // encode
263
-        $encoded_string = base64_encode($text_string);
264
-        // remove chars to make encoding more URL friendly
265
-        return strtr($encoded_string, '+/=', '-_,');
266
-    }
267
-
268
-
269
-    /**
270
-     * decodes  url string that has been encoded with PHP's base64 encoding
271
-     *
272
-     * @see http://php.net/manual/en/function.base64-encode.php
273
-     * @param string $encoded_string the text to be decoded
274
-     * @return string
275
-     * @throws RuntimeException
276
-     */
277
-    public function base64_url_decode($encoded_string = '')
278
-    {
279
-        // you give me nothing??? GET OUT !
280
-        if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
281
-            return $encoded_string;
282
-        }
283
-        // replace previously removed characters
284
-        $encoded_string = strtr($encoded_string, '-_,', '+/=');
285
-        // decode
286
-        $decoded_string = base64_decode($encoded_string);
287
-        if ($decoded_string === false) {
288
-            throw new RuntimeException(
289
-                esc_html__('Base 64 decoding failed.', 'event_espresso')
290
-            );
291
-        }
292
-        return $decoded_string;
293
-    }
294
-
295
-
296
-    /**
297
-     * encrypts data using PHP's openssl functions
298
-     *
299
-     * @param string $text_string the text to be encrypted
300
-     * @param string $cipher_method
301
-     * @param string $encryption_key
302
-     * @return string
303
-     * @throws RuntimeException
304
-     */
305
-    protected function openssl_encrypt(
306
-        $text_string = '',
307
-        $cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
308
-        $encryption_key = ''
309
-    ) {
310
-        // you give me nothing??? GET OUT !
311
-        if (empty($text_string)) {
312
-            return $text_string;
313
-        }
314
-        $this->cipher_method = $this->getCipherMethod($cipher_method);
315
-        // get initialization vector size
316
-        $iv_size = openssl_cipher_iv_length($this->cipher_method);
317
-        // generate initialization vector.
318
-        // The second parameter ("crypto_strong") is passed by reference,
319
-        // and is used to determines if the algorithm used was "cryptographically strong"
320
-        // openssl_random_pseudo_bytes() will toggle it to either true or false
321
-        $iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
322
-        if ($iv === false || $is_strong === false) {
323
-            throw new RuntimeException(
324
-                esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
325
-            );
326
-        }
327
-        // encrypt it
328
-        $encrypted_text = openssl_encrypt(
329
-            $text_string,
330
-            $this->cipher_method,
331
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
332
-            0,
333
-            $iv
334
-        );
335
-        // append the initialization vector
336
-        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
337
-        // trim and maybe encode
338
-        return $this->_use_base64_encode
339
-            ? trim(base64_encode($encrypted_text))
340
-            : trim($encrypted_text);
341
-    }
342
-
343
-
344
-
345
-    /**
346
-     * Returns a cipher method that has been verified to work.
347
-     * First checks if the cached cipher has been set already and if so, returns that.
348
-     * Then tests the incoming default and returns that if it's good.
349
-     * If not, then it retrieves the previously tested and saved cipher method.
350
-     * But if that doesn't exist, then calls getAvailableCipherMethod()
351
-     * to see what is available on the server, and returns the results.
352
-     *
353
-     * @param string $cipher_method
354
-     * @return string
355
-     * @throws RuntimeException
356
-     */
357
-    protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
358
-    {
359
-        if($this->cipher_method !== ''){
360
-            return $this->cipher_method;
361
-        }
362
-        // verify that the default cipher method can produce an initialization vector
363
-        if (openssl_cipher_iv_length($cipher_method) === false) {
364
-            // nope? okay let's get what we found in the past to work
365
-            $cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
366
-            // oops... haven't tested available cipher methods yet
367
-            if($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
368
-                $cipher_method = $this->getAvailableCipherMethod($cipher_method);
369
-            }
370
-        }
371
-        return $cipher_method;
372
-    }
373
-
374
-
375
-
376
-    /**
377
-     * @param string $cipher_method
378
-     * @return string
379
-     * @throws \RuntimeException
380
-     */
381
-    protected function getAvailableCipherMethod($cipher_method)
382
-    {
383
-        // verify that the incoming cipher method can produce an initialization vector
384
-        if (openssl_cipher_iv_length($cipher_method) === false) {
385
-            // nope? then check the next cipher in the list of available cipher methods
386
-            $cipher_method = next($this->cipher_methods);
387
-            // what? there's no list? then generate that list and cache it,
388
-            if (empty($this->cipher_methods)) {
389
-                $this->cipher_methods = openssl_get_cipher_methods();
390
-                // then grab the first item from the list
391
-                $cipher_method = reset($this->cipher_methods);
392
-            }
393
-            if($cipher_method === false){
394
-                throw new RuntimeException(
395
-                    esc_html__(
396
-                        'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
397
-                        'event_espresso'
398
-                    )
399
-                );
400
-            }
401
-            // verify that the next cipher method works
402
-            return $this->getAvailableCipherMethod($cipher_method);
403
-        }
404
-        // if we've gotten this far, then we found an available cipher method that works
405
-        // so save that for next time
406
-        update_option(
407
-            EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME,
408
-            $cipher_method
409
-        );
410
-        return $cipher_method;
411
-    }
412
-
413
-
414
-    /**
415
-     * decrypts data that has been encrypted with PHP's openssl functions
416
-     *
417
-     * @param string $encrypted_text the text to be decrypted
418
-     * @param string $cipher_method
419
-     * @param string $encryption_key
420
-     * @return string
421
-     * @throws RuntimeException
422
-     */
423
-    protected function openssl_decrypt(
424
-        $encrypted_text = '',
425
-        $cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
426
-        $encryption_key = ''
427
-    ) {
428
-        // you give me nothing??? GET OUT !
429
-        if (empty($encrypted_text)) {
430
-            return $encrypted_text;
431
-        }
432
-        // decode
433
-        $encrypted_text = $this->valid_base_64($encrypted_text)
434
-            ? $this->base64_url_decode($encrypted_text)
435
-            : $encrypted_text;
436
-        $encrypted_components = explode(
437
-            EE_Encryption::OPENSSL_IV_DELIMITER,
438
-            $encrypted_text,
439
-            2
440
-        );
441
-        // check that iv exists, and if not, maybe text was encoded using mcrypt?
442
-        if ($this->_use_mcrypt && ! isset($encrypted_components[1])) {
443
-            return $this->m_decrypt($encrypted_text);
444
-        }
445
-        // decrypt it
446
-        $decrypted_text = openssl_decrypt(
447
-            $encrypted_components[0],
448
-            $this->getCipherMethod($cipher_method),
449
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD,$encryption_key),
450
-            0,
451
-            $encrypted_components[1]
452
-        );
453
-        $decrypted_text = trim($decrypted_text);
454
-        return $decrypted_text;
455
-    }
456
-
457
-
458
-    /**
459
-     * Computes the digest hash value using the specified digest method.
460
-     * If that digest method fails to produce a valid hash value,
461
-     * then we'll grab the next digest method and recursively try again until something works.
462
-     *
463
-     * @param string $digest_method
464
-     * @param string $encryption_key
465
-     * @return string
466
-     * @throws RuntimeException
467
-     */
468
-    protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = ''){
469
-        $encryption_key = $encryption_key !== ''
470
-            ? $encryption_key
471
-            : $this->get_encryption_key();
472
-        $digest_hash_value = openssl_digest($encryption_key, $digest_method);
473
-        if ($digest_hash_value === false) {
474
-            return $this->getDigestHashValue($this->getDigestMethod());
475
-        }
476
-        return $digest_hash_value;
477
-    }
478
-
479
-
480
-
481
-    /**
482
-     * Returns the NEXT element in the $digest_methods array.
483
-     * If the $digest_methods array is empty, then we populate it
484
-     * with the available values returned from openssl_get_md_methods().
485
-     *
486
-     * @return string
487
-     * @throws \RuntimeException
488
-     */
489
-    protected function getDigestMethod(){
490
-        $digest_method = prev($this->digest_methods);
491
-        if (empty($this->digest_methods)) {
492
-            $this->digest_methods = openssl_get_md_methods();
493
-            $digest_method = end($this->digest_methods);
494
-        }
495
-        if ($digest_method === false) {
496
-            throw new RuntimeException(
497
-                esc_html__(
498
-                    'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
499
-                    'event_espresso'
500
-                )
501
-            );
502
-        }
503
-        return $digest_method;
504
-    }
505
-
506
-
507
-    /**
508
-     * encrypts data for acme servers that didn't bother to install PHP mcrypt
509
-     *
510
-     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
511
-     * @param string $text_string the text to be decrypted
512
-     * @return string
513
-     */
514
-    protected function acme_encrypt($text_string = '')
515
-    {
516
-        // you give me nothing??? GET OUT !
517
-        if (empty($text_string)) {
518
-            return $text_string;
519
-        }
520
-        $key_bits = str_split(
521
-            str_pad(
522
-                '',
523
-                strlen($text_string),
524
-                $this->get_encryption_key(),
525
-                STR_PAD_RIGHT
526
-            )
527
-        );
528
-        $string_bits = str_split($text_string);
529
-        foreach ($string_bits as $k => $v) {
530
-            $temp = ord($v) + ord($key_bits[$k]);
531
-            $string_bits[$k] = chr($temp > 255 ? ($temp - 256) : $temp);
532
-        }
533
-        $encrypted_text = implode('', $string_bits);
534
-        $encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
535
-        return $this->_use_base64_encode
536
-            ? base64_encode($encrypted_text)
537
-            : $encrypted_text;
538
-    }
539
-
540
-
541
-
542
-    /**
543
-     * decrypts data for acme servers that didn't bother to install PHP mcrypt
544
-     *
545
-     * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
546
-     * @param string $encrypted_text the text to be decrypted
547
-     * @return string
548
-     * @throws RuntimeException
549
-     */
550
-    protected function acme_decrypt($encrypted_text = '')
551
-    {
552
-        // you give me nothing??? GET OUT !
553
-        if (empty($encrypted_text)) {
554
-            return $encrypted_text;
555
-        }
556
-        // decode the data ?
557
-        $encrypted_text = $this->valid_base_64($encrypted_text)
558
-            ? $this->base64_url_decode($encrypted_text)
559
-            : $encrypted_text;
560
-        if (
561
-            $this->_use_mcrypt
562
-            && strpos($encrypted_text, EE_Encryption::ACME_ENCRYPTION_FLAG) === false
563
-        ){
564
-            return $this->m_decrypt($encrypted_text);
565
-        }
566
-        $encrypted_text = substr($encrypted_text, 0, -4);
567
-        $key_bits = str_split(
568
-            str_pad(
569
-                '',
570
-                strlen($encrypted_text),
571
-                $this->get_encryption_key(),
572
-                STR_PAD_RIGHT
573
-            )
574
-        );
575
-        $string_bits = str_split($encrypted_text);
576
-        foreach ($string_bits as $k => $v) {
577
-            $temp = ord($v) - ord($key_bits[$k]);
578
-            $string_bits[$k] = chr($temp < 0 ? ($temp + 256) : $temp);
579
-        }
580
-        return implode('', $string_bits);
581
-    }
582
-
583
-
584
-
585
-    /**
586
-     * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
587
-     * @param $string
588
-     * @return bool
589
-     */
590
-    protected function valid_base_64($string)
591
-    {
592
-        // ensure data is a string
593
-        if (! is_string($string) || ! $this->_use_base64_encode) {
594
-            return false;
595
-        }
596
-        $decoded = base64_decode($string, true);
597
-        // Check if there is no invalid character in string
598
-        if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
599
-            return false;
600
-        }
601
-        // Decode the string in strict mode and send the response
602
-        if (! base64_decode($string, true)) {
603
-            return false;
604
-        }
605
-        // Encode and compare it to original one
606
-        return base64_encode($decoded) === $string;
607
-    }
608
-
609
-
610
-
611
-    /**
612
-     * generate random string
613
-     *
614
-     * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
615
-     * @param int $length number of characters for random string
616
-     * @return string
617
-     */
618
-    public function generate_random_string($length = 40)
619
-    {
620
-        $iterations = ceil($length / 40);
621
-        $random_string = '';
622
-        for ($i = 0; $i < $iterations; $i++) {
623
-            $random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
624
-        }
625
-        $random_string = substr($random_string, 0, $length);
626
-        return $random_string;
627
-    }
628
-
629
-
630
-
631
-    /**
632
-     * encrypts data using PHP's mcrypt functions
633
-     *
634
-     * @deprecated 4.9.39
635
-     * @param string $text_string
636
-     * @internal   param $string - the text to be encrypted
637
-     * @return string
638
-     * @throws RuntimeException
639
-     */
640
-    protected function m_encrypt($text_string = '')
641
-    {
642
-        // you give me nothing??? GET OUT !
643
-        if (empty($text_string)) {
644
-            return $text_string;
645
-        }
646
-        // get the initialization vector size
647
-        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
648
-        // initialization vector
649
-        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
650
-        if ($iv === false) {
651
-            throw new RuntimeException(
652
-                esc_html__('Failed to generate mcrypt initialization vector.', 'event_espresso')
653
-            );
654
-        }
655
-        // encrypt it
656
-        $encrypted_text = mcrypt_encrypt(
657
-            MCRYPT_RIJNDAEL_256,
658
-            $this->get_encryption_key(),
659
-            $text_string,
660
-            MCRYPT_MODE_ECB,
661
-            $iv
662
-        );
663
-        // trim and maybe encode
664
-        return $this->_use_base64_encode
665
-            ? trim(base64_encode($encrypted_text))
666
-            : trim($encrypted_text);
667
-    }
668
-
669
-
670
-
671
-    /**
672
-     * decrypts data that has been encrypted with PHP's mcrypt functions
673
-     *
674
-     * @deprecated 4.9.39
675
-     * @param string $encrypted_text the text to be decrypted
676
-     * @return string
677
-     * @throws RuntimeException
678
-     */
679
-    protected function m_decrypt($encrypted_text = '')
680
-    {
681
-        // you give me nothing??? GET OUT !
682
-        if (empty($encrypted_text)) {
683
-            return $encrypted_text;
684
-        }
685
-        // decode
686
-        $encrypted_text = $this->valid_base_64($encrypted_text)
687
-            ? $this->base64_url_decode($encrypted_text)
688
-            : $encrypted_text;
689
-        // get the initialization vector size
690
-        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
691
-        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
692
-        if ($iv === false) {
693
-            throw new RuntimeException(
694
-                esc_html__('Failed to generate mcrypt initialization vector.', 'event_espresso')
695
-            );
696
-        }
697
-        // decrypt it
698
-        $decrypted_text = mcrypt_decrypt(
699
-            MCRYPT_RIJNDAEL_256,
700
-            $this->get_encryption_key(),
701
-            $encrypted_text,
702
-            MCRYPT_MODE_ECB,
703
-            $iv
704
-        );
705
-        $decrypted_text = trim($decrypted_text);
706
-        return $decrypted_text;
707
-    }
22
+	/**
23
+	 * key used for saving the encryption key to the wp_options table
24
+	 */
25
+	const ENCRYPTION_OPTION_KEY = 'ee_encryption_key';
26
+
27
+	/**
28
+	 * the OPENSSL cipher method used
29
+	 */
30
+	const OPENSSL_CIPHER_METHOD = 'AES-128-CBC';
31
+
32
+	/**
33
+	 * WP "options_name" used to store a verified available cipher method
34
+	 */
35
+	const OPENSSL_CIPHER_METHOD_OPTION_NAME = 'ee_openssl_cipher_method';
36
+
37
+	/**
38
+	 * the OPENSSL digest method used
39
+	 */
40
+	const OPENSSL_DIGEST_METHOD = 'sha512';
41
+
42
+	/**
43
+	 * separates the encrypted text from the initialization vector
44
+	 */
45
+	const OPENSSL_IV_DELIMITER = ':iv:';
46
+
47
+	/**
48
+	 * appended to text encrypted using the acme encryption
49
+	 */
50
+	const ACME_ENCRYPTION_FLAG = '::ae';
51
+
52
+
53
+
54
+	/**
55
+	 * instance of the EE_Encryption object
56
+	 */
57
+	protected static $_instance;
58
+
59
+	/**
60
+	 * @var string $_encryption_key
61
+	 */
62
+	protected $_encryption_key;
63
+
64
+	/**
65
+	 * @var string $cipher_method
66
+	 */
67
+	private $cipher_method = '';
68
+
69
+	/**
70
+	 * @var array $cipher_methods
71
+	 */
72
+	private $cipher_methods = array();
73
+
74
+	/**
75
+	 * @var array $digest_methods
76
+	 */
77
+	private $digest_methods = array();
78
+
79
+	/**
80
+	 * @var boolean $_use_openssl_encrypt
81
+	 */
82
+	protected $_use_openssl_encrypt = false;
83
+
84
+	/**
85
+	 * @var boolean $_use_mcrypt
86
+	 */
87
+	protected $_use_mcrypt = false;
88
+
89
+	/**
90
+	 * @var boolean $_use_base64_encode
91
+	 */
92
+	protected $_use_base64_encode = false;
93
+
94
+
95
+
96
+	/**
97
+	 * protected constructor to prevent direct creation
98
+	 */
99
+	protected function __construct()
100
+	{
101
+		if (! defined('ESPRESSO_ENCRYPT')) {
102
+			define('ESPRESSO_ENCRYPT', true);
103
+		}
104
+		if (extension_loaded('openssl')) {
105
+			$this->_use_openssl_encrypt = true;
106
+		} else if (extension_loaded('mcrypt')) {
107
+			$this->_use_mcrypt = true;
108
+		}
109
+		if (function_exists('base64_encode')) {
110
+			$this->_use_base64_encode = true;
111
+		}
112
+	}
113
+
114
+
115
+
116
+	/**
117
+	 * singleton method used to instantiate class object
118
+	 *
119
+	 * @return EE_Encryption
120
+	 */
121
+	public static function instance()
122
+	{
123
+		// check if class object is instantiated
124
+		if (! EE_Encryption::$_instance instanceof EE_Encryption) {
125
+			EE_Encryption::$_instance = new self();
126
+		}
127
+		return EE_Encryption::$_instance;
128
+	}
129
+
130
+
131
+
132
+	/**
133
+	 * get encryption key
134
+	 *
135
+	 * @return string
136
+	 */
137
+	public function get_encryption_key()
138
+	{
139
+		// if encryption key has not been set
140
+		if (empty($this->_encryption_key)) {
141
+			// retrieve encryption_key from db
142
+			$this->_encryption_key = get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, '');
143
+			// WHAT?? No encryption_key in the db ??
144
+			if ($this->_encryption_key === '') {
145
+				// let's make one. And md5 it to make it just the right size for a key
146
+				$new_key = md5($this->generate_random_string());
147
+				// now save it to the db for later
148
+				add_option(EE_Encryption::ENCRYPTION_OPTION_KEY, $new_key);
149
+				// here's the key - FINALLY !
150
+				$this->_encryption_key = $new_key;
151
+			}
152
+		}
153
+		return $this->_encryption_key;
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 * encrypts data
160
+	 *
161
+	 * @param string $text_string - the text to be encrypted
162
+	 * @return string
163
+	 * @throws RuntimeException
164
+	 */
165
+	public function encrypt($text_string = '')
166
+	{
167
+		// you give me nothing??? GET OUT !
168
+		if (empty($text_string)) {
169
+			return $text_string;
170
+		}
171
+		if ($this->_use_openssl_encrypt) {
172
+			$encrypted_text = $this->openssl_encrypt($text_string);
173
+		} else {
174
+			$encrypted_text = $this->acme_encrypt($text_string);
175
+		}
176
+		return $encrypted_text;
177
+	}
178
+
179
+
180
+
181
+	/**
182
+	 * decrypts data
183
+	 *
184
+	 * @param string $encrypted_text - the text to be decrypted
185
+	 * @return string
186
+	 * @throws RuntimeException
187
+	 */
188
+	public function decrypt($encrypted_text = '')
189
+	{
190
+		// you give me nothing??? GET OUT !
191
+		if (empty($encrypted_text)) {
192
+			return $encrypted_text;
193
+		}
194
+		// if PHP's mcrypt functions are installed then we'll use them
195
+		if ($this->_use_openssl_encrypt) {
196
+			$decrypted_text = $this->openssl_decrypt($encrypted_text);
197
+		} else {
198
+			$decrypted_text = $this->acme_decrypt($encrypted_text);
199
+		}
200
+		return $decrypted_text;
201
+	}
202
+
203
+
204
+
205
+	/**
206
+	 * encodes string with PHP's base64 encoding
207
+	 *
208
+	 * @see http://php.net/manual/en/function.base64-encode.php
209
+	 * @param string $text_string the text to be encoded
210
+	 * @return string
211
+	 */
212
+	public function base64_string_encode($text_string = '')
213
+	{
214
+		// you give me nothing??? GET OUT !
215
+		if (empty($text_string) || ! $this->_use_base64_encode) {
216
+			return $text_string;
217
+		}
218
+		// encode
219
+		return base64_encode($text_string);
220
+	}
221
+
222
+
223
+	/**
224
+	 * decodes string that has been encoded with PHP's base64 encoding
225
+	 *
226
+	 * @see http://php.net/manual/en/function.base64-encode.php
227
+	 * @param string $encoded_string the text to be decoded
228
+	 * @return string
229
+	 * @throws RuntimeException
230
+	 */
231
+	public function base64_string_decode($encoded_string = '')
232
+	{
233
+		// you give me nothing??? GET OUT !
234
+		if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
235
+			return $encoded_string;
236
+		}
237
+		// decode
238
+		$decoded_string = base64_decode($encoded_string);
239
+		if ($decoded_string === false) {
240
+			throw new RuntimeException(
241
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
242
+			);
243
+		}
244
+		return $decoded_string;
245
+	}
246
+
247
+
248
+
249
+	/**
250
+	 * encodes  url string with PHP's base64 encoding
251
+	 *
252
+	 * @see http://php.net/manual/en/function.base64-encode.php
253
+	 * @param string $text_string the text to be encoded
254
+	 * @return string
255
+	 */
256
+	public function base64_url_encode($text_string = '')
257
+	{
258
+		// you give me nothing??? GET OUT !
259
+		if (empty($text_string) || ! $this->_use_base64_encode) {
260
+			return $text_string;
261
+		}
262
+		// encode
263
+		$encoded_string = base64_encode($text_string);
264
+		// remove chars to make encoding more URL friendly
265
+		return strtr($encoded_string, '+/=', '-_,');
266
+	}
267
+
268
+
269
+	/**
270
+	 * decodes  url string that has been encoded with PHP's base64 encoding
271
+	 *
272
+	 * @see http://php.net/manual/en/function.base64-encode.php
273
+	 * @param string $encoded_string the text to be decoded
274
+	 * @return string
275
+	 * @throws RuntimeException
276
+	 */
277
+	public function base64_url_decode($encoded_string = '')
278
+	{
279
+		// you give me nothing??? GET OUT !
280
+		if (empty($encoded_string) || ! $this->valid_base_64($encoded_string)) {
281
+			return $encoded_string;
282
+		}
283
+		// replace previously removed characters
284
+		$encoded_string = strtr($encoded_string, '-_,', '+/=');
285
+		// decode
286
+		$decoded_string = base64_decode($encoded_string);
287
+		if ($decoded_string === false) {
288
+			throw new RuntimeException(
289
+				esc_html__('Base 64 decoding failed.', 'event_espresso')
290
+			);
291
+		}
292
+		return $decoded_string;
293
+	}
294
+
295
+
296
+	/**
297
+	 * encrypts data using PHP's openssl functions
298
+	 *
299
+	 * @param string $text_string the text to be encrypted
300
+	 * @param string $cipher_method
301
+	 * @param string $encryption_key
302
+	 * @return string
303
+	 * @throws RuntimeException
304
+	 */
305
+	protected function openssl_encrypt(
306
+		$text_string = '',
307
+		$cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
308
+		$encryption_key = ''
309
+	) {
310
+		// you give me nothing??? GET OUT !
311
+		if (empty($text_string)) {
312
+			return $text_string;
313
+		}
314
+		$this->cipher_method = $this->getCipherMethod($cipher_method);
315
+		// get initialization vector size
316
+		$iv_size = openssl_cipher_iv_length($this->cipher_method);
317
+		// generate initialization vector.
318
+		// The second parameter ("crypto_strong") is passed by reference,
319
+		// and is used to determines if the algorithm used was "cryptographically strong"
320
+		// openssl_random_pseudo_bytes() will toggle it to either true or false
321
+		$iv = openssl_random_pseudo_bytes($iv_size, $is_strong);
322
+		if ($iv === false || $is_strong === false) {
323
+			throw new RuntimeException(
324
+				esc_html__('Failed to generate OpenSSL initialization vector.', 'event_espresso')
325
+			);
326
+		}
327
+		// encrypt it
328
+		$encrypted_text = openssl_encrypt(
329
+			$text_string,
330
+			$this->cipher_method,
331
+			$this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
332
+			0,
333
+			$iv
334
+		);
335
+		// append the initialization vector
336
+		$encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
337
+		// trim and maybe encode
338
+		return $this->_use_base64_encode
339
+			? trim(base64_encode($encrypted_text))
340
+			: trim($encrypted_text);
341
+	}
342
+
343
+
344
+
345
+	/**
346
+	 * Returns a cipher method that has been verified to work.
347
+	 * First checks if the cached cipher has been set already and if so, returns that.
348
+	 * Then tests the incoming default and returns that if it's good.
349
+	 * If not, then it retrieves the previously tested and saved cipher method.
350
+	 * But if that doesn't exist, then calls getAvailableCipherMethod()
351
+	 * to see what is available on the server, and returns the results.
352
+	 *
353
+	 * @param string $cipher_method
354
+	 * @return string
355
+	 * @throws RuntimeException
356
+	 */
357
+	protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
358
+	{
359
+		if($this->cipher_method !== ''){
360
+			return $this->cipher_method;
361
+		}
362
+		// verify that the default cipher method can produce an initialization vector
363
+		if (openssl_cipher_iv_length($cipher_method) === false) {
364
+			// nope? okay let's get what we found in the past to work
365
+			$cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
366
+			// oops... haven't tested available cipher methods yet
367
+			if($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
368
+				$cipher_method = $this->getAvailableCipherMethod($cipher_method);
369
+			}
370
+		}
371
+		return $cipher_method;
372
+	}
373
+
374
+
375
+
376
+	/**
377
+	 * @param string $cipher_method
378
+	 * @return string
379
+	 * @throws \RuntimeException
380
+	 */
381
+	protected function getAvailableCipherMethod($cipher_method)
382
+	{
383
+		// verify that the incoming cipher method can produce an initialization vector
384
+		if (openssl_cipher_iv_length($cipher_method) === false) {
385
+			// nope? then check the next cipher in the list of available cipher methods
386
+			$cipher_method = next($this->cipher_methods);
387
+			// what? there's no list? then generate that list and cache it,
388
+			if (empty($this->cipher_methods)) {
389
+				$this->cipher_methods = openssl_get_cipher_methods();
390
+				// then grab the first item from the list
391
+				$cipher_method = reset($this->cipher_methods);
392
+			}
393
+			if($cipher_method === false){
394
+				throw new RuntimeException(
395
+					esc_html__(
396
+						'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
397
+						'event_espresso'
398
+					)
399
+				);
400
+			}
401
+			// verify that the next cipher method works
402
+			return $this->getAvailableCipherMethod($cipher_method);
403
+		}
404
+		// if we've gotten this far, then we found an available cipher method that works
405
+		// so save that for next time
406
+		update_option(
407
+			EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME,
408
+			$cipher_method
409
+		);
410
+		return $cipher_method;
411
+	}
412
+
413
+
414
+	/**
415
+	 * decrypts data that has been encrypted with PHP's openssl functions
416
+	 *
417
+	 * @param string $encrypted_text the text to be decrypted
418
+	 * @param string $cipher_method
419
+	 * @param string $encryption_key
420
+	 * @return string
421
+	 * @throws RuntimeException
422
+	 */
423
+	protected function openssl_decrypt(
424
+		$encrypted_text = '',
425
+		$cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD,
426
+		$encryption_key = ''
427
+	) {
428
+		// you give me nothing??? GET OUT !
429
+		if (empty($encrypted_text)) {
430
+			return $encrypted_text;
431
+		}
432
+		// decode
433
+		$encrypted_text = $this->valid_base_64($encrypted_text)
434
+			? $this->base64_url_decode($encrypted_text)
435
+			: $encrypted_text;
436
+		$encrypted_components = explode(
437
+			EE_Encryption::OPENSSL_IV_DELIMITER,
438
+			$encrypted_text,
439
+			2
440
+		);
441
+		// check that iv exists, and if not, maybe text was encoded using mcrypt?
442
+		if ($this->_use_mcrypt && ! isset($encrypted_components[1])) {
443
+			return $this->m_decrypt($encrypted_text);
444
+		}
445
+		// decrypt it
446
+		$decrypted_text = openssl_decrypt(
447
+			$encrypted_components[0],
448
+			$this->getCipherMethod($cipher_method),
449
+			$this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD,$encryption_key),
450
+			0,
451
+			$encrypted_components[1]
452
+		);
453
+		$decrypted_text = trim($decrypted_text);
454
+		return $decrypted_text;
455
+	}
456
+
457
+
458
+	/**
459
+	 * Computes the digest hash value using the specified digest method.
460
+	 * If that digest method fails to produce a valid hash value,
461
+	 * then we'll grab the next digest method and recursively try again until something works.
462
+	 *
463
+	 * @param string $digest_method
464
+	 * @param string $encryption_key
465
+	 * @return string
466
+	 * @throws RuntimeException
467
+	 */
468
+	protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = ''){
469
+		$encryption_key = $encryption_key !== ''
470
+			? $encryption_key
471
+			: $this->get_encryption_key();
472
+		$digest_hash_value = openssl_digest($encryption_key, $digest_method);
473
+		if ($digest_hash_value === false) {
474
+			return $this->getDigestHashValue($this->getDigestMethod());
475
+		}
476
+		return $digest_hash_value;
477
+	}
478
+
479
+
480
+
481
+	/**
482
+	 * Returns the NEXT element in the $digest_methods array.
483
+	 * If the $digest_methods array is empty, then we populate it
484
+	 * with the available values returned from openssl_get_md_methods().
485
+	 *
486
+	 * @return string
487
+	 * @throws \RuntimeException
488
+	 */
489
+	protected function getDigestMethod(){
490
+		$digest_method = prev($this->digest_methods);
491
+		if (empty($this->digest_methods)) {
492
+			$this->digest_methods = openssl_get_md_methods();
493
+			$digest_method = end($this->digest_methods);
494
+		}
495
+		if ($digest_method === false) {
496
+			throw new RuntimeException(
497
+				esc_html__(
498
+					'OpenSSL support appears to be enabled on the server, but no digest methods are available. Please contact the server administrator.',
499
+					'event_espresso'
500
+				)
501
+			);
502
+		}
503
+		return $digest_method;
504
+	}
505
+
506
+
507
+	/**
508
+	 * encrypts data for acme servers that didn't bother to install PHP mcrypt
509
+	 *
510
+	 * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
511
+	 * @param string $text_string the text to be decrypted
512
+	 * @return string
513
+	 */
514
+	protected function acme_encrypt($text_string = '')
515
+	{
516
+		// you give me nothing??? GET OUT !
517
+		if (empty($text_string)) {
518
+			return $text_string;
519
+		}
520
+		$key_bits = str_split(
521
+			str_pad(
522
+				'',
523
+				strlen($text_string),
524
+				$this->get_encryption_key(),
525
+				STR_PAD_RIGHT
526
+			)
527
+		);
528
+		$string_bits = str_split($text_string);
529
+		foreach ($string_bits as $k => $v) {
530
+			$temp = ord($v) + ord($key_bits[$k]);
531
+			$string_bits[$k] = chr($temp > 255 ? ($temp - 256) : $temp);
532
+		}
533
+		$encrypted_text = implode('', $string_bits);
534
+		$encrypted_text .= EE_Encryption::ACME_ENCRYPTION_FLAG;
535
+		return $this->_use_base64_encode
536
+			? base64_encode($encrypted_text)
537
+			: $encrypted_text;
538
+	}
539
+
540
+
541
+
542
+	/**
543
+	 * decrypts data for acme servers that didn't bother to install PHP mcrypt
544
+	 *
545
+	 * @see http://stackoverflow.com/questions/800922/how-to-encrypt-string-without-mcrypt-library-in-php
546
+	 * @param string $encrypted_text the text to be decrypted
547
+	 * @return string
548
+	 * @throws RuntimeException
549
+	 */
550
+	protected function acme_decrypt($encrypted_text = '')
551
+	{
552
+		// you give me nothing??? GET OUT !
553
+		if (empty($encrypted_text)) {
554
+			return $encrypted_text;
555
+		}
556
+		// decode the data ?
557
+		$encrypted_text = $this->valid_base_64($encrypted_text)
558
+			? $this->base64_url_decode($encrypted_text)
559
+			: $encrypted_text;
560
+		if (
561
+			$this->_use_mcrypt
562
+			&& strpos($encrypted_text, EE_Encryption::ACME_ENCRYPTION_FLAG) === false
563
+		){
564
+			return $this->m_decrypt($encrypted_text);
565
+		}
566
+		$encrypted_text = substr($encrypted_text, 0, -4);
567
+		$key_bits = str_split(
568
+			str_pad(
569
+				'',
570
+				strlen($encrypted_text),
571
+				$this->get_encryption_key(),
572
+				STR_PAD_RIGHT
573
+			)
574
+		);
575
+		$string_bits = str_split($encrypted_text);
576
+		foreach ($string_bits as $k => $v) {
577
+			$temp = ord($v) - ord($key_bits[$k]);
578
+			$string_bits[$k] = chr($temp < 0 ? ($temp + 256) : $temp);
579
+		}
580
+		return implode('', $string_bits);
581
+	}
582
+
583
+
584
+
585
+	/**
586
+	 * @see http://stackoverflow.com/questions/2556345/detect-base64-encoding-in-php#30231906
587
+	 * @param $string
588
+	 * @return bool
589
+	 */
590
+	protected function valid_base_64($string)
591
+	{
592
+		// ensure data is a string
593
+		if (! is_string($string) || ! $this->_use_base64_encode) {
594
+			return false;
595
+		}
596
+		$decoded = base64_decode($string, true);
597
+		// Check if there is no invalid character in string
598
+		if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
599
+			return false;
600
+		}
601
+		// Decode the string in strict mode and send the response
602
+		if (! base64_decode($string, true)) {
603
+			return false;
604
+		}
605
+		// Encode and compare it to original one
606
+		return base64_encode($decoded) === $string;
607
+	}
608
+
609
+
610
+
611
+	/**
612
+	 * generate random string
613
+	 *
614
+	 * @see http://stackoverflow.com/questions/637278/what-is-the-best-way-to-generate-a-random-key-within-php
615
+	 * @param int $length number of characters for random string
616
+	 * @return string
617
+	 */
618
+	public function generate_random_string($length = 40)
619
+	{
620
+		$iterations = ceil($length / 40);
621
+		$random_string = '';
622
+		for ($i = 0; $i < $iterations; $i++) {
623
+			$random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
624
+		}
625
+		$random_string = substr($random_string, 0, $length);
626
+		return $random_string;
627
+	}
628
+
629
+
630
+
631
+	/**
632
+	 * encrypts data using PHP's mcrypt functions
633
+	 *
634
+	 * @deprecated 4.9.39
635
+	 * @param string $text_string
636
+	 * @internal   param $string - the text to be encrypted
637
+	 * @return string
638
+	 * @throws RuntimeException
639
+	 */
640
+	protected function m_encrypt($text_string = '')
641
+	{
642
+		// you give me nothing??? GET OUT !
643
+		if (empty($text_string)) {
644
+			return $text_string;
645
+		}
646
+		// get the initialization vector size
647
+		$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
648
+		// initialization vector
649
+		$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
650
+		if ($iv === false) {
651
+			throw new RuntimeException(
652
+				esc_html__('Failed to generate mcrypt initialization vector.', 'event_espresso')
653
+			);
654
+		}
655
+		// encrypt it
656
+		$encrypted_text = mcrypt_encrypt(
657
+			MCRYPT_RIJNDAEL_256,
658
+			$this->get_encryption_key(),
659
+			$text_string,
660
+			MCRYPT_MODE_ECB,
661
+			$iv
662
+		);
663
+		// trim and maybe encode
664
+		return $this->_use_base64_encode
665
+			? trim(base64_encode($encrypted_text))
666
+			: trim($encrypted_text);
667
+	}
668
+
669
+
670
+
671
+	/**
672
+	 * decrypts data that has been encrypted with PHP's mcrypt functions
673
+	 *
674
+	 * @deprecated 4.9.39
675
+	 * @param string $encrypted_text the text to be decrypted
676
+	 * @return string
677
+	 * @throws RuntimeException
678
+	 */
679
+	protected function m_decrypt($encrypted_text = '')
680
+	{
681
+		// you give me nothing??? GET OUT !
682
+		if (empty($encrypted_text)) {
683
+			return $encrypted_text;
684
+		}
685
+		// decode
686
+		$encrypted_text = $this->valid_base_64($encrypted_text)
687
+			? $this->base64_url_decode($encrypted_text)
688
+			: $encrypted_text;
689
+		// get the initialization vector size
690
+		$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
691
+		$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
692
+		if ($iv === false) {
693
+			throw new RuntimeException(
694
+				esc_html__('Failed to generate mcrypt initialization vector.', 'event_espresso')
695
+			);
696
+		}
697
+		// decrypt it
698
+		$decrypted_text = mcrypt_decrypt(
699
+			MCRYPT_RIJNDAEL_256,
700
+			$this->get_encryption_key(),
701
+			$encrypted_text,
702
+			MCRYPT_MODE_ECB,
703
+			$iv
704
+		);
705
+		$decrypted_text = trim($decrypted_text);
706
+		return $decrypted_text;
707
+	}
708 708
 
709 709
 }
710 710
 /* End of file EE_Encryption.class.php */
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -98,7 +98,7 @@  discard block
 block discarded – undo
98 98
      */
99 99
     protected function __construct()
100 100
     {
101
-        if (! defined('ESPRESSO_ENCRYPT')) {
101
+        if ( ! defined('ESPRESSO_ENCRYPT')) {
102 102
             define('ESPRESSO_ENCRYPT', true);
103 103
         }
104 104
         if (extension_loaded('openssl')) {
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
     public static function instance()
122 122
     {
123 123
         // check if class object is instantiated
124
-        if (! EE_Encryption::$_instance instanceof EE_Encryption) {
124
+        if ( ! EE_Encryption::$_instance instanceof EE_Encryption) {
125 125
             EE_Encryption::$_instance = new self();
126 126
         }
127 127
         return EE_Encryption::$_instance;
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
             $iv
334 334
         );
335 335
         // append the initialization vector
336
-        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER . $iv;
336
+        $encrypted_text .= EE_Encryption::OPENSSL_IV_DELIMITER.$iv;
337 337
         // trim and maybe encode
338 338
         return $this->_use_base64_encode
339 339
             ? trim(base64_encode($encrypted_text))
@@ -356,7 +356,7 @@  discard block
 block discarded – undo
356 356
      */
357 357
     protected function getCipherMethod($cipher_method = EE_Encryption::OPENSSL_CIPHER_METHOD)
358 358
     {
359
-        if($this->cipher_method !== ''){
359
+        if ($this->cipher_method !== '') {
360 360
             return $this->cipher_method;
361 361
         }
362 362
         // verify that the default cipher method can produce an initialization vector
@@ -364,7 +364,7 @@  discard block
 block discarded – undo
364 364
             // nope? okay let's get what we found in the past to work
365 365
             $cipher_method = get_option(EE_Encryption::OPENSSL_CIPHER_METHOD_OPTION_NAME, '');
366 366
             // oops... haven't tested available cipher methods yet
367
-            if($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
367
+            if ($cipher_method === '' || openssl_cipher_iv_length($cipher_method) === false) {
368 368
                 $cipher_method = $this->getAvailableCipherMethod($cipher_method);
369 369
             }
370 370
         }
@@ -390,7 +390,7 @@  discard block
 block discarded – undo
390 390
                 // then grab the first item from the list
391 391
                 $cipher_method = reset($this->cipher_methods);
392 392
             }
393
-            if($cipher_method === false){
393
+            if ($cipher_method === false) {
394 394
                 throw new RuntimeException(
395 395
                     esc_html__(
396 396
                         'OpenSSL support appears to be enabled on the server, but no cipher methods are available. Please contact the server administrator.',
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
         $decrypted_text = openssl_decrypt(
447 447
             $encrypted_components[0],
448 448
             $this->getCipherMethod($cipher_method),
449
-            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD,$encryption_key),
449
+            $this->getDigestHashValue(EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key),
450 450
             0,
451 451
             $encrypted_components[1]
452 452
         );
@@ -465,7 +465,7 @@  discard block
 block discarded – undo
465 465
      * @return string
466 466
      * @throws RuntimeException
467 467
      */
468
-    protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = ''){
468
+    protected function getDigestHashValue($digest_method = EE_Encryption::OPENSSL_DIGEST_METHOD, $encryption_key = '') {
469 469
         $encryption_key = $encryption_key !== ''
470 470
             ? $encryption_key
471 471
             : $this->get_encryption_key();
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
      * @return string
487 487
      * @throws \RuntimeException
488 488
      */
489
-    protected function getDigestMethod(){
489
+    protected function getDigestMethod() {
490 490
         $digest_method = prev($this->digest_methods);
491 491
         if (empty($this->digest_methods)) {
492 492
             $this->digest_methods = openssl_get_md_methods();
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
         if (
561 561
             $this->_use_mcrypt
562 562
             && strpos($encrypted_text, EE_Encryption::ACME_ENCRYPTION_FLAG) === false
563
-        ){
563
+        ) {
564 564
             return $this->m_decrypt($encrypted_text);
565 565
         }
566 566
         $encrypted_text = substr($encrypted_text, 0, -4);
@@ -590,16 +590,16 @@  discard block
 block discarded – undo
590 590
     protected function valid_base_64($string)
591 591
     {
592 592
         // ensure data is a string
593
-        if (! is_string($string) || ! $this->_use_base64_encode) {
593
+        if ( ! is_string($string) || ! $this->_use_base64_encode) {
594 594
             return false;
595 595
         }
596 596
         $decoded = base64_decode($string, true);
597 597
         // Check if there is no invalid character in string
598
-        if (! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
598
+        if ( ! preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) {
599 599
             return false;
600 600
         }
601 601
         // Decode the string in strict mode and send the response
602
-        if (! base64_decode($string, true)) {
602
+        if ( ! base64_decode($string, true)) {
603 603
             return false;
604 604
         }
605 605
         // Encode and compare it to original one
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
         $iterations = ceil($length / 40);
621 621
         $random_string = '';
622 622
         for ($i = 0; $i < $iterations; $i++) {
623
-            $random_string .= sha1(microtime(true) . mt_rand(10000, 90000));
623
+            $random_string .= sha1(microtime(true).mt_rand(10000, 90000));
624 624
         }
625 625
         $random_string = substr($random_string, 0, $length);
626 626
         return $random_string;
Please login to merge, or discard this patch.
core/db_models/EEM_Line_Item.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -416,7 +416,7 @@
 block discarded – undo
416 416
      * If $expired is set to true, then only line items for expired sessions will be returned.
417 417
      * If $expired is set to false, then only line items for active sessions will be returned.
418 418
      *
419
-     * @param null $expired
419
+     * @param boolean $expired
420 420
      * @return EE_Base_Class[]|EE_Line_Item[]
421 421
      * @throws EE_Error
422 422
      * @throws InvalidArgumentException
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
 use EventEspresso\core\exceptions\InvalidInterfaceException;
5 5
 use EventEspresso\core\services\loaders\LoaderFactory;
6 6
 
7
-if (!defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
7
+if ( ! defined('EVENT_ESPRESSO_VERSION')) exit('No direct script access allowed');
8 8
 
9 9
 /**
10 10
  * Event Espresso
@@ -211,8 +211,8 @@  discard block
 block discarded – undo
211 211
         );
212 212
         $query = $wpdb->prepare(
213 213
             'DELETE li
214
-				FROM ' . $this->table() . ' li
215
-				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
214
+				FROM ' . $this->table().' li
215
+				LEFT JOIN ' . EEM_Transaction::instance()->table().' t ON li.TXN_ID = t.TXN_ID
216 216
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
217 217
             // use GMT time because that's what TXN_timestamps are in
218 218
             date('Y-m-d H:i:s', time() - $time_to_leave_alone)
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
         $query_params = array(
254 254
             'OBJ_type' => $OBJ_type,
255 255
             // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
256
-            'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
256
+            'OBJ_ID' => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
257 257
         );
258 258
         if ($TXN_ID) {
259 259
             $query_params['TXN_ID'] = $TXN_ID;
@@ -456,7 +456,7 @@  discard block
 block discarded – undo
456 456
      */
457 457
     public function getTicketLineItemsForExpiredCarts($timestamp = 0)
458 458
     {
459
-        if(! absint($timestamp)) {
459
+        if ( ! absint($timestamp)) {
460 460
             /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
461 461
             $session_lifespan = LoaderFactory::getLoader()->getShared(
462 462
                 'EventEspresso\core\domain\values\session\SessionLifespan'
Please login to merge, or discard this patch.
Indentation   +436 added lines, -436 removed lines patch added patch discarded remove patch
@@ -47,444 +47,444 @@
 block discarded – undo
47 47
 class EEM_Line_Item extends EEM_Base
48 48
 {
49 49
 
50
-    /**
51
-     * Tax sub-total is just the total of all the taxes, which should be children
52
-     * of this line item. There should only ever be one tax sub-total, and it should
53
-     * be a direct child of. Its quantity and LIN_unit_price = 1.
54
-     */
55
-    const type_tax_sub_total = 'tax-sub-total';
56
-
57
-    /**
58
-     * Tax line items indicate a tax applied to all the taxable line items.
59
-     * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
60
-     * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
61
-     */
62
-    const type_tax = 'tax';
63
-
64
-    /**
65
-     * Indicating individual items purchased, or discounts or surcharges.
66
-     * The sum of all the regular line items  plus the tax items should equal
67
-     * the grand total.
68
-     * Possible children are sub-line-items and cancellations.
69
-     * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
70
-     * LIN_totals. Its LIN_percent = 0.
71
-     * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
72
-     * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
73
-     */
74
-    const type_line_item = 'line-item';
75
-
76
-    /**
77
-     * Line item indicating all the factors that make a single line item.
78
-     * Sub-line items should have NO children line items.
79
-     * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
80
-     * contribution towards the price of ONE of their parent items, and its LIN_total should be
81
-     *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
82
-     * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
83
-     * = LIN_percent / 100 * sum of lower-priority sibling line items..
84
-     */
85
-    const type_sub_line_item = 'sub-item';
86
-
87
-    /**
88
-     * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
89
-     * Direct children should be event subtotals.
90
-     * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
91
-     *
92
-     */
93
-    const type_sub_total = 'sub-total';
94
-
95
-    /**
96
-     * Line item for the grand total of an order. Its direct children
97
-     * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
98
-     * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
99
-     * the entire order's mount.
100
-     */
101
-    const type_total = 'total';
102
-
103
-    /**
104
-     * When a line item is cancelled, a sub-line-item of type 'cancellation'
105
-     * should be created, indicating the quantity that were cancelled
106
-     * (because a line item could have a quantity of 1, and its cancellation item
107
-     * could be for 3, indicating that originally 4 were purchased, but 3 have been
108
-     * cancelled, and only one remains).
109
-     * When items are refunded, a cancellation line item should be made, which points
110
-     * to teh payment model object which actually refunded the payment.
111
-     * Cancellations should NOT have any children line items; the should NOT affect
112
-     * any calculations, and are only meant as a record that cancellations have occurred.
113
-     * Their LIN_percent should be 0.
114
-     */
115
-    const type_cancellation = 'cancellation';
116
-
117
-    // private instance of the EEM_Line_Item object
118
-    protected static $_instance = NULL;
119
-
120
-
121
-    /**
122
-     *        private constructor to prevent direct creation
123
-     * @Constructor
124
-     * @access protected
125
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
126
-     * @return \EEM_Line_Item
127
-     */
128
-    protected function __construct($timezone)
129
-    {
130
-        $this->singular_item = __('Line Item', 'event_espresso');
131
-        $this->plural_item = __('Line Items', 'event_espresso');
132
-
133
-        $this->_tables = array(
134
-            'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
135
-        );
136
-        $line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
137
-        $this->_fields = array(
138
-            'Line_Item' => array(
139
-                'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
140
-                'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), TRUE),
141
-                'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), TRUE, NULL, 'Transaction'),
142
-                'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), FALSE, ''),
143
-                'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), TRUE),
144
-                'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), FALSE, 0),
145
-                'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), FALSE, 0),
146
-                'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), FALSE, FALSE),
147
-                'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), FALSE, 1),
148
-                'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), FALSE, 0),
149
-                'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), TRUE, 1),
150
-                'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), TRUE, NULL),
151
-                'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), FALSE, 'line-item', array(
152
-                        self::type_line_item => __("Line Item", "event_espresso"),
153
-                        self::type_sub_line_item => __("Sub-Item", "event_espresso"),
154
-                        self::type_sub_total => __("Subtotal", "event_espresso"),
155
-                        self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
156
-                        self::type_tax => __("Tax", "event_espresso"),
157
-                        self::type_total => __("Total", "event_espresso"),
158
-                        self::type_cancellation => __('Cancellation', 'event_espresso')
159
-                    )
160
-                ),
161
-                'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), TRUE, NULL, $line_items_can_be_for),
162
-                'OBJ_type' => new EE_Any_Foreign_Model_Name_Field('OBJ_type', __("Model Name this Line Item is for", "event_espresso"), TRUE, NULL, $line_items_can_be_for),
163
-                'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
164
-            )
165
-        );
166
-        $this->_model_relations = array(
167
-            'Transaction' => new EE_Belongs_To_Relation(),
168
-            'Ticket' => new EE_Belongs_To_Any_Relation(),
169
-            'Price' => new EE_Belongs_To_Any_Relation(),
170
-            'Event' => new EE_Belongs_To_Any_Relation()
171
-        );
172
-        $this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
173
-        $this->_caps_slug = 'transactions';
174
-        parent::__construct($timezone);
175
-    }
176
-
177
-
178
-    /**
179
-     * Gets all the line items for this transaction of the given type
180
-     * @param string $line_item_type like one of EEM_Line_Item::type_*
181
-     * @param EE_Transaction|int $transaction
182
-     * @return EE_Line_Item[]
183
-     */
184
-    public function get_all_of_type_for_transaction($line_item_type, $transaction)
185
-    {
186
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
-        return $this->get_all(array(array(
188
-            'LIN_type' => $line_item_type,
189
-            'TXN_ID' => $transaction
190
-        )));
191
-    }
192
-
193
-
194
-    /**
195
-     * Gets all line items unrelated to tickets that are normal line items
196
-     * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
197
-     * @param EE_Transaction|int $transaction
198
-     * @return EE_Line_Item[]
199
-     */
200
-    public function get_all_non_ticket_line_items_for_transaction($transaction)
201
-    {
202
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
203
-        return $this->get_all(array(array(
204
-            'LIN_type' => self::type_line_item,
205
-            'TXN_ID' => $transaction,
206
-            'OR' => array(
207
-                'OBJ_type*notticket' => array('!=', 'Ticket'),
208
-                'OBJ_type*null' => array('IS_NULL'))
209
-        )));
210
-    }
211
-
212
-    /**
213
-     * Deletes line items with no transaction who have passed the transaction cutoff time.
214
-     * This needs to be very efficient
215
-     * because if there are spam bots afoot there will be LOTS of line items
216
-     * @return int count of how many deleted
217
-     */
218
-    public function delete_line_items_with_no_transaction()
219
-    {
220
-        /** @type WPDB $wpdb */
221
-        global $wpdb;
222
-        $time_to_leave_alone = apply_filters(
223
-            'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', WEEK_IN_SECONDS
224
-        );
225
-        $query = $wpdb->prepare(
226
-            'DELETE li
50
+	/**
51
+	 * Tax sub-total is just the total of all the taxes, which should be children
52
+	 * of this line item. There should only ever be one tax sub-total, and it should
53
+	 * be a direct child of. Its quantity and LIN_unit_price = 1.
54
+	 */
55
+	const type_tax_sub_total = 'tax-sub-total';
56
+
57
+	/**
58
+	 * Tax line items indicate a tax applied to all the taxable line items.
59
+	 * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
60
+	 * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
61
+	 */
62
+	const type_tax = 'tax';
63
+
64
+	/**
65
+	 * Indicating individual items purchased, or discounts or surcharges.
66
+	 * The sum of all the regular line items  plus the tax items should equal
67
+	 * the grand total.
68
+	 * Possible children are sub-line-items and cancellations.
69
+	 * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
70
+	 * LIN_totals. Its LIN_percent = 0.
71
+	 * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
72
+	 * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
73
+	 */
74
+	const type_line_item = 'line-item';
75
+
76
+	/**
77
+	 * Line item indicating all the factors that make a single line item.
78
+	 * Sub-line items should have NO children line items.
79
+	 * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
80
+	 * contribution towards the price of ONE of their parent items, and its LIN_total should be
81
+	 *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
82
+	 * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
83
+	 * = LIN_percent / 100 * sum of lower-priority sibling line items..
84
+	 */
85
+	const type_sub_line_item = 'sub-item';
86
+
87
+	/**
88
+	 * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
89
+	 * Direct children should be event subtotals.
90
+	 * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
91
+	 *
92
+	 */
93
+	const type_sub_total = 'sub-total';
94
+
95
+	/**
96
+	 * Line item for the grand total of an order. Its direct children
97
+	 * should be tax subtotals and (pre-tax) subtotals, and possibly a regular line item
98
+	 * indicating a transaction-wide discount/surcharge. Should have a quantity of 1, a LIN_total and LIN_unit_price of
99
+	 * the entire order's mount.
100
+	 */
101
+	const type_total = 'total';
102
+
103
+	/**
104
+	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
105
+	 * should be created, indicating the quantity that were cancelled
106
+	 * (because a line item could have a quantity of 1, and its cancellation item
107
+	 * could be for 3, indicating that originally 4 were purchased, but 3 have been
108
+	 * cancelled, and only one remains).
109
+	 * When items are refunded, a cancellation line item should be made, which points
110
+	 * to teh payment model object which actually refunded the payment.
111
+	 * Cancellations should NOT have any children line items; the should NOT affect
112
+	 * any calculations, and are only meant as a record that cancellations have occurred.
113
+	 * Their LIN_percent should be 0.
114
+	 */
115
+	const type_cancellation = 'cancellation';
116
+
117
+	// private instance of the EEM_Line_Item object
118
+	protected static $_instance = NULL;
119
+
120
+
121
+	/**
122
+	 *        private constructor to prevent direct creation
123
+	 * @Constructor
124
+	 * @access protected
125
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any incoming timezone data that gets saved).  Note this just sends the timezone info to the date time model field objects.  Default is NULL (and will be assumed using the set timezone in the 'timezone_string' wp option)
126
+	 * @return \EEM_Line_Item
127
+	 */
128
+	protected function __construct($timezone)
129
+	{
130
+		$this->singular_item = __('Line Item', 'event_espresso');
131
+		$this->plural_item = __('Line Items', 'event_espresso');
132
+
133
+		$this->_tables = array(
134
+			'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID')
135
+		);
136
+		$line_items_can_be_for = apply_filters('FHEE__EEM_Line_Item__line_items_can_be_for', array('Ticket', 'Price', 'Event'));
137
+		$this->_fields = array(
138
+			'Line_Item' => array(
139
+				'LIN_ID' => new EE_Primary_Key_Int_Field('LIN_ID', __("ID", "event_espresso")),
140
+				'LIN_code' => new EE_Slug_Field('LIN_code', __("Code for index into Cart", "event_espresso"), TRUE),
141
+				'TXN_ID' => new EE_Foreign_Key_Int_Field('TXN_ID', __("Transaction ID", "event_espresso"), TRUE, NULL, 'Transaction'),
142
+				'LIN_name' => new EE_Full_HTML_Field('LIN_name', __("Line Item Name", "event_espresso"), FALSE, ''),
143
+				'LIN_desc' => new EE_Full_HTML_Field('LIN_desc', __("Line Item Description", "event_espresso"), TRUE),
144
+				'LIN_unit_price' => new EE_Money_Field('LIN_unit_price', __("Unit Price", "event_espresso"), FALSE, 0),
145
+				'LIN_percent' => new EE_Float_Field('LIN_percent', __("Percent", "event_espresso"), FALSE, 0),
146
+				'LIN_is_taxable' => new EE_Boolean_Field('LIN_is_taxable', __("Taxable", "event_espresso"), FALSE, FALSE),
147
+				'LIN_order' => new EE_Integer_Field('LIN_order', __("Order of Application towards total of parent", "event_espresso"), FALSE, 1),
148
+				'LIN_total' => new EE_Money_Field('LIN_total', __("Total (unit price x quantity)", "event_espresso"), FALSE, 0),
149
+				'LIN_quantity' => new EE_Integer_Field('LIN_quantity', __("Quantity", "event_espresso"), TRUE, 1),
150
+				'LIN_parent' => new EE_Integer_Field('LIN_parent', __("Parent ID (this item goes towards that Line Item's total)", "event_espresso"), TRUE, NULL),
151
+				'LIN_type' => new EE_Enum_Text_Field('LIN_type', __("Type", "event_espresso"), FALSE, 'line-item', array(
152
+						self::type_line_item => __("Line Item", "event_espresso"),
153
+						self::type_sub_line_item => __("Sub-Item", "event_espresso"),
154
+						self::type_sub_total => __("Subtotal", "event_espresso"),
155
+						self::type_tax_sub_total => __("Tax Subtotal", "event_espresso"),
156
+						self::type_tax => __("Tax", "event_espresso"),
157
+						self::type_total => __("Total", "event_espresso"),
158
+						self::type_cancellation => __('Cancellation', 'event_espresso')
159
+					)
160
+				),
161
+				'OBJ_ID' => new EE_Foreign_Key_Int_Field('OBJ_ID', __('ID of Item purchased.', 'event_espresso'), TRUE, NULL, $line_items_can_be_for),
162
+				'OBJ_type' => new EE_Any_Foreign_Model_Name_Field('OBJ_type', __("Model Name this Line Item is for", "event_espresso"), TRUE, NULL, $line_items_can_be_for),
163
+				'LIN_timestamp' => new EE_Datetime_Field('LIN_timestamp', __('When the line item was created', 'event_espresso'), false, EE_Datetime_Field::now, $timezone),
164
+			)
165
+		);
166
+		$this->_model_relations = array(
167
+			'Transaction' => new EE_Belongs_To_Relation(),
168
+			'Ticket' => new EE_Belongs_To_Any_Relation(),
169
+			'Price' => new EE_Belongs_To_Any_Relation(),
170
+			'Event' => new EE_Belongs_To_Any_Relation()
171
+		);
172
+		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
173
+		$this->_caps_slug = 'transactions';
174
+		parent::__construct($timezone);
175
+	}
176
+
177
+
178
+	/**
179
+	 * Gets all the line items for this transaction of the given type
180
+	 * @param string $line_item_type like one of EEM_Line_Item::type_*
181
+	 * @param EE_Transaction|int $transaction
182
+	 * @return EE_Line_Item[]
183
+	 */
184
+	public function get_all_of_type_for_transaction($line_item_type, $transaction)
185
+	{
186
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
187
+		return $this->get_all(array(array(
188
+			'LIN_type' => $line_item_type,
189
+			'TXN_ID' => $transaction
190
+		)));
191
+	}
192
+
193
+
194
+	/**
195
+	 * Gets all line items unrelated to tickets that are normal line items
196
+	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
197
+	 * @param EE_Transaction|int $transaction
198
+	 * @return EE_Line_Item[]
199
+	 */
200
+	public function get_all_non_ticket_line_items_for_transaction($transaction)
201
+	{
202
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
203
+		return $this->get_all(array(array(
204
+			'LIN_type' => self::type_line_item,
205
+			'TXN_ID' => $transaction,
206
+			'OR' => array(
207
+				'OBJ_type*notticket' => array('!=', 'Ticket'),
208
+				'OBJ_type*null' => array('IS_NULL'))
209
+		)));
210
+	}
211
+
212
+	/**
213
+	 * Deletes line items with no transaction who have passed the transaction cutoff time.
214
+	 * This needs to be very efficient
215
+	 * because if there are spam bots afoot there will be LOTS of line items
216
+	 * @return int count of how many deleted
217
+	 */
218
+	public function delete_line_items_with_no_transaction()
219
+	{
220
+		/** @type WPDB $wpdb */
221
+		global $wpdb;
222
+		$time_to_leave_alone = apply_filters(
223
+			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone', WEEK_IN_SECONDS
224
+		);
225
+		$query = $wpdb->prepare(
226
+			'DELETE li
227 227
 				FROM ' . $this->table() . ' li
228 228
 				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
229 229
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
230
-            // use GMT time because that's what TXN_timestamps are in
231
-            date('Y-m-d H:i:s', time() - $time_to_leave_alone)
232
-        );
233
-        return $wpdb->query($query);
234
-    }
235
-
236
-
237
-    /**
238
-     * get_line_item_for_transaction_object
239
-     * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
240
-     *
241
-     * @param int $TXN_ID
242
-     * @param \EE_Base_Class $object
243
-     * @return EE_Line_Item[]
244
-     */
245
-    public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
246
-    {
247
-        return $this->get_all(array(array(
248
-            'TXN_ID' => $TXN_ID,
249
-            'OBJ_type' => str_replace('EE_', '', get_class($object)),
250
-            'OBJ_ID' => $object->ID()
251
-        )));
252
-    }
253
-
254
-
255
-    /**
256
-     * get_object_line_items_for_transaction
257
-     * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
258
-     *
259
-     * @param int $TXN_ID
260
-     * @param string $OBJ_type
261
-     * @param array $OBJ_IDs
262
-     * @return EE_Line_Item[]
263
-     */
264
-    public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
265
-    {
266
-        $query_params = array(
267
-            'OBJ_type' => $OBJ_type,
268
-            // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
269
-            'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
270
-        );
271
-        if ($TXN_ID) {
272
-            $query_params['TXN_ID'] = $TXN_ID;
273
-        }
274
-        return $this->get_all(array($query_params));
275
-    }
276
-
277
-
278
-    /**
279
-     * get_all_ticket_line_items_for_transaction
280
-     *
281
-     * @param EE_Transaction $transaction
282
-     * @return EE_Line_Item[]
283
-     */
284
-    public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
285
-    {
286
-        return $this->get_all(array(
287
-            array(
288
-                'TXN_ID' => $transaction->ID(),
289
-                'OBJ_type' => 'Ticket',
290
-            )
291
-        ));
292
-    }
293
-
294
-
295
-    /**
296
-     * get_ticket_line_item_for_transaction
297
-     *
298
-     * @param int $TXN_ID
299
-     * @param int $TKT_ID
300
-     * @return \EE_Line_Item
301
-     */
302
-    public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
303
-    {
304
-        return $this->get_one(array(
305
-            array(
306
-                'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
307
-                'OBJ_ID' => $TKT_ID,
308
-                'OBJ_type' => 'Ticket',
309
-            )
310
-        ));
311
-    }
312
-
313
-
314
-    /**
315
-     * get_existing_promotion_line_item
316
-     * searches the cart for existing line items for the specified promotion
317
-     *
318
-     * @since   1.0.0
319
-     *
320
-     * @param EE_Line_Item $parent_line_item
321
-     * @param EE_Promotion $promotion
322
-     * @return EE_Line_Item
323
-     */
324
-    public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
325
-    {
326
-        return $this->get_one(array(
327
-            array(
328
-                'TXN_ID' => $parent_line_item->TXN_ID(),
329
-                'LIN_parent' => $parent_line_item->ID(),
330
-                'OBJ_type' => 'Promotion',
331
-                'OBJ_ID' => $promotion->ID()
332
-            )
333
-        ));
334
-    }
335
-
336
-
337
-    /**
338
-     * get_all_promotion_line_items
339
-     * searches the cart for any and all existing promotion line items
340
-     *
341
-     * @since   1.0.0
342
-     *
343
-     * @param EE_Line_Item $parent_line_item
344
-     * @return EE_Line_Item[]
345
-     */
346
-    public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
347
-    {
348
-        return $this->get_all(array(
349
-            array(
350
-                'TXN_ID' => $parent_line_item->TXN_ID(),
351
-                'LIN_parent' => $parent_line_item->ID(),
352
-                'OBJ_type' => 'Promotion'
353
-            )
354
-        ));
355
-    }
356
-
357
-    /**
358
-     * Gets the registration's corresponding line item.
359
-     * Note: basically does NOT support having multiple line items for a single ticket,
360
-     * which would happen if some of the registrations had a price modifier while others didn't.
361
-     * In order to support that, we'd probably need a LIN_ID on registrations or something.
362
-     * @param EE_Registration $registration
363
-     * @return EE_Line_ITem
364
-     */
365
-    public function get_line_item_for_registration(EE_Registration $registration)
366
-    {
367
-        return $this->get_one($this->line_item_for_registration_query_params($registration));
368
-    }
369
-
370
-    /**
371
-     * Gets the query params used to retrieve a specific line item for the given registration
372
-     * @param EE_Registration $registration
373
-     * @param array $original_query_params any extra query params you'd like to be merged with
374
-     * @return array like EEM_Base::get_all()'s $query_params
375
-     */
376
-    public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
377
-    {
378
-        return array_replace_recursive($original_query_params, array(
379
-            array(
380
-                'OBJ_ID' => $registration->ticket_ID(),
381
-                'OBJ_type' => 'Ticket',
382
-                'TXN_ID' => $registration->transaction_ID()
383
-            )
384
-        ));
385
-    }
386
-
387
-
388
-    /**
389
-     * @return EE_Base_Class[]|EE_Line_Item[]
390
-     * @throws InvalidInterfaceException
391
-     * @throws InvalidDataTypeException
392
-     * @throws EE_Error
393
-     * @throws InvalidArgumentException
394
-     */
395
-    public function get_total_line_items_with_no_transaction()
396
-    {
397
-        return $this->get_total_line_items_for_carts();
398
-    }
399
-
400
-
401
-    /**
402
-     * @return EE_Base_Class[]|EE_Line_Item[]
403
-     * @throws InvalidInterfaceException
404
-     * @throws InvalidDataTypeException
405
-     * @throws EE_Error
406
-     * @throws InvalidArgumentException
407
-     */
408
-    public function get_total_line_items_for_active_carts()
409
-    {
410
-        return $this->get_total_line_items_for_carts(false);
411
-    }
412
-
413
-
414
-    /**
415
-     * @return EE_Base_Class[]|EE_Line_Item[]
416
-     * @throws InvalidInterfaceException
417
-     * @throws InvalidDataTypeException
418
-     * @throws EE_Error
419
-     * @throws InvalidArgumentException
420
-     */
421
-    public function get_total_line_items_for_expired_carts()
422
-    {
423
-        return $this->get_total_line_items_for_carts(true);
424
-    }
425
-
426
-
427
-    /**
428
-     * Returns an array of grand total line items where the TXN_ID is 0.
429
-     * If $expired is set to true, then only line items for expired sessions will be returned.
430
-     * If $expired is set to false, then only line items for active sessions will be returned.
431
-     *
432
-     * @param null $expired
433
-     * @return EE_Base_Class[]|EE_Line_Item[]
434
-     * @throws EE_Error
435
-     * @throws InvalidArgumentException
436
-     * @throws InvalidDataTypeException
437
-     * @throws InvalidInterfaceException
438
-     */
439
-    private function get_total_line_items_for_carts($expired = null)
440
-    {
441
-        $where_params = array(
442
-            'TXN_ID' => 0,
443
-            'LIN_type' => 'total',
444
-        );
445
-        if ($expired !== null) {
446
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
447
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
448
-                'EventEspresso\core\domain\values\session\SessionLifespan'
449
-            );
450
-            $where_params['LIN_timestamp'] = array(
451
-                $expired ? '<=' : '>',
452
-                $session_lifespan->expiration(),
453
-            );
454
-        }
455
-        return $this->get_all(array($where_params));
456
-    }
457
-
458
-
459
-    /**
460
-     * Returns an array of ticket total line items where the TXN_ID is 0
461
-     * AND the timestamp is older than the session lifespan.
462
-     *
463
-     * @param int $timestamp
464
-     * @return EE_Base_Class[]|EE_Line_Item[]
465
-     * @throws EE_Error
466
-     * @throws InvalidArgumentException
467
-     * @throws InvalidDataTypeException
468
-     * @throws InvalidInterfaceException
469
-     */
470
-    public function getTicketLineItemsForExpiredCarts($timestamp = 0)
471
-    {
472
-        if(! absint($timestamp)) {
473
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
474
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
475
-                'EventEspresso\core\domain\values\session\SessionLifespan'
476
-            );
477
-            $timestamp = $session_lifespan->expiration();
478
-        }
479
-        return $this->get_all(
480
-            array(
481
-                array(
482
-                    'TXN_ID'        => 0,
483
-                    'OBJ_type'      => 'Ticket',
484
-                    'LIN_timestamp' => array('<=', $timestamp),
485
-                )
486
-            )
487
-        );
488
-    }
230
+			// use GMT time because that's what TXN_timestamps are in
231
+			date('Y-m-d H:i:s', time() - $time_to_leave_alone)
232
+		);
233
+		return $wpdb->query($query);
234
+	}
235
+
236
+
237
+	/**
238
+	 * get_line_item_for_transaction_object
239
+	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
240
+	 *
241
+	 * @param int $TXN_ID
242
+	 * @param \EE_Base_Class $object
243
+	 * @return EE_Line_Item[]
244
+	 */
245
+	public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
246
+	{
247
+		return $this->get_all(array(array(
248
+			'TXN_ID' => $TXN_ID,
249
+			'OBJ_type' => str_replace('EE_', '', get_class($object)),
250
+			'OBJ_ID' => $object->ID()
251
+		)));
252
+	}
253
+
254
+
255
+	/**
256
+	 * get_object_line_items_for_transaction
257
+	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
258
+	 *
259
+	 * @param int $TXN_ID
260
+	 * @param string $OBJ_type
261
+	 * @param array $OBJ_IDs
262
+	 * @return EE_Line_Item[]
263
+	 */
264
+	public function get_object_line_items_for_transaction($TXN_ID, $OBJ_type = 'Event', $OBJ_IDs = array())
265
+	{
266
+		$query_params = array(
267
+			'OBJ_type' => $OBJ_type,
268
+			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
269
+			'OBJ_ID' => is_array($OBJ_IDs) && !isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs
270
+		);
271
+		if ($TXN_ID) {
272
+			$query_params['TXN_ID'] = $TXN_ID;
273
+		}
274
+		return $this->get_all(array($query_params));
275
+	}
276
+
277
+
278
+	/**
279
+	 * get_all_ticket_line_items_for_transaction
280
+	 *
281
+	 * @param EE_Transaction $transaction
282
+	 * @return EE_Line_Item[]
283
+	 */
284
+	public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
285
+	{
286
+		return $this->get_all(array(
287
+			array(
288
+				'TXN_ID' => $transaction->ID(),
289
+				'OBJ_type' => 'Ticket',
290
+			)
291
+		));
292
+	}
293
+
294
+
295
+	/**
296
+	 * get_ticket_line_item_for_transaction
297
+	 *
298
+	 * @param int $TXN_ID
299
+	 * @param int $TKT_ID
300
+	 * @return \EE_Line_Item
301
+	 */
302
+	public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
303
+	{
304
+		return $this->get_one(array(
305
+			array(
306
+				'TXN_ID' => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
307
+				'OBJ_ID' => $TKT_ID,
308
+				'OBJ_type' => 'Ticket',
309
+			)
310
+		));
311
+	}
312
+
313
+
314
+	/**
315
+	 * get_existing_promotion_line_item
316
+	 * searches the cart for existing line items for the specified promotion
317
+	 *
318
+	 * @since   1.0.0
319
+	 *
320
+	 * @param EE_Line_Item $parent_line_item
321
+	 * @param EE_Promotion $promotion
322
+	 * @return EE_Line_Item
323
+	 */
324
+	public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
325
+	{
326
+		return $this->get_one(array(
327
+			array(
328
+				'TXN_ID' => $parent_line_item->TXN_ID(),
329
+				'LIN_parent' => $parent_line_item->ID(),
330
+				'OBJ_type' => 'Promotion',
331
+				'OBJ_ID' => $promotion->ID()
332
+			)
333
+		));
334
+	}
335
+
336
+
337
+	/**
338
+	 * get_all_promotion_line_items
339
+	 * searches the cart for any and all existing promotion line items
340
+	 *
341
+	 * @since   1.0.0
342
+	 *
343
+	 * @param EE_Line_Item $parent_line_item
344
+	 * @return EE_Line_Item[]
345
+	 */
346
+	public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
347
+	{
348
+		return $this->get_all(array(
349
+			array(
350
+				'TXN_ID' => $parent_line_item->TXN_ID(),
351
+				'LIN_parent' => $parent_line_item->ID(),
352
+				'OBJ_type' => 'Promotion'
353
+			)
354
+		));
355
+	}
356
+
357
+	/**
358
+	 * Gets the registration's corresponding line item.
359
+	 * Note: basically does NOT support having multiple line items for a single ticket,
360
+	 * which would happen if some of the registrations had a price modifier while others didn't.
361
+	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
362
+	 * @param EE_Registration $registration
363
+	 * @return EE_Line_ITem
364
+	 */
365
+	public function get_line_item_for_registration(EE_Registration $registration)
366
+	{
367
+		return $this->get_one($this->line_item_for_registration_query_params($registration));
368
+	}
369
+
370
+	/**
371
+	 * Gets the query params used to retrieve a specific line item for the given registration
372
+	 * @param EE_Registration $registration
373
+	 * @param array $original_query_params any extra query params you'd like to be merged with
374
+	 * @return array like EEM_Base::get_all()'s $query_params
375
+	 */
376
+	public function line_item_for_registration_query_params(EE_Registration $registration, $original_query_params = array())
377
+	{
378
+		return array_replace_recursive($original_query_params, array(
379
+			array(
380
+				'OBJ_ID' => $registration->ticket_ID(),
381
+				'OBJ_type' => 'Ticket',
382
+				'TXN_ID' => $registration->transaction_ID()
383
+			)
384
+		));
385
+	}
386
+
387
+
388
+	/**
389
+	 * @return EE_Base_Class[]|EE_Line_Item[]
390
+	 * @throws InvalidInterfaceException
391
+	 * @throws InvalidDataTypeException
392
+	 * @throws EE_Error
393
+	 * @throws InvalidArgumentException
394
+	 */
395
+	public function get_total_line_items_with_no_transaction()
396
+	{
397
+		return $this->get_total_line_items_for_carts();
398
+	}
399
+
400
+
401
+	/**
402
+	 * @return EE_Base_Class[]|EE_Line_Item[]
403
+	 * @throws InvalidInterfaceException
404
+	 * @throws InvalidDataTypeException
405
+	 * @throws EE_Error
406
+	 * @throws InvalidArgumentException
407
+	 */
408
+	public function get_total_line_items_for_active_carts()
409
+	{
410
+		return $this->get_total_line_items_for_carts(false);
411
+	}
412
+
413
+
414
+	/**
415
+	 * @return EE_Base_Class[]|EE_Line_Item[]
416
+	 * @throws InvalidInterfaceException
417
+	 * @throws InvalidDataTypeException
418
+	 * @throws EE_Error
419
+	 * @throws InvalidArgumentException
420
+	 */
421
+	public function get_total_line_items_for_expired_carts()
422
+	{
423
+		return $this->get_total_line_items_for_carts(true);
424
+	}
425
+
426
+
427
+	/**
428
+	 * Returns an array of grand total line items where the TXN_ID is 0.
429
+	 * If $expired is set to true, then only line items for expired sessions will be returned.
430
+	 * If $expired is set to false, then only line items for active sessions will be returned.
431
+	 *
432
+	 * @param null $expired
433
+	 * @return EE_Base_Class[]|EE_Line_Item[]
434
+	 * @throws EE_Error
435
+	 * @throws InvalidArgumentException
436
+	 * @throws InvalidDataTypeException
437
+	 * @throws InvalidInterfaceException
438
+	 */
439
+	private function get_total_line_items_for_carts($expired = null)
440
+	{
441
+		$where_params = array(
442
+			'TXN_ID' => 0,
443
+			'LIN_type' => 'total',
444
+		);
445
+		if ($expired !== null) {
446
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
447
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
448
+				'EventEspresso\core\domain\values\session\SessionLifespan'
449
+			);
450
+			$where_params['LIN_timestamp'] = array(
451
+				$expired ? '<=' : '>',
452
+				$session_lifespan->expiration(),
453
+			);
454
+		}
455
+		return $this->get_all(array($where_params));
456
+	}
457
+
458
+
459
+	/**
460
+	 * Returns an array of ticket total line items where the TXN_ID is 0
461
+	 * AND the timestamp is older than the session lifespan.
462
+	 *
463
+	 * @param int $timestamp
464
+	 * @return EE_Base_Class[]|EE_Line_Item[]
465
+	 * @throws EE_Error
466
+	 * @throws InvalidArgumentException
467
+	 * @throws InvalidDataTypeException
468
+	 * @throws InvalidInterfaceException
469
+	 */
470
+	public function getTicketLineItemsForExpiredCarts($timestamp = 0)
471
+	{
472
+		if(! absint($timestamp)) {
473
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
474
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
475
+				'EventEspresso\core\domain\values\session\SessionLifespan'
476
+			);
477
+			$timestamp = $session_lifespan->expiration();
478
+		}
479
+		return $this->get_all(
480
+			array(
481
+				array(
482
+					'TXN_ID'        => 0,
483
+					'OBJ_type'      => 'Ticket',
484
+					'LIN_timestamp' => array('<=', $timestamp),
485
+				)
486
+			)
487
+		);
488
+	}
489 489
 
490 490
 }
Please login to merge, or discard this patch.
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 2 patches
Indentation   +1066 added lines, -1066 removed lines patch added patch discarded remove patch
@@ -24,1073 +24,1073 @@
 block discarded – undo
24 24
 class EED_Ticket_Sales_Monitor extends EED_Module
25 25
 {
26 26
 
27
-    const debug = false;    //	true false
28
-
29
-    private static $nl = '';
30
-
31
-    /**
32
-     * an array of raw ticket data from EED_Ticket_Selector
33
-     *
34
-     * @var array $ticket_selections
35
-     */
36
-    protected $ticket_selections = array();
37
-
38
-    /**
39
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
40
-     * according to how they are displayed in the actual Ticket_Selector
41
-     * this tracks the current row being processed
42
-     *
43
-     * @var int $current_row
44
-     */
45
-    protected $current_row = 0;
46
-
47
-    /**
48
-     * an array for tracking names of tickets that have sold out
49
-     *
50
-     * @var array $sold_out_tickets
51
-     */
52
-    protected $sold_out_tickets = array();
53
-
54
-    /**
55
-     * an array for tracking names of tickets that have had their quantities reduced
56
-     *
57
-     * @var array $decremented_tickets
58
-     */
59
-    protected $decremented_tickets = array();
60
-
61
-
62
-
63
-    /**
64
-     * set_hooks - for hooking into EE Core, other modules, etc
65
-     *
66
-     * @return    void
67
-     */
68
-    public static function set_hooks()
69
-    {
70
-        self::$nl = defined('EE_TESTS_DIR')? "\n" : '<br />';
71
-        // release tickets for expired carts
72
-        add_action(
73
-            'EED_Ticket_Selector__process_ticket_selections__before',
74
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
75
-            1
76
-        );
77
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
78
-        add_filter(
79
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
80
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
81
-            20,
82
-            3
83
-        );
84
-        // add notices for sold out tickets
85
-        add_action(
86
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
87
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
88
-            10
89
-        );
90
-        // handle ticket quantities adjusted in cart
91
-        //add_action(
92
-        //	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
93
-        //	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
94
-        //	10, 2
95
-        //);
96
-        // handle tickets deleted from cart
97
-        add_action(
98
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
99
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
100
-            10,
101
-            2
102
-        );
103
-        // handle emptied carts
104
-        add_action(
105
-            'AHEE__EE_Session__reset_cart__before_reset',
106
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
107
-            10,
108
-            1
109
-        );
110
-        add_action(
111
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
112
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
113
-            10,
114
-            1
115
-        );
116
-        // handle cancelled registrations
117
-        add_action(
118
-            'AHEE__EE_Session__reset_checkout__before_reset',
119
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
120
-            10,
121
-            1
122
-        );
123
-        // cron tasks
124
-        add_action(
125
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
126
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
127
-            10,
128
-            1
129
-        );
130
-        add_action(
131
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
132
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
133
-            10,
134
-            1
135
-        );
136
-        add_action(
137
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
138
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
139
-            10,
140
-            1
141
-        );
142
-    }
143
-
144
-
145
-
146
-    /**
147
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
148
-     *
149
-     * @return void
150
-     */
151
-    public static function set_hooks_admin()
152
-    {
153
-        EED_Ticket_Sales_Monitor::set_hooks();
154
-    }
155
-
156
-
157
-
158
-    /**
159
-     * @return EED_Ticket_Sales_Monitor|EED_Module
160
-     */
161
-    public static function instance()
162
-    {
163
-        return parent::get_instance(__CLASS__);
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * @param WP_Query $WP_Query
170
-     * @return    void
171
-     */
172
-    public function run($WP_Query)
173
-    {
174
-    }
175
-
176
-
177
-
178
-    /********************************** PRE_TICKET_SALES  **********************************/
179
-
180
-
181
-
182
-    /**
183
-     * Retrieves grand totals from the line items that have no TXN ID
184
-     * and timestamps less than the current time minus the session lifespan.
185
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
186
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
187
-     *
188
-     * @return void
189
-     * @throws DomainException
190
-     * @throws EE_Error
191
-     * @throws InvalidArgumentException
192
-     * @throws InvalidDataTypeException
193
-     * @throws InvalidInterfaceException
194
-     * @throws UnexpectedEntityException
195
-     */
196
-    public static function release_tickets_for_expired_carts()
197
-    {
198
-        if (self::debug) {
199
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
200
-        }
201
-        do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
202
-        $expired_ticket_IDs = array();
203
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
204
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
205
-            'EventEspresso\core\domain\values\session\SessionLifespan'
206
-        );
207
-        $timestamp = $session_lifespan->expiration();
208
-        $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
209
-        if (self::debug) {
210
-            echo self::$nl . ' . time(): ' . time();
211
-            echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
212
-            echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
213
-            echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
214
-            echo self::$nl . ' . timestamp: ' . $timestamp;
215
-            echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
216
-        }
217
-        if (! empty($expired_ticket_line_items)) {
218
-            foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
219
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
220
-                    continue;
221
-                }
222
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
223
-                if (self::debug) {
224
-                    echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
225
-                    echo self::$nl . ' . $expired_ticket_line_item->timestamp(): ' . date('Y-m-d h:i a',
226
-                            $expired_ticket_line_item->timestamp(true));
227
-                }
228
-            }
229
-            if (! empty($expired_ticket_IDs)) {
230
-                EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
231
-                    \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
232
-                    array(),
233
-                    __FUNCTION__
234
-                );
235
-                // now  let's get rid of expired line items so that they can't interfere with tracking
236
-                EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
237
-            }
238
-        }
239
-        do_action(
240
-            'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
241
-            $expired_ticket_IDs,
242
-            $expired_ticket_line_items
243
-        );
244
-    }
245
-
246
-
247
-
248
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
249
-
250
-
251
-
252
-    /**
253
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
254
-     *
255
-     * @param int       $qty
256
-     * @param EE_Ticket $ticket
257
-     * @return bool
258
-     * @throws UnexpectedEntityException
259
-     * @throws EE_Error
260
-     */
261
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
262
-    {
263
-        $qty = absint($qty);
264
-        if ($qty > 0) {
265
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
266
-        }
267
-        if (self::debug) {
268
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
269
-            echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
270
-        }
271
-        return $qty;
272
-    }
273
-
274
-
275
-
276
-    /**
277
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
278
-     *
279
-     * @param   EE_Ticket $ticket
280
-     * @param int         $qty
281
-     * @return int
282
-     * @throws UnexpectedEntityException
283
-     * @throws EE_Error
284
-     */
285
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
286
-    {
287
-        if (self::debug) {
288
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
289
-        }
290
-        if (! $ticket instanceof EE_Ticket) {
291
-            return 0;
292
-        }
293
-        if (self::debug) {
294
-            echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
295
-            echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
296
-        }
297
-        $ticket->refresh_from_db();
298
-        // first let's determine the ticket availability based on sales
299
-        $available = $ticket->qty('saleable');
300
-        if (self::debug) {
301
-            echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
302
-            echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
303
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
304
-            echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
305
-            echo self::$nl . ' . . . available: ' . $available;
306
-        }
307
-        if ($available < 1) {
308
-            $this->_ticket_sold_out($ticket);
309
-            return 0;
310
-        }
311
-        if (self::debug) {
312
-            echo self::$nl . ' . . . qty: ' . $qty;
313
-        }
314
-        if ($available < $qty) {
315
-            $qty = $available;
316
-            if (self::debug) {
317
-                echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
318
-            }
319
-            $this->_ticket_quantity_decremented($ticket);
320
-        }
321
-        $this->_reserve_ticket($ticket, $qty);
322
-        return $qty;
323
-    }
324
-
325
-
326
-
327
-    /**
328
-     * increments ticket reserved based on quantity passed
329
-     *
330
-     * @param    EE_Ticket $ticket
331
-     * @param int          $quantity
332
-     * @return bool
333
-     * @throws EE_Error
334
-     */
335
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
336
-    {
337
-        if (self::debug) {
338
-            echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
339
-        }
340
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
341
-        return $ticket->save();
342
-    }
343
-
344
-
345
-
346
-    /**
347
-     * @param  EE_Ticket $ticket
348
-     * @param  int       $quantity
349
-     * @return bool
350
-     * @throws EE_Error
351
-     */
352
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
353
-    {
354
-        if (self::debug) {
355
-            echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
356
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
357
-        }
358
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
359
-        if (self::debug) {
360
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
361
-        }
362
-        return $ticket->save() ? 1 : 0;
363
-    }
364
-
365
-
366
-
367
-    /**
368
-     * removes quantities within the ticket selector based on zero ticket availability
369
-     *
370
-     * @param    EE_Ticket $ticket
371
-     * @return    void
372
-     * @throws UnexpectedEntityException
373
-     * @throws EE_Error
374
-     */
375
-    protected function _ticket_sold_out(EE_Ticket $ticket)
376
-    {
377
-        if (self::debug) {
378
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
379
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
380
-        }
381
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
382
-    }
383
-
384
-
385
-
386
-    /**
387
-     * adjusts quantities within the ticket selector based on decreased ticket availability
388
-     *
389
-     * @param    EE_Ticket $ticket
390
-     * @return void
391
-     * @throws UnexpectedEntityException
392
-     * @throws EE_Error
393
-     */
394
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
395
-    {
396
-        if (self::debug) {
397
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
398
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
399
-        }
400
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
401
-    }
402
-
403
-
404
-
405
-    /**
406
-     * builds string out of ticket and event name
407
-     *
408
-     * @param    EE_Ticket $ticket
409
-     * @return string
410
-     * @throws UnexpectedEntityException
411
-     * @throws EE_Error
412
-     */
413
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
414
-    {
415
-        $event = $ticket->get_related_event();
416
-        if ($event instanceof EE_Event) {
417
-            $ticket_name = sprintf(
418
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
419
-                $ticket->name(),
420
-                $event->name()
421
-            );
422
-        } else {
423
-            $ticket_name = $ticket->name();
424
-        }
425
-        return $ticket_name;
426
-    }
427
-
428
-
429
-
430
-    /********************************** EVENT CART  **********************************/
431
-
432
-
433
-
434
-    /**
435
-     * releases or reserves ticket(s) based on quantity passed
436
-     *
437
-     * @param  EE_Line_Item $line_item
438
-     * @param  int          $quantity
439
-     * @return void
440
-     * @throws EE_Error
441
-     * @throws InvalidArgumentException
442
-     * @throws InvalidDataTypeException
443
-     * @throws InvalidInterfaceException
444
-     */
445
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
446
-    {
447
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
448
-        if ($ticket instanceof EE_Ticket) {
449
-            $ticket->add_extra_meta(
450
-                EE_Ticket::META_KEY_TICKET_RESERVATIONS,
451
-                __LINE__ . ') ' . __METHOD__ . '()'
452
-            );
453
-            if ($quantity > 0) {
454
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
455
-            } else {
456
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
457
-            }
458
-        }
459
-    }
460
-
461
-
462
-
463
-    /**
464
-     * releases reserved ticket(s) based on quantity passed
465
-     *
466
-     * @param  EE_Ticket $ticket
467
-     * @param  int       $quantity
468
-     * @return void
469
-     * @throws EE_Error
470
-     */
471
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
472
-    {
473
-        $ticket->add_extra_meta(
474
-            EE_Ticket::META_KEY_TICKET_RESERVATIONS,
475
-            __LINE__ . ') ' . __METHOD__ . '()'
476
-        );
477
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
478
-    }
479
-
480
-
481
-
482
-    /********************************** POST_NOTICES  **********************************/
483
-
484
-
485
-
486
-    /**
487
-     * @return void
488
-     * @throws EE_Error
489
-     * @throws InvalidArgumentException
490
-     * @throws ReflectionException
491
-     * @throws InvalidDataTypeException
492
-     * @throws InvalidInterfaceException
493
-     */
494
-    public static function post_notices()
495
-    {
496
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
497
-    }
498
-
499
-
500
-
501
-    /**
502
-     * @return void
503
-     * @throws EE_Error
504
-     * @throws InvalidArgumentException
505
-     * @throws ReflectionException
506
-     * @throws InvalidDataTypeException
507
-     * @throws InvalidInterfaceException
508
-     */
509
-    protected function _post_notices()
510
-    {
511
-        if (self::debug) {
512
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
513
-        }
514
-        $refresh_msg    = '';
515
-        $none_added_msg = '';
516
-        if (defined('DOING_AJAX') && DOING_AJAX) {
517
-            $refresh_msg    = __(
518
-                'Please refresh the page to view updated ticket quantities.',
519
-                'event_espresso'
520
-            );
521
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
522
-        }
523
-        if (! empty($this->sold_out_tickets)) {
524
-            EE_Error::add_attention(
525
-                sprintf(
526
-                    apply_filters(
527
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
528
-                        __(
529
-                            'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
530
-                            'event_espresso'
531
-                        )
532
-                    ),
533
-                    '<br />',
534
-                    implode('<br />', $this->sold_out_tickets),
535
-                    $none_added_msg,
536
-                    $refresh_msg
537
-                )
538
-            );
539
-            // alter code flow in the Ticket Selector for better UX
540
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
541
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
542
-            $this->sold_out_tickets = array();
543
-            // and reset the cart
544
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
545
-        }
546
-        if (! empty($this->decremented_tickets)) {
547
-            EE_Error::add_attention(
548
-                sprintf(
549
-                    apply_filters(
550
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
551
-                        __(
552
-                            'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
553
-                            'event_espresso'
554
-                        )
555
-                    ),
556
-                    '<br />',
557
-                    implode('<br />', $this->decremented_tickets),
558
-                    $none_added_msg,
559
-                    $refresh_msg
560
-                )
561
-            );
562
-            $this->decremented_tickets = array();
563
-        }
564
-    }
565
-
566
-
567
-
568
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
569
-
570
-
571
-
572
-    /**
573
-     * releases reserved tickets for all registrations of an EE_Transaction
574
-     * by default, will NOT release tickets for finalized transactions
575
-     *
576
-     * @param    EE_Transaction $transaction
577
-     * @return int
578
-     * @throws EE_Error
579
-     * @throws InvalidSessionDataException
580
-     */
581
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
582
-    {
583
-        if (self::debug) {
584
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
585
-            echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
586
-            echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
587
-        }
588
-        // check if 'finalize_registration' step has been completed...
589
-        $finalized = $transaction->reg_step_completed('finalize_registration');
590
-        if (self::debug) {
591
-            // DEBUG LOG
592
-            EEH_Debug_Tools::log(
593
-                __CLASS__,
594
-                __FUNCTION__,
595
-                __LINE__,
596
-                array('finalized' => $finalized),
597
-                false,
598
-                'EE_Transaction: ' . $transaction->ID()
599
-            );
600
-        }
601
-        // how many tickets were released
602
-        $count = 0;
603
-        if (self::debug) {
604
-            echo self::$nl . ' . . . TXN finalized: ' . $finalized;
605
-        }
606
-        $release_tickets_with_TXN_status = array(
607
-            EEM_Transaction::failed_status_code,
608
-            EEM_Transaction::abandoned_status_code,
609
-            EEM_Transaction::incomplete_status_code,
610
-        );
611
-        $events = array();
612
-        // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
613
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
614
-            // cancel any reserved tickets for registrations that were not approved
615
-            $registrations = $transaction->registrations();
616
-            if (self::debug) {
617
-                echo self::$nl . ' . . . # registrations: ' . count($registrations);
618
-                $reg    = reset($registrations);
619
-                $ticket = $reg->ticket();
620
-                if ($ticket instanceof EE_Ticket) {
621
-                    $ticket->add_extra_meta(
622
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
623
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
624
-                    );
625
-                }
626
-            }
627
-            if (! empty($registrations)) {
628
-                foreach ($registrations as $registration) {
629
-                    if (
630
-                        $registration instanceof EE_Registration
631
-                        && $this->_release_reserved_ticket_for_registration($registration, $transaction)
632
-                    ) {
633
-                        $count++;
634
-                        $events[ $registration->event_ID() ] = $registration->event();
635
-                    }
636
-                }
637
-            }
638
-        }
639
-        if ($events !== array()) {
640
-            foreach ($events as $event) {
641
-                /** @var EE_Event $event */
642
-                $event->perform_sold_out_status_check();
643
-            }
644
-        }
645
-        return $count;
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * releases reserved tickets for an EE_Registration
652
-     * by default, will NOT release tickets for APPROVED registrations
653
-     *
654
-     * @param EE_Registration $registration
655
-     * @param EE_Transaction  $transaction
656
-     * @return int
657
-     * @throws EE_Error
658
-     */
659
-    protected function _release_reserved_ticket_for_registration(
660
-        EE_Registration $registration,
661
-        EE_Transaction $transaction
662
-    ) {
663
-        $STS_ID = $transaction->status_ID();
664
-        if (self::debug) {
665
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
666
-            echo self::$nl . ' . . registration->ID: ' . $registration->ID();
667
-            echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
668
-            echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
669
-        }
670
-        if (
671
-            // release Tickets for Failed Transactions and Abandoned Transactions
672
-            $STS_ID === EEM_Transaction::failed_status_code
673
-            || $STS_ID === EEM_Transaction::abandoned_status_code
674
-            || (
675
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
676
-                $STS_ID === EEM_Transaction::incomplete_status_code
677
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
678
-            )
679
-        ) {
680
-            if (self::debug) {
681
-                echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
682
-                $rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
683
-                echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
684
-                var_dump($rsrvd);
685
-            }
686
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
687
-            return 1;
688
-        }
689
-        return 0;
690
-    }
691
-
692
-
693
-
694
-    /********************************** SESSION_CART_RESET  **********************************/
695
-
696
-
697
-
698
-    /**
699
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
700
-     *
701
-     * @param EE_Session $session
702
-     * @return void
703
-     * @throws EE_Error
704
-     * @throws InvalidArgumentException
705
-     * @throws ReflectionException
706
-     * @throws InvalidDataTypeException
707
-     * @throws InvalidInterfaceException
708
-     */
709
-    public static function session_cart_reset(EE_Session $session)
710
-    {
711
-        if (self::debug) {
712
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
713
-        }
714
-        // first check of the session has a valid Checkout object
715
-        $checkout = $session->checkout();
716
-        if ($checkout instanceof EE_Checkout) {
717
-            // and use that to clear ticket reservations because it will update the associated registration meta data
718
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
719
-            return;
720
-        }
721
-        $cart = $session->cart();
722
-        if ($cart instanceof EE_Cart) {
723
-            if (self::debug) {
724
-                echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
725
-            }
726
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
727
-        } else {
728
-            if (self::debug) {
729
-                echo self::$nl . self::$nl . ' invalid EE_Cart: ';
730
-                var_export($cart, true);
731
-            }
732
-        }
733
-    }
734
-
735
-
736
-
737
-    /**
738
-     * releases reserved tickets in the EE_Cart
739
-     *
740
-     * @param EE_Cart $cart
741
-     * @return void
742
-     * @throws EE_Error
743
-     * @throws InvalidArgumentException
744
-     * @throws ReflectionException
745
-     * @throws InvalidDataTypeException
746
-     * @throws InvalidInterfaceException
747
-     */
748
-    protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
749
-    {
750
-        if (self::debug) {
751
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
752
-        }
753
-        EE_Registry::instance()->load_helper('Line_Item');
754
-        $ticket_line_items = $cart->get_tickets();
755
-        if (empty($ticket_line_items)) {
756
-            return;
757
-        }
758
-        foreach ($ticket_line_items as $ticket_line_item) {
759
-            if (self::debug) {
760
-                echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
761
-            }
762
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
763
-                if (self::debug) {
764
-                    echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
765
-                }
766
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
767
-                if ($ticket instanceof EE_Ticket) {
768
-                    if (self::debug) {
769
-                        echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
770
-                        echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
771
-                    }
772
-                    $ticket->add_extra_meta(
773
-                        EE_Ticket::META_KEY_TICKET_RESERVATIONS,
774
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
775
-                    );
776
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
777
-                }
778
-            }
779
-        }
780
-        if (self::debug) {
781
-            echo self::$nl . self::$nl . ' RESET COMPLETED ';
782
-        }
783
-    }
784
-
785
-
786
-
787
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
788
-
789
-
790
-
791
-    /**
792
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
793
-     *
794
-     * @param EE_Session $session
795
-     * @return void
796
-     * @throws EE_Error
797
-     * @throws InvalidSessionDataException
798
-     */
799
-    public static function session_checkout_reset(EE_Session $session)
800
-    {
801
-        $checkout = $session->checkout();
802
-        if ($checkout instanceof EE_Checkout) {
803
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
804
-        }
805
-    }
806
-
807
-
808
-
809
-    /**
810
-     * releases reserved tickets for the EE_Checkout->transaction
811
-     *
812
-     * @param EE_Checkout $checkout
813
-     * @return void
814
-     * @throws EE_Error
815
-     * @throws InvalidSessionDataException
816
-     */
817
-    protected function _session_checkout_reset(EE_Checkout $checkout)
818
-    {
819
-        if (self::debug) {
820
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
821
-        }
822
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
823
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
824
-            return;
825
-        }
826
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
827
-    }
828
-
829
-
830
-
831
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
832
-
833
-
834
-
835
-    /**
836
-     * @param    EE_Session $session
837
-     * @return    void
838
-     */
839
-    public static function session_expired_reset(EE_Session $session)
840
-    {
841
-    }
842
-
843
-
844
-
845
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
846
-
847
-
848
-
849
-    /**
850
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
851
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
852
-     *
853
-     * @param EE_Transaction $transaction
854
-     * @return void
855
-     * @throws EE_Error
856
-     * @throws InvalidSessionDataException
857
-     */
858
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
859
-    {
860
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
861
-        if ($transaction->is_free() || $transaction->paid() > 0) {
862
-            if (self::debug) {
863
-                // DEBUG LOG
864
-                EEH_Debug_Tools::log(
865
-                    __CLASS__,
866
-                    __FUNCTION__,
867
-                    __LINE__,
868
-                    array($transaction),
869
-                    false,
870
-                    'EE_Transaction: ' . $transaction->ID()
871
-                );
872
-            }
873
-            return;
874
-        }
875
-        // have their been any successful payments made ?
876
-        $payments = $transaction->payments();
877
-        foreach ($payments as $payment) {
878
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
879
-                if (self::debug) {
880
-                    // DEBUG LOG
881
-                    EEH_Debug_Tools::log(
882
-                        __CLASS__,
883
-                        __FUNCTION__,
884
-                        __LINE__,
885
-                        array($payment),
886
-                        false,
887
-                        'EE_Transaction: ' . $transaction->ID()
888
-                    );
889
-                }
890
-                return;
891
-            }
892
-        }
893
-        // since you haven't even attempted to pay for your ticket...
894
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
895
-    }
896
-
897
-
898
-
899
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
900
-
901
-
902
-
903
-    /**
904
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
905
-     *
906
-     * @param EE_Transaction $transaction
907
-     * @return void
908
-     * @throws EE_Error
909
-     * @throws InvalidSessionDataException
910
-     */
911
-    public static function process_failed_transactions(EE_Transaction $transaction)
912
-    {
913
-        // since you haven't even attempted to pay for your ticket...
914
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
915
-    }
916
-
917
-
918
-
919
-    /********************************** RESET RESERVATION COUNTS  *********************************/
920
-
921
-
922
-
923
-    /**
924
-     * Resets all ticket and datetime reserved counts to zero
925
-     * Tickets that are currently associated with a Transaction that is in progress
926
-     *
927
-     * @throws EE_Error
928
-     * @throws DomainException
929
-     * @throws InvalidDataTypeException
930
-     * @throws InvalidInterfaceException
931
-     * @throws InvalidArgumentException
932
-     * @throws UnexpectedEntityException
933
-     */
934
-    public static function reset_reservation_counts()
935
-    {
936
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
937
-        $valid_reserved_tickets = array();
938
-        /** @var EE_Transaction[] $transactions_not_in_progress */
939
-        $transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
940
-        foreach ($transactions_not_in_progress as $transaction) {
941
-            // if this TXN has been fully completed, then skip it
942
-            if ($transaction->reg_step_completed('finalize_registration')) {
943
-                continue;
944
-            }
945
-            $total_line_item = $transaction->total_line_item();
946
-            // $transaction_in_progress->line
947
-            if (! $total_line_item instanceof EE_Line_Item) {
948
-                throw new DomainException(
949
-                    esc_html__(
950
-                        'Transaction does not have a valid Total Line Item associated with it.',
951
-                        'event_espresso'
952
-                    )
953
-                );
954
-            }
955
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
956
-                $total_line_item
957
-            );
958
-        }
959
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
960
-        foreach ($total_line_items as $total_line_item) {
961
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
962
-                $total_line_item
963
-            );
964
-        }
965
-        $tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
966
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
967
-            $tickets_with_reservations,
968
-            $valid_reserved_tickets,
969
-            __FUNCTION__
970
-        );
971
-    }
972
-
973
-
974
-
975
-    /**
976
-     * @param EE_Line_Item $total_line_item
977
-     * @return EE_Line_Item[]
978
-     */
979
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
980
-    {
981
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
982
-        $valid_reserved_tickets = array();
983
-        $ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
984
-        foreach ($ticket_line_items as $ticket_line_item) {
985
-            if ($ticket_line_item instanceof EE_Line_Item) {
986
-                $valid_reserved_tickets[] = $ticket_line_item;
987
-            }
988
-        }
989
-        return $valid_reserved_tickets;
990
-    }
991
-
992
-
993
-
994
-    /**
995
-     * @param EE_Ticket[]    $tickets_with_reservations
996
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
997
-     * @return int
998
-     * @throws UnexpectedEntityException
999
-     * @throws DomainException
1000
-     * @throws EE_Error
1001
-     */
1002
-    private static function release_reservations_for_tickets(
1003
-        array $tickets_with_reservations,
1004
-        array $valid_reserved_ticket_line_items = array(),
1005
-        $source
1006
-    ) {
1007
-        if (self::debug) {
1008
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
1009
-        }
1010
-        $total_tickets_released = 0;
1011
-        $sold_out_events = array();
1012
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
1013
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1014
-                continue;
1015
-            }
1016
-            $reserved_qty = $ticket_with_reservations->reserved();
1017
-            if (self::debug) {
1018
-                echo self::$nl . ' . $ticket_with_reservations->ID(): ' . $ticket_with_reservations->ID();
1019
-                echo self::$nl . ' . $reserved_qty: ' . $reserved_qty;
1020
-            }
1021
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1022
-                if (
1023
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
1024
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1025
-                ) {
1026
-                    if (self::debug) {
1027
-                        echo self::$nl . ' . $valid_reserved_ticket_line_item->quantity(): ' . $valid_reserved_ticket_line_item->quantity();
1028
-                    }
1029
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1030
-                }
1031
-            }
1032
-            if ($reserved_qty > 0) {
1033
-                $ticket_with_reservations->add_extra_meta(
1034
-                    EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1035
-                    __LINE__ . ') ' . $source . '()'
1036
-                );
1037
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1038
-                $ticket_with_reservations->save();
1039
-                $total_tickets_released += $reserved_qty;
1040
-                $event = $ticket_with_reservations->get_related_event();
1041
-                // track sold out events
1042
-                if ($event instanceof EE_Event && $event->is_sold_out()) {
1043
-                    $sold_out_events[] = $event;
1044
-                }
1045
-            }
1046
-        }
1047
-        if (self::debug) {
1048
-            echo self::$nl . ' . $total_tickets_released: ' . $total_tickets_released;
1049
-        }
1050
-        // double check whether sold out events should remain sold out after releasing tickets
1051
-        if($sold_out_events !== array()){
1052
-            foreach ($sold_out_events as $sold_out_event) {
1053
-                /** @var EE_Event $sold_out_event */
1054
-                $sold_out_event->perform_sold_out_status_check();
1055
-            }
1056
-        }
1057
-        return $total_tickets_released;
1058
-    }
1059
-
1060
-
1061
-
1062
-    /********************************** SHUTDOWN  **********************************/
1063
-
1064
-
1065
-
1066
-    /**
1067
-     * @param int $timestamp
1068
-     * @return false|int
1069
-     * @throws EE_Error
1070
-     * @throws InvalidArgumentException
1071
-     * @throws InvalidDataTypeException
1072
-     * @throws InvalidInterfaceException
1073
-     */
1074
-    public static function clear_expired_line_items_with_no_transaction($timestamp = 0)
1075
-    {
1076
-       /** @type WPDB $wpdb */
1077
-        global $wpdb;
1078
-        if (! absint($timestamp)) {
1079
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1080
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
1081
-                'EventEspresso\core\domain\values\session\SessionLifespan'
1082
-            );
1083
-            $timestamp = $session_lifespan->expiration();
1084
-        }
1085
-         return $wpdb->query(
1086
-            $wpdb->prepare(
1087
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
27
+	const debug = false;    //	true false
28
+
29
+	private static $nl = '';
30
+
31
+	/**
32
+	 * an array of raw ticket data from EED_Ticket_Selector
33
+	 *
34
+	 * @var array $ticket_selections
35
+	 */
36
+	protected $ticket_selections = array();
37
+
38
+	/**
39
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
40
+	 * according to how they are displayed in the actual Ticket_Selector
41
+	 * this tracks the current row being processed
42
+	 *
43
+	 * @var int $current_row
44
+	 */
45
+	protected $current_row = 0;
46
+
47
+	/**
48
+	 * an array for tracking names of tickets that have sold out
49
+	 *
50
+	 * @var array $sold_out_tickets
51
+	 */
52
+	protected $sold_out_tickets = array();
53
+
54
+	/**
55
+	 * an array for tracking names of tickets that have had their quantities reduced
56
+	 *
57
+	 * @var array $decremented_tickets
58
+	 */
59
+	protected $decremented_tickets = array();
60
+
61
+
62
+
63
+	/**
64
+	 * set_hooks - for hooking into EE Core, other modules, etc
65
+	 *
66
+	 * @return    void
67
+	 */
68
+	public static function set_hooks()
69
+	{
70
+		self::$nl = defined('EE_TESTS_DIR')? "\n" : '<br />';
71
+		// release tickets for expired carts
72
+		add_action(
73
+			'EED_Ticket_Selector__process_ticket_selections__before',
74
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
75
+			1
76
+		);
77
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
78
+		add_filter(
79
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
80
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
81
+			20,
82
+			3
83
+		);
84
+		// add notices for sold out tickets
85
+		add_action(
86
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
87
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
88
+			10
89
+		);
90
+		// handle ticket quantities adjusted in cart
91
+		//add_action(
92
+		//	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
93
+		//	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
94
+		//	10, 2
95
+		//);
96
+		// handle tickets deleted from cart
97
+		add_action(
98
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
99
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
100
+			10,
101
+			2
102
+		);
103
+		// handle emptied carts
104
+		add_action(
105
+			'AHEE__EE_Session__reset_cart__before_reset',
106
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
107
+			10,
108
+			1
109
+		);
110
+		add_action(
111
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
112
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
113
+			10,
114
+			1
115
+		);
116
+		// handle cancelled registrations
117
+		add_action(
118
+			'AHEE__EE_Session__reset_checkout__before_reset',
119
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
120
+			10,
121
+			1
122
+		);
123
+		// cron tasks
124
+		add_action(
125
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
126
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
127
+			10,
128
+			1
129
+		);
130
+		add_action(
131
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
132
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
133
+			10,
134
+			1
135
+		);
136
+		add_action(
137
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
138
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
139
+			10,
140
+			1
141
+		);
142
+	}
143
+
144
+
145
+
146
+	/**
147
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
148
+	 *
149
+	 * @return void
150
+	 */
151
+	public static function set_hooks_admin()
152
+	{
153
+		EED_Ticket_Sales_Monitor::set_hooks();
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
160
+	 */
161
+	public static function instance()
162
+	{
163
+		return parent::get_instance(__CLASS__);
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * @param WP_Query $WP_Query
170
+	 * @return    void
171
+	 */
172
+	public function run($WP_Query)
173
+	{
174
+	}
175
+
176
+
177
+
178
+	/********************************** PRE_TICKET_SALES  **********************************/
179
+
180
+
181
+
182
+	/**
183
+	 * Retrieves grand totals from the line items that have no TXN ID
184
+	 * and timestamps less than the current time minus the session lifespan.
185
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
186
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
187
+	 *
188
+	 * @return void
189
+	 * @throws DomainException
190
+	 * @throws EE_Error
191
+	 * @throws InvalidArgumentException
192
+	 * @throws InvalidDataTypeException
193
+	 * @throws InvalidInterfaceException
194
+	 * @throws UnexpectedEntityException
195
+	 */
196
+	public static function release_tickets_for_expired_carts()
197
+	{
198
+		if (self::debug) {
199
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
200
+		}
201
+		do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
202
+		$expired_ticket_IDs = array();
203
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
204
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
205
+			'EventEspresso\core\domain\values\session\SessionLifespan'
206
+		);
207
+		$timestamp = $session_lifespan->expiration();
208
+		$expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
209
+		if (self::debug) {
210
+			echo self::$nl . ' . time(): ' . time();
211
+			echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
212
+			echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
213
+			echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
214
+			echo self::$nl . ' . timestamp: ' . $timestamp;
215
+			echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
216
+		}
217
+		if (! empty($expired_ticket_line_items)) {
218
+			foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
219
+				if (! $expired_ticket_line_item instanceof EE_Line_Item) {
220
+					continue;
221
+				}
222
+				$expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
223
+				if (self::debug) {
224
+					echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
225
+					echo self::$nl . ' . $expired_ticket_line_item->timestamp(): ' . date('Y-m-d h:i a',
226
+							$expired_ticket_line_item->timestamp(true));
227
+				}
228
+			}
229
+			if (! empty($expired_ticket_IDs)) {
230
+				EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
231
+					\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
232
+					array(),
233
+					__FUNCTION__
234
+				);
235
+				// now  let's get rid of expired line items so that they can't interfere with tracking
236
+				EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
237
+			}
238
+		}
239
+		do_action(
240
+			'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
241
+			$expired_ticket_IDs,
242
+			$expired_ticket_line_items
243
+		);
244
+	}
245
+
246
+
247
+
248
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
249
+
250
+
251
+
252
+	/**
253
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
254
+	 *
255
+	 * @param int       $qty
256
+	 * @param EE_Ticket $ticket
257
+	 * @return bool
258
+	 * @throws UnexpectedEntityException
259
+	 * @throws EE_Error
260
+	 */
261
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
262
+	{
263
+		$qty = absint($qty);
264
+		if ($qty > 0) {
265
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
266
+		}
267
+		if (self::debug) {
268
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
269
+			echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
270
+		}
271
+		return $qty;
272
+	}
273
+
274
+
275
+
276
+	/**
277
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
278
+	 *
279
+	 * @param   EE_Ticket $ticket
280
+	 * @param int         $qty
281
+	 * @return int
282
+	 * @throws UnexpectedEntityException
283
+	 * @throws EE_Error
284
+	 */
285
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
286
+	{
287
+		if (self::debug) {
288
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
289
+		}
290
+		if (! $ticket instanceof EE_Ticket) {
291
+			return 0;
292
+		}
293
+		if (self::debug) {
294
+			echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
295
+			echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
296
+		}
297
+		$ticket->refresh_from_db();
298
+		// first let's determine the ticket availability based on sales
299
+		$available = $ticket->qty('saleable');
300
+		if (self::debug) {
301
+			echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
302
+			echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
303
+			echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
304
+			echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
305
+			echo self::$nl . ' . . . available: ' . $available;
306
+		}
307
+		if ($available < 1) {
308
+			$this->_ticket_sold_out($ticket);
309
+			return 0;
310
+		}
311
+		if (self::debug) {
312
+			echo self::$nl . ' . . . qty: ' . $qty;
313
+		}
314
+		if ($available < $qty) {
315
+			$qty = $available;
316
+			if (self::debug) {
317
+				echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
318
+			}
319
+			$this->_ticket_quantity_decremented($ticket);
320
+		}
321
+		$this->_reserve_ticket($ticket, $qty);
322
+		return $qty;
323
+	}
324
+
325
+
326
+
327
+	/**
328
+	 * increments ticket reserved based on quantity passed
329
+	 *
330
+	 * @param    EE_Ticket $ticket
331
+	 * @param int          $quantity
332
+	 * @return bool
333
+	 * @throws EE_Error
334
+	 */
335
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
336
+	{
337
+		if (self::debug) {
338
+			echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
339
+		}
340
+		$ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
341
+		return $ticket->save();
342
+	}
343
+
344
+
345
+
346
+	/**
347
+	 * @param  EE_Ticket $ticket
348
+	 * @param  int       $quantity
349
+	 * @return bool
350
+	 * @throws EE_Error
351
+	 */
352
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
353
+	{
354
+		if (self::debug) {
355
+			echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
356
+			echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
357
+		}
358
+		$ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
359
+		if (self::debug) {
360
+			echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
361
+		}
362
+		return $ticket->save() ? 1 : 0;
363
+	}
364
+
365
+
366
+
367
+	/**
368
+	 * removes quantities within the ticket selector based on zero ticket availability
369
+	 *
370
+	 * @param    EE_Ticket $ticket
371
+	 * @return    void
372
+	 * @throws UnexpectedEntityException
373
+	 * @throws EE_Error
374
+	 */
375
+	protected function _ticket_sold_out(EE_Ticket $ticket)
376
+	{
377
+		if (self::debug) {
378
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
379
+			echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
380
+		}
381
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
382
+	}
383
+
384
+
385
+
386
+	/**
387
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
388
+	 *
389
+	 * @param    EE_Ticket $ticket
390
+	 * @return void
391
+	 * @throws UnexpectedEntityException
392
+	 * @throws EE_Error
393
+	 */
394
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
395
+	{
396
+		if (self::debug) {
397
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
398
+			echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
399
+		}
400
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
401
+	}
402
+
403
+
404
+
405
+	/**
406
+	 * builds string out of ticket and event name
407
+	 *
408
+	 * @param    EE_Ticket $ticket
409
+	 * @return string
410
+	 * @throws UnexpectedEntityException
411
+	 * @throws EE_Error
412
+	 */
413
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
414
+	{
415
+		$event = $ticket->get_related_event();
416
+		if ($event instanceof EE_Event) {
417
+			$ticket_name = sprintf(
418
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
419
+				$ticket->name(),
420
+				$event->name()
421
+			);
422
+		} else {
423
+			$ticket_name = $ticket->name();
424
+		}
425
+		return $ticket_name;
426
+	}
427
+
428
+
429
+
430
+	/********************************** EVENT CART  **********************************/
431
+
432
+
433
+
434
+	/**
435
+	 * releases or reserves ticket(s) based on quantity passed
436
+	 *
437
+	 * @param  EE_Line_Item $line_item
438
+	 * @param  int          $quantity
439
+	 * @return void
440
+	 * @throws EE_Error
441
+	 * @throws InvalidArgumentException
442
+	 * @throws InvalidDataTypeException
443
+	 * @throws InvalidInterfaceException
444
+	 */
445
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
446
+	{
447
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
448
+		if ($ticket instanceof EE_Ticket) {
449
+			$ticket->add_extra_meta(
450
+				EE_Ticket::META_KEY_TICKET_RESERVATIONS,
451
+				__LINE__ . ') ' . __METHOD__ . '()'
452
+			);
453
+			if ($quantity > 0) {
454
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
455
+			} else {
456
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
457
+			}
458
+		}
459
+	}
460
+
461
+
462
+
463
+	/**
464
+	 * releases reserved ticket(s) based on quantity passed
465
+	 *
466
+	 * @param  EE_Ticket $ticket
467
+	 * @param  int       $quantity
468
+	 * @return void
469
+	 * @throws EE_Error
470
+	 */
471
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
472
+	{
473
+		$ticket->add_extra_meta(
474
+			EE_Ticket::META_KEY_TICKET_RESERVATIONS,
475
+			__LINE__ . ') ' . __METHOD__ . '()'
476
+		);
477
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
478
+	}
479
+
480
+
481
+
482
+	/********************************** POST_NOTICES  **********************************/
483
+
484
+
485
+
486
+	/**
487
+	 * @return void
488
+	 * @throws EE_Error
489
+	 * @throws InvalidArgumentException
490
+	 * @throws ReflectionException
491
+	 * @throws InvalidDataTypeException
492
+	 * @throws InvalidInterfaceException
493
+	 */
494
+	public static function post_notices()
495
+	{
496
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
497
+	}
498
+
499
+
500
+
501
+	/**
502
+	 * @return void
503
+	 * @throws EE_Error
504
+	 * @throws InvalidArgumentException
505
+	 * @throws ReflectionException
506
+	 * @throws InvalidDataTypeException
507
+	 * @throws InvalidInterfaceException
508
+	 */
509
+	protected function _post_notices()
510
+	{
511
+		if (self::debug) {
512
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
513
+		}
514
+		$refresh_msg    = '';
515
+		$none_added_msg = '';
516
+		if (defined('DOING_AJAX') && DOING_AJAX) {
517
+			$refresh_msg    = __(
518
+				'Please refresh the page to view updated ticket quantities.',
519
+				'event_espresso'
520
+			);
521
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
522
+		}
523
+		if (! empty($this->sold_out_tickets)) {
524
+			EE_Error::add_attention(
525
+				sprintf(
526
+					apply_filters(
527
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
528
+						__(
529
+							'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
530
+							'event_espresso'
531
+						)
532
+					),
533
+					'<br />',
534
+					implode('<br />', $this->sold_out_tickets),
535
+					$none_added_msg,
536
+					$refresh_msg
537
+				)
538
+			);
539
+			// alter code flow in the Ticket Selector for better UX
540
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
541
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
542
+			$this->sold_out_tickets = array();
543
+			// and reset the cart
544
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
545
+		}
546
+		if (! empty($this->decremented_tickets)) {
547
+			EE_Error::add_attention(
548
+				sprintf(
549
+					apply_filters(
550
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
551
+						__(
552
+							'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
553
+							'event_espresso'
554
+						)
555
+					),
556
+					'<br />',
557
+					implode('<br />', $this->decremented_tickets),
558
+					$none_added_msg,
559
+					$refresh_msg
560
+				)
561
+			);
562
+			$this->decremented_tickets = array();
563
+		}
564
+	}
565
+
566
+
567
+
568
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
569
+
570
+
571
+
572
+	/**
573
+	 * releases reserved tickets for all registrations of an EE_Transaction
574
+	 * by default, will NOT release tickets for finalized transactions
575
+	 *
576
+	 * @param    EE_Transaction $transaction
577
+	 * @return int
578
+	 * @throws EE_Error
579
+	 * @throws InvalidSessionDataException
580
+	 */
581
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
582
+	{
583
+		if (self::debug) {
584
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
585
+			echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
586
+			echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
587
+		}
588
+		// check if 'finalize_registration' step has been completed...
589
+		$finalized = $transaction->reg_step_completed('finalize_registration');
590
+		if (self::debug) {
591
+			// DEBUG LOG
592
+			EEH_Debug_Tools::log(
593
+				__CLASS__,
594
+				__FUNCTION__,
595
+				__LINE__,
596
+				array('finalized' => $finalized),
597
+				false,
598
+				'EE_Transaction: ' . $transaction->ID()
599
+			);
600
+		}
601
+		// how many tickets were released
602
+		$count = 0;
603
+		if (self::debug) {
604
+			echo self::$nl . ' . . . TXN finalized: ' . $finalized;
605
+		}
606
+		$release_tickets_with_TXN_status = array(
607
+			EEM_Transaction::failed_status_code,
608
+			EEM_Transaction::abandoned_status_code,
609
+			EEM_Transaction::incomplete_status_code,
610
+		);
611
+		$events = array();
612
+		// if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
613
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
614
+			// cancel any reserved tickets for registrations that were not approved
615
+			$registrations = $transaction->registrations();
616
+			if (self::debug) {
617
+				echo self::$nl . ' . . . # registrations: ' . count($registrations);
618
+				$reg    = reset($registrations);
619
+				$ticket = $reg->ticket();
620
+				if ($ticket instanceof EE_Ticket) {
621
+					$ticket->add_extra_meta(
622
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
623
+						__LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
624
+					);
625
+				}
626
+			}
627
+			if (! empty($registrations)) {
628
+				foreach ($registrations as $registration) {
629
+					if (
630
+						$registration instanceof EE_Registration
631
+						&& $this->_release_reserved_ticket_for_registration($registration, $transaction)
632
+					) {
633
+						$count++;
634
+						$events[ $registration->event_ID() ] = $registration->event();
635
+					}
636
+				}
637
+			}
638
+		}
639
+		if ($events !== array()) {
640
+			foreach ($events as $event) {
641
+				/** @var EE_Event $event */
642
+				$event->perform_sold_out_status_check();
643
+			}
644
+		}
645
+		return $count;
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * releases reserved tickets for an EE_Registration
652
+	 * by default, will NOT release tickets for APPROVED registrations
653
+	 *
654
+	 * @param EE_Registration $registration
655
+	 * @param EE_Transaction  $transaction
656
+	 * @return int
657
+	 * @throws EE_Error
658
+	 */
659
+	protected function _release_reserved_ticket_for_registration(
660
+		EE_Registration $registration,
661
+		EE_Transaction $transaction
662
+	) {
663
+		$STS_ID = $transaction->status_ID();
664
+		if (self::debug) {
665
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
666
+			echo self::$nl . ' . . registration->ID: ' . $registration->ID();
667
+			echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
668
+			echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
669
+		}
670
+		if (
671
+			// release Tickets for Failed Transactions and Abandoned Transactions
672
+			$STS_ID === EEM_Transaction::failed_status_code
673
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
674
+			|| (
675
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
676
+				$STS_ID === EEM_Transaction::incomplete_status_code
677
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
678
+			)
679
+		) {
680
+			if (self::debug) {
681
+				echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
682
+				$rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
683
+				echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
684
+				var_dump($rsrvd);
685
+			}
686
+			$registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
687
+			return 1;
688
+		}
689
+		return 0;
690
+	}
691
+
692
+
693
+
694
+	/********************************** SESSION_CART_RESET  **********************************/
695
+
696
+
697
+
698
+	/**
699
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
700
+	 *
701
+	 * @param EE_Session $session
702
+	 * @return void
703
+	 * @throws EE_Error
704
+	 * @throws InvalidArgumentException
705
+	 * @throws ReflectionException
706
+	 * @throws InvalidDataTypeException
707
+	 * @throws InvalidInterfaceException
708
+	 */
709
+	public static function session_cart_reset(EE_Session $session)
710
+	{
711
+		if (self::debug) {
712
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
713
+		}
714
+		// first check of the session has a valid Checkout object
715
+		$checkout = $session->checkout();
716
+		if ($checkout instanceof EE_Checkout) {
717
+			// and use that to clear ticket reservations because it will update the associated registration meta data
718
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
719
+			return;
720
+		}
721
+		$cart = $session->cart();
722
+		if ($cart instanceof EE_Cart) {
723
+			if (self::debug) {
724
+				echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
725
+			}
726
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
727
+		} else {
728
+			if (self::debug) {
729
+				echo self::$nl . self::$nl . ' invalid EE_Cart: ';
730
+				var_export($cart, true);
731
+			}
732
+		}
733
+	}
734
+
735
+
736
+
737
+	/**
738
+	 * releases reserved tickets in the EE_Cart
739
+	 *
740
+	 * @param EE_Cart $cart
741
+	 * @return void
742
+	 * @throws EE_Error
743
+	 * @throws InvalidArgumentException
744
+	 * @throws ReflectionException
745
+	 * @throws InvalidDataTypeException
746
+	 * @throws InvalidInterfaceException
747
+	 */
748
+	protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
749
+	{
750
+		if (self::debug) {
751
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
752
+		}
753
+		EE_Registry::instance()->load_helper('Line_Item');
754
+		$ticket_line_items = $cart->get_tickets();
755
+		if (empty($ticket_line_items)) {
756
+			return;
757
+		}
758
+		foreach ($ticket_line_items as $ticket_line_item) {
759
+			if (self::debug) {
760
+				echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
761
+			}
762
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
763
+				if (self::debug) {
764
+					echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
765
+				}
766
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
767
+				if ($ticket instanceof EE_Ticket) {
768
+					if (self::debug) {
769
+						echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
770
+						echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
771
+					}
772
+					$ticket->add_extra_meta(
773
+						EE_Ticket::META_KEY_TICKET_RESERVATIONS,
774
+						__LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
775
+					);
776
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
777
+				}
778
+			}
779
+		}
780
+		if (self::debug) {
781
+			echo self::$nl . self::$nl . ' RESET COMPLETED ';
782
+		}
783
+	}
784
+
785
+
786
+
787
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
788
+
789
+
790
+
791
+	/**
792
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
793
+	 *
794
+	 * @param EE_Session $session
795
+	 * @return void
796
+	 * @throws EE_Error
797
+	 * @throws InvalidSessionDataException
798
+	 */
799
+	public static function session_checkout_reset(EE_Session $session)
800
+	{
801
+		$checkout = $session->checkout();
802
+		if ($checkout instanceof EE_Checkout) {
803
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
804
+		}
805
+	}
806
+
807
+
808
+
809
+	/**
810
+	 * releases reserved tickets for the EE_Checkout->transaction
811
+	 *
812
+	 * @param EE_Checkout $checkout
813
+	 * @return void
814
+	 * @throws EE_Error
815
+	 * @throws InvalidSessionDataException
816
+	 */
817
+	protected function _session_checkout_reset(EE_Checkout $checkout)
818
+	{
819
+		if (self::debug) {
820
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
821
+		}
822
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
823
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
824
+			return;
825
+		}
826
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
827
+	}
828
+
829
+
830
+
831
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
832
+
833
+
834
+
835
+	/**
836
+	 * @param    EE_Session $session
837
+	 * @return    void
838
+	 */
839
+	public static function session_expired_reset(EE_Session $session)
840
+	{
841
+	}
842
+
843
+
844
+
845
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
846
+
847
+
848
+
849
+	/**
850
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
851
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
852
+	 *
853
+	 * @param EE_Transaction $transaction
854
+	 * @return void
855
+	 * @throws EE_Error
856
+	 * @throws InvalidSessionDataException
857
+	 */
858
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
859
+	{
860
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
861
+		if ($transaction->is_free() || $transaction->paid() > 0) {
862
+			if (self::debug) {
863
+				// DEBUG LOG
864
+				EEH_Debug_Tools::log(
865
+					__CLASS__,
866
+					__FUNCTION__,
867
+					__LINE__,
868
+					array($transaction),
869
+					false,
870
+					'EE_Transaction: ' . $transaction->ID()
871
+				);
872
+			}
873
+			return;
874
+		}
875
+		// have their been any successful payments made ?
876
+		$payments = $transaction->payments();
877
+		foreach ($payments as $payment) {
878
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
879
+				if (self::debug) {
880
+					// DEBUG LOG
881
+					EEH_Debug_Tools::log(
882
+						__CLASS__,
883
+						__FUNCTION__,
884
+						__LINE__,
885
+						array($payment),
886
+						false,
887
+						'EE_Transaction: ' . $transaction->ID()
888
+					);
889
+				}
890
+				return;
891
+			}
892
+		}
893
+		// since you haven't even attempted to pay for your ticket...
894
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
895
+	}
896
+
897
+
898
+
899
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
900
+
901
+
902
+
903
+	/**
904
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
905
+	 *
906
+	 * @param EE_Transaction $transaction
907
+	 * @return void
908
+	 * @throws EE_Error
909
+	 * @throws InvalidSessionDataException
910
+	 */
911
+	public static function process_failed_transactions(EE_Transaction $transaction)
912
+	{
913
+		// since you haven't even attempted to pay for your ticket...
914
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
915
+	}
916
+
917
+
918
+
919
+	/********************************** RESET RESERVATION COUNTS  *********************************/
920
+
921
+
922
+
923
+	/**
924
+	 * Resets all ticket and datetime reserved counts to zero
925
+	 * Tickets that are currently associated with a Transaction that is in progress
926
+	 *
927
+	 * @throws EE_Error
928
+	 * @throws DomainException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws InvalidInterfaceException
931
+	 * @throws InvalidArgumentException
932
+	 * @throws UnexpectedEntityException
933
+	 */
934
+	public static function reset_reservation_counts()
935
+	{
936
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
937
+		$valid_reserved_tickets = array();
938
+		/** @var EE_Transaction[] $transactions_not_in_progress */
939
+		$transactions_not_in_progress = EEM_Transaction::instance()->get_transactions_not_in_progress();
940
+		foreach ($transactions_not_in_progress as $transaction) {
941
+			// if this TXN has been fully completed, then skip it
942
+			if ($transaction->reg_step_completed('finalize_registration')) {
943
+				continue;
944
+			}
945
+			$total_line_item = $transaction->total_line_item();
946
+			// $transaction_in_progress->line
947
+			if (! $total_line_item instanceof EE_Line_Item) {
948
+				throw new DomainException(
949
+					esc_html__(
950
+						'Transaction does not have a valid Total Line Item associated with it.',
951
+						'event_espresso'
952
+					)
953
+				);
954
+			}
955
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
956
+				$total_line_item
957
+			);
958
+		}
959
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
960
+		foreach ($total_line_items as $total_line_item) {
961
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
962
+				$total_line_item
963
+			);
964
+		}
965
+		$tickets_with_reservations = EEM_Ticket::instance()->get_tickets_with_reservations();
966
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
967
+			$tickets_with_reservations,
968
+			$valid_reserved_tickets,
969
+			__FUNCTION__
970
+		);
971
+	}
972
+
973
+
974
+
975
+	/**
976
+	 * @param EE_Line_Item $total_line_item
977
+	 * @return EE_Line_Item[]
978
+	 */
979
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
980
+	{
981
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
982
+		$valid_reserved_tickets = array();
983
+		$ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
984
+		foreach ($ticket_line_items as $ticket_line_item) {
985
+			if ($ticket_line_item instanceof EE_Line_Item) {
986
+				$valid_reserved_tickets[] = $ticket_line_item;
987
+			}
988
+		}
989
+		return $valid_reserved_tickets;
990
+	}
991
+
992
+
993
+
994
+	/**
995
+	 * @param EE_Ticket[]    $tickets_with_reservations
996
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
997
+	 * @return int
998
+	 * @throws UnexpectedEntityException
999
+	 * @throws DomainException
1000
+	 * @throws EE_Error
1001
+	 */
1002
+	private static function release_reservations_for_tickets(
1003
+		array $tickets_with_reservations,
1004
+		array $valid_reserved_ticket_line_items = array(),
1005
+		$source
1006
+	) {
1007
+		if (self::debug) {
1008
+			echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
1009
+		}
1010
+		$total_tickets_released = 0;
1011
+		$sold_out_events = array();
1012
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
1013
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
1014
+				continue;
1015
+			}
1016
+			$reserved_qty = $ticket_with_reservations->reserved();
1017
+			if (self::debug) {
1018
+				echo self::$nl . ' . $ticket_with_reservations->ID(): ' . $ticket_with_reservations->ID();
1019
+				echo self::$nl . ' . $reserved_qty: ' . $reserved_qty;
1020
+			}
1021
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1022
+				if (
1023
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
1024
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1025
+				) {
1026
+					if (self::debug) {
1027
+						echo self::$nl . ' . $valid_reserved_ticket_line_item->quantity(): ' . $valid_reserved_ticket_line_item->quantity();
1028
+					}
1029
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1030
+				}
1031
+			}
1032
+			if ($reserved_qty > 0) {
1033
+				$ticket_with_reservations->add_extra_meta(
1034
+					EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1035
+					__LINE__ . ') ' . $source . '()'
1036
+				);
1037
+				$ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1038
+				$ticket_with_reservations->save();
1039
+				$total_tickets_released += $reserved_qty;
1040
+				$event = $ticket_with_reservations->get_related_event();
1041
+				// track sold out events
1042
+				if ($event instanceof EE_Event && $event->is_sold_out()) {
1043
+					$sold_out_events[] = $event;
1044
+				}
1045
+			}
1046
+		}
1047
+		if (self::debug) {
1048
+			echo self::$nl . ' . $total_tickets_released: ' . $total_tickets_released;
1049
+		}
1050
+		// double check whether sold out events should remain sold out after releasing tickets
1051
+		if($sold_out_events !== array()){
1052
+			foreach ($sold_out_events as $sold_out_event) {
1053
+				/** @var EE_Event $sold_out_event */
1054
+				$sold_out_event->perform_sold_out_status_check();
1055
+			}
1056
+		}
1057
+		return $total_tickets_released;
1058
+	}
1059
+
1060
+
1061
+
1062
+	/********************************** SHUTDOWN  **********************************/
1063
+
1064
+
1065
+
1066
+	/**
1067
+	 * @param int $timestamp
1068
+	 * @return false|int
1069
+	 * @throws EE_Error
1070
+	 * @throws InvalidArgumentException
1071
+	 * @throws InvalidDataTypeException
1072
+	 * @throws InvalidInterfaceException
1073
+	 */
1074
+	public static function clear_expired_line_items_with_no_transaction($timestamp = 0)
1075
+	{
1076
+	   /** @type WPDB $wpdb */
1077
+		global $wpdb;
1078
+		if (! absint($timestamp)) {
1079
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1080
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
1081
+				'EventEspresso\core\domain\values\session\SessionLifespan'
1082
+			);
1083
+			$timestamp = $session_lifespan->expiration();
1084
+		}
1085
+		 return $wpdb->query(
1086
+			$wpdb->prepare(
1087
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1088 1088
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1089
-                // use GMT time because that's what LIN_timestamps are in
1090
-                date('Y-m-d H:i:s', $timestamp)
1091
-            )
1092
-        );
1093
-    }
1089
+				// use GMT time because that's what LIN_timestamps are in
1090
+				date('Y-m-d H:i:s', $timestamp)
1091
+			)
1092
+		);
1093
+	}
1094 1094
 
1095 1095
 }
1096 1096
 // End of file EED_Ticket_Sales_Monitor.module.php
Please login to merge, or discard this patch.
Spacing   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
 class EED_Ticket_Sales_Monitor extends EED_Module
25 25
 {
26 26
 
27
-    const debug = false;    //	true false
27
+    const debug = false; //	true false
28 28
 
29 29
     private static $nl = '';
30 30
 
@@ -67,7 +67,7 @@  discard block
 block discarded – undo
67 67
      */
68 68
     public static function set_hooks()
69 69
     {
70
-        self::$nl = defined('EE_TESTS_DIR')? "\n" : '<br />';
70
+        self::$nl = defined('EE_TESTS_DIR') ? "\n" : '<br />';
71 71
         // release tickets for expired carts
72 72
         add_action(
73 73
             'EED_Ticket_Selector__process_ticket_selections__before',
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
     public static function release_tickets_for_expired_carts()
197 197
     {
198 198
         if (self::debug) {
199
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
199
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
200 200
         }
201 201
         do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
202 202
         $expired_ticket_IDs = array();
@@ -207,26 +207,26 @@  discard block
 block discarded – undo
207 207
         $timestamp = $session_lifespan->expiration();
208 208
         $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
209 209
         if (self::debug) {
210
-            echo self::$nl . ' . time(): ' . time();
211
-            echo self::$nl . ' . time() as date: ' . date('Y-m-d H:i a');
212
-            echo self::$nl . ' . session expiration: ' . $session_lifespan->expiration();
213
-            echo self::$nl . ' . session expiration as date: ' . date('Y-m-d H:i a', $session_lifespan->expiration());
214
-            echo self::$nl . ' . timestamp: ' . $timestamp;
215
-            echo self::$nl . ' . $expired_ticket_line_items: ' . count($expired_ticket_line_items);
210
+            echo self::$nl.' . time(): '.time();
211
+            echo self::$nl.' . time() as date: '.date('Y-m-d H:i a');
212
+            echo self::$nl.' . session expiration: '.$session_lifespan->expiration();
213
+            echo self::$nl.' . session expiration as date: '.date('Y-m-d H:i a', $session_lifespan->expiration());
214
+            echo self::$nl.' . timestamp: '.$timestamp;
215
+            echo self::$nl.' . $expired_ticket_line_items: '.count($expired_ticket_line_items);
216 216
         }
217
-        if (! empty($expired_ticket_line_items)) {
217
+        if ( ! empty($expired_ticket_line_items)) {
218 218
             foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
219
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
219
+                if ( ! $expired_ticket_line_item instanceof EE_Line_Item) {
220 220
                     continue;
221 221
                 }
222
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
222
+                $expired_ticket_IDs[$expired_ticket_line_item->OBJ_ID()] = $expired_ticket_line_item->OBJ_ID();
223 223
                 if (self::debug) {
224
-                    echo self::$nl . ' . $expired_ticket_line_item->OBJ_ID(): ' . $expired_ticket_line_item->OBJ_ID();
225
-                    echo self::$nl . ' . $expired_ticket_line_item->timestamp(): ' . date('Y-m-d h:i a',
224
+                    echo self::$nl.' . $expired_ticket_line_item->OBJ_ID(): '.$expired_ticket_line_item->OBJ_ID();
225
+                    echo self::$nl.' . $expired_ticket_line_item->timestamp(): '.date('Y-m-d h:i a',
226 226
                             $expired_ticket_line_item->timestamp(true));
227 227
                 }
228 228
             }
229
-            if (! empty($expired_ticket_IDs)) {
229
+            if ( ! empty($expired_ticket_IDs)) {
230 230
                 EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
231 231
                     \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
232 232
                     array(),
@@ -265,8 +265,8 @@  discard block
 block discarded – undo
265 265
             $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
266 266
         }
267 267
         if (self::debug) {
268
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
269
-            echo self::$nl . self::$nl . '<b> RETURNED QTY: ' . $qty . '</b>';
268
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
269
+            echo self::$nl.self::$nl.'<b> RETURNED QTY: '.$qty.'</b>';
270 270
         }
271 271
         return $qty;
272 272
     }
@@ -285,36 +285,36 @@  discard block
 block discarded – undo
285 285
     protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
286 286
     {
287 287
         if (self::debug) {
288
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
288
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
289 289
         }
290
-        if (! $ticket instanceof EE_Ticket) {
290
+        if ( ! $ticket instanceof EE_Ticket) {
291 291
             return 0;
292 292
         }
293 293
         if (self::debug) {
294
-            echo self::$nl . '<b> . ticket->ID: ' . $ticket->ID() . '</b>';
295
-            echo self::$nl . ' . original ticket->reserved: ' . $ticket->reserved();
294
+            echo self::$nl.'<b> . ticket->ID: '.$ticket->ID().'</b>';
295
+            echo self::$nl.' . original ticket->reserved: '.$ticket->reserved();
296 296
         }
297 297
         $ticket->refresh_from_db();
298 298
         // first let's determine the ticket availability based on sales
299 299
         $available = $ticket->qty('saleable');
300 300
         if (self::debug) {
301
-            echo self::$nl . ' . . . ticket->qty: ' . $ticket->qty();
302
-            echo self::$nl . ' . . . ticket->sold: ' . $ticket->sold();
303
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
304
-            echo self::$nl . ' . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
305
-            echo self::$nl . ' . . . available: ' . $available;
301
+            echo self::$nl.' . . . ticket->qty: '.$ticket->qty();
302
+            echo self::$nl.' . . . ticket->sold: '.$ticket->sold();
303
+            echo self::$nl.' . . . ticket->reserved: '.$ticket->reserved();
304
+            echo self::$nl.' . . . ticket->qty(saleable): '.$ticket->qty('saleable');
305
+            echo self::$nl.' . . . available: '.$available;
306 306
         }
307 307
         if ($available < 1) {
308 308
             $this->_ticket_sold_out($ticket);
309 309
             return 0;
310 310
         }
311 311
         if (self::debug) {
312
-            echo self::$nl . ' . . . qty: ' . $qty;
312
+            echo self::$nl.' . . . qty: '.$qty;
313 313
         }
314 314
         if ($available < $qty) {
315 315
             $qty = $available;
316 316
             if (self::debug) {
317
-                echo self::$nl . ' . . . QTY ADJUSTED: ' . $qty;
317
+                echo self::$nl.' . . . QTY ADJUSTED: '.$qty;
318 318
             }
319 319
             $this->_ticket_quantity_decremented($ticket);
320 320
         }
@@ -335,9 +335,9 @@  discard block
 block discarded – undo
335 335
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
336 336
     {
337 337
         if (self::debug) {
338
-            echo self::$nl . self::$nl . ' . . . INCREASE RESERVED: ' . $quantity;
338
+            echo self::$nl.self::$nl.' . . . INCREASE RESERVED: '.$quantity;
339 339
         }
340
-        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'. __LINE__);
340
+        $ticket->increase_reserved($quantity, 'TicketSalesMonitor:'.__LINE__);
341 341
         return $ticket->save();
342 342
     }
343 343
 
@@ -352,12 +352,12 @@  discard block
 block discarded – undo
352 352
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
353 353
     {
354 354
         if (self::debug) {
355
-            echo self::$nl . ' . . . ticket->ID: ' . $ticket->ID();
356
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
355
+            echo self::$nl.' . . . ticket->ID: '.$ticket->ID();
356
+            echo self::$nl.' . . . ticket->reserved: '.$ticket->reserved();
357 357
         }
358
-        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'. __LINE__);
358
+        $ticket->decrease_reserved($quantity, true, 'TicketSalesMonitor:'.__LINE__);
359 359
         if (self::debug) {
360
-            echo self::$nl . ' . . . ticket->reserved: ' . $ticket->reserved();
360
+            echo self::$nl.' . . . ticket->reserved: '.$ticket->reserved();
361 361
         }
362 362
         return $ticket->save() ? 1 : 0;
363 363
     }
@@ -375,8 +375,8 @@  discard block
 block discarded – undo
375 375
     protected function _ticket_sold_out(EE_Ticket $ticket)
376 376
     {
377 377
         if (self::debug) {
378
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
379
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
378
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
379
+            echo self::$nl.' . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
380 380
         }
381 381
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
382 382
     }
@@ -394,8 +394,8 @@  discard block
 block discarded – undo
394 394
     protected function _ticket_quantity_decremented(EE_Ticket $ticket)
395 395
     {
396 396
         if (self::debug) {
397
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
398
-            echo self::$nl . ' . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
397
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
398
+            echo self::$nl.' . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
399 399
         }
400 400
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
401 401
     }
@@ -448,7 +448,7 @@  discard block
 block discarded – undo
448 448
         if ($ticket instanceof EE_Ticket) {
449 449
             $ticket->add_extra_meta(
450 450
                 EE_Ticket::META_KEY_TICKET_RESERVATIONS,
451
-                __LINE__ . ') ' . __METHOD__ . '()'
451
+                __LINE__.') '.__METHOD__.'()'
452 452
             );
453 453
             if ($quantity > 0) {
454 454
                 EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
     {
473 473
         $ticket->add_extra_meta(
474 474
             EE_Ticket::META_KEY_TICKET_RESERVATIONS,
475
-            __LINE__ . ') ' . __METHOD__ . '()'
475
+            __LINE__.') '.__METHOD__.'()'
476 476
         );
477 477
         EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
478 478
     }
@@ -509,18 +509,18 @@  discard block
 block discarded – undo
509 509
     protected function _post_notices()
510 510
     {
511 511
         if (self::debug) {
512
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
512
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
513 513
         }
514 514
         $refresh_msg    = '';
515 515
         $none_added_msg = '';
516 516
         if (defined('DOING_AJAX') && DOING_AJAX) {
517
-            $refresh_msg    = __(
517
+            $refresh_msg = __(
518 518
                 'Please refresh the page to view updated ticket quantities.',
519 519
                 'event_espresso'
520 520
             );
521 521
             $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
522 522
         }
523
-        if (! empty($this->sold_out_tickets)) {
523
+        if ( ! empty($this->sold_out_tickets)) {
524 524
             EE_Error::add_attention(
525 525
                 sprintf(
526 526
                     apply_filters(
@@ -543,7 +543,7 @@  discard block
 block discarded – undo
543 543
             // and reset the cart
544 544
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
545 545
         }
546
-        if (! empty($this->decremented_tickets)) {
546
+        if ( ! empty($this->decremented_tickets)) {
547 547
             EE_Error::add_attention(
548 548
                 sprintf(
549 549
                     apply_filters(
@@ -581,9 +581,9 @@  discard block
 block discarded – undo
581 581
     protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
582 582
     {
583 583
         if (self::debug) {
584
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
585
-            echo self::$nl . ' . transaction->ID: ' . $transaction->ID();
586
-            echo self::$nl . ' . TXN status_ID: ' . $transaction->status_ID();
584
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
585
+            echo self::$nl.' . transaction->ID: '.$transaction->ID();
586
+            echo self::$nl.' . TXN status_ID: '.$transaction->status_ID();
587 587
         }
588 588
         // check if 'finalize_registration' step has been completed...
589 589
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -595,13 +595,13 @@  discard block
 block discarded – undo
595 595
                 __LINE__,
596 596
                 array('finalized' => $finalized),
597 597
                 false,
598
-                'EE_Transaction: ' . $transaction->ID()
598
+                'EE_Transaction: '.$transaction->ID()
599 599
             );
600 600
         }
601 601
         // how many tickets were released
602 602
         $count = 0;
603 603
         if (self::debug) {
604
-            echo self::$nl . ' . . . TXN finalized: ' . $finalized;
604
+            echo self::$nl.' . . . TXN finalized: '.$finalized;
605 605
         }
606 606
         $release_tickets_with_TXN_status = array(
607 607
             EEM_Transaction::failed_status_code,
@@ -610,28 +610,28 @@  discard block
 block discarded – undo
610 610
         );
611 611
         $events = array();
612 612
         // if the session is getting cleared BEFORE the TXN has been finalized or the transaction is not completed
613
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
613
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
614 614
             // cancel any reserved tickets for registrations that were not approved
615 615
             $registrations = $transaction->registrations();
616 616
             if (self::debug) {
617
-                echo self::$nl . ' . . . # registrations: ' . count($registrations);
617
+                echo self::$nl.' . . . # registrations: '.count($registrations);
618 618
                 $reg    = reset($registrations);
619 619
                 $ticket = $reg->ticket();
620 620
                 if ($ticket instanceof EE_Ticket) {
621 621
                     $ticket->add_extra_meta(
622 622
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
623
-                        __LINE__ . ') Release All Tickets TXN:' . $transaction->ID()
623
+                        __LINE__.') Release All Tickets TXN:'.$transaction->ID()
624 624
                     );
625 625
                 }
626 626
             }
627
-            if (! empty($registrations)) {
627
+            if ( ! empty($registrations)) {
628 628
                 foreach ($registrations as $registration) {
629 629
                     if (
630 630
                         $registration instanceof EE_Registration
631 631
                         && $this->_release_reserved_ticket_for_registration($registration, $transaction)
632 632
                     ) {
633 633
                         $count++;
634
-                        $events[ $registration->event_ID() ] = $registration->event();
634
+                        $events[$registration->event_ID()] = $registration->event();
635 635
                     }
636 636
                 }
637 637
             }
@@ -662,10 +662,10 @@  discard block
 block discarded – undo
662 662
     ) {
663 663
         $STS_ID = $transaction->status_ID();
664 664
         if (self::debug) {
665
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
666
-            echo self::$nl . ' . . registration->ID: ' . $registration->ID();
667
-            echo self::$nl . ' . . registration->status_ID: ' . $registration->status_ID();
668
-            echo self::$nl . ' . . transaction->status_ID(): ' . $STS_ID;
665
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
666
+            echo self::$nl.' . . registration->ID: '.$registration->ID();
667
+            echo self::$nl.' . . registration->status_ID: '.$registration->status_ID();
668
+            echo self::$nl.' . . transaction->status_ID(): '.$STS_ID;
669 669
         }
670 670
         if (
671 671
             // release Tickets for Failed Transactions and Abandoned Transactions
@@ -678,12 +678,12 @@  discard block
 block discarded – undo
678 678
             )
679 679
         ) {
680 680
             if (self::debug) {
681
-                echo self::$nl . self::$nl . ' . . RELEASE RESERVED TICKET';
681
+                echo self::$nl.self::$nl.' . . RELEASE RESERVED TICKET';
682 682
                 $rsrvd = $registration->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true);
683
-                echo self::$nl . ' . . . registration HAS_RESERVED_TICKET_KEY: ';
683
+                echo self::$nl.' . . . registration HAS_RESERVED_TICKET_KEY: ';
684 684
                 var_dump($rsrvd);
685 685
             }
686
-            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'. __LINE__);
686
+            $registration->release_reserved_ticket(true, 'TicketSalesMonitor:'.__LINE__);
687 687
             return 1;
688 688
         }
689 689
         return 0;
@@ -709,7 +709,7 @@  discard block
 block discarded – undo
709 709
     public static function session_cart_reset(EE_Session $session)
710 710
     {
711 711
         if (self::debug) {
712
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
712
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
713 713
         }
714 714
         // first check of the session has a valid Checkout object
715 715
         $checkout = $session->checkout();
@@ -721,12 +721,12 @@  discard block
 block discarded – undo
721 721
         $cart = $session->cart();
722 722
         if ($cart instanceof EE_Cart) {
723 723
             if (self::debug) {
724
-                echo self::$nl . self::$nl . ' cart instance of EE_Cart: ';
724
+                echo self::$nl.self::$nl.' cart instance of EE_Cart: ';
725 725
             }
726 726
             EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart, $session);
727 727
         } else {
728 728
             if (self::debug) {
729
-                echo self::$nl . self::$nl . ' invalid EE_Cart: ';
729
+                echo self::$nl.self::$nl.' invalid EE_Cart: ';
730 730
                 var_export($cart, true);
731 731
             }
732 732
         }
@@ -748,7 +748,7 @@  discard block
 block discarded – undo
748 748
     protected function _session_cart_reset(EE_Cart $cart, EE_Session $session)
749 749
     {
750 750
         if (self::debug) {
751
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
751
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
752 752
         }
753 753
         EE_Registry::instance()->load_helper('Line_Item');
754 754
         $ticket_line_items = $cart->get_tickets();
@@ -757,28 +757,28 @@  discard block
 block discarded – undo
757 757
         }
758 758
         foreach ($ticket_line_items as $ticket_line_item) {
759 759
             if (self::debug) {
760
-                echo self::$nl . ' . ticket_line_item->ID(): ' . $ticket_line_item->ID();
760
+                echo self::$nl.' . ticket_line_item->ID(): '.$ticket_line_item->ID();
761 761
             }
762 762
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
763 763
                 if (self::debug) {
764
-                    echo self::$nl . ' . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
764
+                    echo self::$nl.' . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
765 765
                 }
766 766
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
767 767
                 if ($ticket instanceof EE_Ticket) {
768 768
                     if (self::debug) {
769
-                        echo self::$nl . ' . . ticket->ID(): ' . $ticket->ID();
770
-                        echo self::$nl . ' . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
769
+                        echo self::$nl.' . . ticket->ID(): '.$ticket->ID();
770
+                        echo self::$nl.' . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
771 771
                     }
772 772
                     $ticket->add_extra_meta(
773 773
                         EE_Ticket::META_KEY_TICKET_RESERVATIONS,
774
-                        __LINE__ . ') ' . __METHOD__ . '() SID = ' . $session->id()
774
+                        __LINE__.') '.__METHOD__.'() SID = '.$session->id()
775 775
                     );
776 776
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
777 777
                 }
778 778
             }
779 779
         }
780 780
         if (self::debug) {
781
-            echo self::$nl . self::$nl . ' RESET COMPLETED ';
781
+            echo self::$nl.self::$nl.' RESET COMPLETED ';
782 782
         }
783 783
     }
784 784
 
@@ -817,7 +817,7 @@  discard block
 block discarded – undo
817 817
     protected function _session_checkout_reset(EE_Checkout $checkout)
818 818
     {
819 819
         if (self::debug) {
820
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '() ';
820
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'() ';
821 821
         }
822 822
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
823 823
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -867,7 +867,7 @@  discard block
 block discarded – undo
867 867
                     __LINE__,
868 868
                     array($transaction),
869 869
                     false,
870
-                    'EE_Transaction: ' . $transaction->ID()
870
+                    'EE_Transaction: '.$transaction->ID()
871 871
                 );
872 872
             }
873 873
             return;
@@ -884,7 +884,7 @@  discard block
 block discarded – undo
884 884
                         __LINE__,
885 885
                         array($payment),
886 886
                         false,
887
-                        'EE_Transaction: ' . $transaction->ID()
887
+                        'EE_Transaction: '.$transaction->ID()
888 888
                     );
889 889
                 }
890 890
                 return;
@@ -944,7 +944,7 @@  discard block
 block discarded – undo
944 944
             }
945 945
             $total_line_item = $transaction->total_line_item();
946 946
             // $transaction_in_progress->line
947
-            if (! $total_line_item instanceof EE_Line_Item) {
947
+            if ( ! $total_line_item instanceof EE_Line_Item) {
948 948
                 throw new DomainException(
949 949
                     esc_html__(
950 950
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -1005,18 +1005,18 @@  discard block
 block discarded – undo
1005 1005
         $source
1006 1006
     ) {
1007 1007
         if (self::debug) {
1008
-            echo self::$nl . self::$nl . __LINE__ . ') ' . __METHOD__ . '()';
1008
+            echo self::$nl.self::$nl.__LINE__.') '.__METHOD__.'()';
1009 1009
         }
1010 1010
         $total_tickets_released = 0;
1011 1011
         $sold_out_events = array();
1012 1012
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
1013
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
1013
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
1014 1014
                 continue;
1015 1015
             }
1016 1016
             $reserved_qty = $ticket_with_reservations->reserved();
1017 1017
             if (self::debug) {
1018
-                echo self::$nl . ' . $ticket_with_reservations->ID(): ' . $ticket_with_reservations->ID();
1019
-                echo self::$nl . ' . $reserved_qty: ' . $reserved_qty;
1018
+                echo self::$nl.' . $ticket_with_reservations->ID(): '.$ticket_with_reservations->ID();
1019
+                echo self::$nl.' . $reserved_qty: '.$reserved_qty;
1020 1020
             }
1021 1021
             foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
1022 1022
                 if (
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
                     && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
1025 1025
                 ) {
1026 1026
                     if (self::debug) {
1027
-                        echo self::$nl . ' . $valid_reserved_ticket_line_item->quantity(): ' . $valid_reserved_ticket_line_item->quantity();
1027
+                        echo self::$nl.' . $valid_reserved_ticket_line_item->quantity(): '.$valid_reserved_ticket_line_item->quantity();
1028 1028
                     }
1029 1029
                     $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
1030 1030
                 }
@@ -1032,9 +1032,9 @@  discard block
 block discarded – undo
1032 1032
             if ($reserved_qty > 0) {
1033 1033
                 $ticket_with_reservations->add_extra_meta(
1034 1034
                     EE_Ticket::META_KEY_TICKET_RESERVATIONS,
1035
-                    __LINE__ . ') ' . $source . '()'
1035
+                    __LINE__.') '.$source.'()'
1036 1036
                 );
1037
-                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'. __LINE__);
1037
+                $ticket_with_reservations->decrease_reserved($reserved_qty, true, 'TicketSalesMonitor:'.__LINE__);
1038 1038
                 $ticket_with_reservations->save();
1039 1039
                 $total_tickets_released += $reserved_qty;
1040 1040
                 $event = $ticket_with_reservations->get_related_event();
@@ -1045,10 +1045,10 @@  discard block
 block discarded – undo
1045 1045
             }
1046 1046
         }
1047 1047
         if (self::debug) {
1048
-            echo self::$nl . ' . $total_tickets_released: ' . $total_tickets_released;
1048
+            echo self::$nl.' . $total_tickets_released: '.$total_tickets_released;
1049 1049
         }
1050 1050
         // double check whether sold out events should remain sold out after releasing tickets
1051
-        if($sold_out_events !== array()){
1051
+        if ($sold_out_events !== array()) {
1052 1052
             foreach ($sold_out_events as $sold_out_event) {
1053 1053
                 /** @var EE_Event $sold_out_event */
1054 1054
                 $sold_out_event->perform_sold_out_status_check();
@@ -1075,7 +1075,7 @@  discard block
 block discarded – undo
1075 1075
     {
1076 1076
        /** @type WPDB $wpdb */
1077 1077
         global $wpdb;
1078
-        if (! absint($timestamp)) {
1078
+        if ( ! absint($timestamp)) {
1079 1079
             /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
1080 1080
             $session_lifespan = LoaderFactory::getLoader()->getShared(
1081 1081
                 'EventEspresso\core\domain\values\session\SessionLifespan'
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
         }
1085 1085
          return $wpdb->query(
1086 1086
             $wpdb->prepare(
1087
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
1087
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
1088 1088
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
1089 1089
                 // use GMT time because that's what LIN_timestamps are in
1090 1090
                 date('Y-m-d H:i:s', $timestamp)
Please login to merge, or discard this patch.
core/domain/values/session/SessionLifespan.php 1 patch
Indentation   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -24,99 +24,99 @@
 block discarded – undo
24 24
 class SessionLifespan
25 25
 {
26 26
 
27
-    /**
28
-     * how long an EE session lasts in seconds
29
-     * default session lifespan of 1 hour (for not so instant IPNs)
30
-     *
31
-     * @var int $lifespan
32
-     */
33
-    private $lifespan;
34
-
35
-
36
-    /**
37
-     * SessionLifespan constructor.
38
-     *
39
-     * @param int $lifespan
40
-     * @throws DomainException
41
-     */
42
-    public function __construct($lifespan = 0)
43
-    {
44
-        $lifespan = absint($lifespan);
45
-        $lifespan = $lifespan > 0 ? $lifespan : (int) HOUR_IN_SECONDS;
46
-        $this->setLifespan($lifespan);
47
-    }
48
-
49
-
50
-    /**
51
-     * @param int $lifespan
52
-     * @throws DomainException
53
-     */
54
-    protected function setLifespan($lifespan)
55
-    {
56
-        if($lifespan < 60) {
57
-            throw new DomainException(
58
-                esc_html__(
59
-                    'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
60
-                    'event_espresso'
61
-                )
62
-            );
63
-
64
-        }
65
-        $this->lifespan = apply_filters(
66
-            'FHEE__EventEspresso_core_domain_values_session_SessionLifespan__setLifespan___lifespan',
67
-            // apply legacy filter for now but add doing it wrong notice in future
68
-            apply_filters(
69
-                'FHEE__EE_Session__construct___lifespan',
70
-                $lifespan
71
-            )
72
-        ) + 1;
73
-    }
74
-
75
-
76
-    /**
77
-     * @return int
78
-     */
79
-    public function inSeconds()
80
-    {
81
-        return $this->lifespan;
82
-    }
83
-
84
-
85
-    /**
86
-     * @param string $separator
87
-     * @return string
88
-     */
89
-    public function inHoursMinutesSeconds($separator = ':')
90
-    {
91
-        return sprintf(
92
-            '%02d%s%02d%s%02d',
93
-            floor($this->lifespan / 3600),
94
-            $separator,
95
-            ($this->lifespan / 60) % 60,
96
-            $separator,
97
-            $this->lifespan % 60
98
-        );
99
-    }
100
-
101
-
102
-    /**
103
-     * Returns a timestamp for when the session would expire based on this lifespan
104
-     *
105
-     * @param bool $utc If true, displays expiration in UTC
106
-     *                  If false, displays expiration in local time
107
-     * @return int
108
-     */
109
-    public function expiration($utc = true)
110
-    {
111
-        return (int) current_time('timestamp', $utc) - $this->lifespan;
112
-    }
113
-
114
-
115
-    /**
116
-     * @return string
117
-     */
118
-    public function __toString()
119
-    {
120
-        return (string) $this->inSeconds();
121
-    }
27
+	/**
28
+	 * how long an EE session lasts in seconds
29
+	 * default session lifespan of 1 hour (for not so instant IPNs)
30
+	 *
31
+	 * @var int $lifespan
32
+	 */
33
+	private $lifespan;
34
+
35
+
36
+	/**
37
+	 * SessionLifespan constructor.
38
+	 *
39
+	 * @param int $lifespan
40
+	 * @throws DomainException
41
+	 */
42
+	public function __construct($lifespan = 0)
43
+	{
44
+		$lifespan = absint($lifespan);
45
+		$lifespan = $lifespan > 0 ? $lifespan : (int) HOUR_IN_SECONDS;
46
+		$this->setLifespan($lifespan);
47
+	}
48
+
49
+
50
+	/**
51
+	 * @param int $lifespan
52
+	 * @throws DomainException
53
+	 */
54
+	protected function setLifespan($lifespan)
55
+	{
56
+		if($lifespan < 60) {
57
+			throw new DomainException(
58
+				esc_html__(
59
+					'The session lifespan needs to be at least 60 seconds, and even that is extremely short',
60
+					'event_espresso'
61
+				)
62
+			);
63
+
64
+		}
65
+		$this->lifespan = apply_filters(
66
+			'FHEE__EventEspresso_core_domain_values_session_SessionLifespan__setLifespan___lifespan',
67
+			// apply legacy filter for now but add doing it wrong notice in future
68
+			apply_filters(
69
+				'FHEE__EE_Session__construct___lifespan',
70
+				$lifespan
71
+			)
72
+		) + 1;
73
+	}
74
+
75
+
76
+	/**
77
+	 * @return int
78
+	 */
79
+	public function inSeconds()
80
+	{
81
+		return $this->lifespan;
82
+	}
83
+
84
+
85
+	/**
86
+	 * @param string $separator
87
+	 * @return string
88
+	 */
89
+	public function inHoursMinutesSeconds($separator = ':')
90
+	{
91
+		return sprintf(
92
+			'%02d%s%02d%s%02d',
93
+			floor($this->lifespan / 3600),
94
+			$separator,
95
+			($this->lifespan / 60) % 60,
96
+			$separator,
97
+			$this->lifespan % 60
98
+		);
99
+	}
100
+
101
+
102
+	/**
103
+	 * Returns a timestamp for when the session would expire based on this lifespan
104
+	 *
105
+	 * @param bool $utc If true, displays expiration in UTC
106
+	 *                  If false, displays expiration in local time
107
+	 * @return int
108
+	 */
109
+	public function expiration($utc = true)
110
+	{
111
+		return (int) current_time('timestamp', $utc) - $this->lifespan;
112
+	}
113
+
114
+
115
+	/**
116
+	 * @return string
117
+	 */
118
+	public function __toString()
119
+	{
120
+		return (string) $this->inSeconds();
121
+	}
122 122
 }
Please login to merge, or discard this patch.